IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> Android 11系统稳定性 --亮屏解锁后闪现一个后台应用界面 -> 正文阅读

[移动开发]Android 11系统稳定性 --亮屏解锁后闪现一个后台应用界面

Android 11平台出现一个随机性问题,灭屏然后亮屏后解锁,界面会闪现一个后台应用的界面,只要出现以后除非清除此后台应用或者重启,否则就一直存在此问题。此问题为概率性问题,故我追踪了很长时间才找到此问题原因。

(1)问题原因:

从抓取的问题log来看,很容易就看出来如下:

Window{fd7df20 u0 com.google.android.gm/com.google.android.gm.welcome.WelcomeTourActivity EXITING}

WelcomeTourActivity的WindowState一直处于EXITING状态,也就是说WindowState的属性mAnimatingExit一直等于true。

(2)问题分析:

WindowState.mAnimatingExit赋值的位置有很多,为了能够定位问题点,我打开了WMS的所有log,然后复现此问题。此过程花费了很长时间精力,不过还是复现看了出现。通过对log的分析,定位在如下位置:

08-06 18:07:02.142999  1282  3643 V WindowManager: applyAnimation: win=WindowStateAnimator{1ee7238 com.google.android.gm/com.google.android.gm.welcome.WelcomeTourActivity}anim=0 attr=0x1 a=null transit=2 type=1 isEntrance=false Callers com.android.server.wm.WindowManagerService.tryStartExitingAnimation:2547 com.android.server.wm.WindowManagerService.relayoutWindow:2341 com.android.server.wm.Session.relayout:213

08-06 18:07:02.144712  1282  3643 V WindowManager: 1ST PASS Window{fd7df20 u0 com.google.android.gm/com.google.android.gm.welcome.WelcomeTourActivity EXITING}: gone=true mHaveFrame=true mLayoutAttached=false config reported=true

如上,通过分析原码把其问题定位到了如下函数中:

    private boolean tryStartExitingAnimation(WindowState win, WindowStateAnimator winAnimator,
            boolean focusMayChange) {
        // Try starting an animation; if there isn't one, we
        // can destroy the surface right away.
        int transit = WindowManagerPolicy.TRANSIT_EXIT;
        if (win.mAttrs.type == TYPE_APPLICATION_STARTING) {
            transit = WindowManagerPolicy.TRANSIT_PREVIEW_DONE;
        }
        if (win.isWinVisibleLw() && winAnimator.applyAnimationLocked(transit, false)) {
            focusMayChange = true;
            win.mAnimatingExit = true;
        } else if (win.isAnimating(TRANSITION | PARENTS)) {
            // Currently in a hide animation... turn this into
            // an exit.
            win.mAnimatingExit = true;
        } else if (win.getDisplayContent().mWallpaperController.isWallpaperTarget(win)) {
            // If the wallpaper is currently behind this
            // window, we need to change both of them inside
            // of a transaction to avoid artifacts.
            win.mAnimatingExit = true;
        } else {
            boolean stopped = win.mActivityRecord != null ? win.mActivityRecord.mAppStopped : true;
            // We set mDestroying=true so ActivityRecord#notifyAppStopped in-to destroy surfaces
            // will later actually destroy the surface if we do not do so here. Normally we leave
            // this to the exit animation.
            win.mDestroying = true;
            win.destroySurface(false, stopped);
        }
        if (mAccessibilityController != null) {
            mAccessibilityController.onWindowTransitionLocked(win, transit);
        }

        // When we start the exit animation we take the Surface from the client
        // so it will stop perturbing it. We need to likewise takeaway the SurfaceFlinger
        // side child surfaces, so they will remain preserved in their current state
        // (rather than be cleaned up immediately by the app code).
        SurfaceControl.openTransaction();
        winAnimator.detachChildren();
        SurfaceControl.closeTransaction();

        return focusMayChange;
    }

可以看到tryStartExitingAnimation函数中有多个地方在对WindowState.mAnimatingExit做赋值操作,这和初始的问题原因也有关系,但是找到此问题的正真原因还是要继续分析。

a.对源码分析得出,但是在普通WindowState此自身或者父容器处于isAnimating时会赋值mAnimatingExit=true,但是查看log如下,其自身WindowState和其父容器ActivityRecord刚刚退出了一个动画,且没有新的动画进入:

08-06 18:07:01.664929  1282  1303 V WindowManager: Starting animation on ActivityRecord{a125606 u0 com.google.android.gm/.welcome.WelcomeTourActivity t300}: type=1, anim=com.android.server.wm.LocalAnimationAdapter@4fdb030

08-06 18:07:02.124094  1282  1303 V ActivityTaskManager: Animation done in ActivityRecord{a125606 u0 com.google.android.gm/.welcome.WelcomeTourActivity t300}: reportedVisible=true okToDisplay=true okToAnimate=true startingDisplayed=false
08-06 18:07:02.124120  1282  1303 V WindowManager: onExitAnimationDone in Window{fd7df20 u0 com.google.android.gm/com.google.android.gm.welcome.WelcomeTourActivity}: exiting=false remove=false selfAnimating=false
08-06 18:07:02.124150  1282  1303 V WindowManager: Win Window{fd7df20 u0 com.google.android.gm/com.google.android.gm.welcome.WelcomeTourActivity}: isDrawn=true, animating=true

由以上log看到,ActivityRecord的动画刚运行完,同时WindowState的selfAnimating=false但是WindowState的?animating却为true,查看源码selfAnimating==isSelfAnimating,而animating==isAnimating,以下为其源码:

    /**
     * Internal method only to be used during {@link #getAnimatingContainer(int, int)}.DO NOT CALL
     * FROM OUTSIDE.
     */
    protected boolean isSelfAnimating(int flags, int typesToCheck) {
        if (mSurfaceAnimator.isAnimating()
                && (mSurfaceAnimator.getAnimationType() & typesToCheck) > 0) {
            return true;
        }
        if ((flags & TRANSITION) != 0 && isWaitingForTransitionStart()) {
            return true;
        }
        return false;
    }

    final boolean isAnimating(int flags, int typesToCheck) {
        return getAnimatingContainer(flags, typesToCheck) != null;
    }

    @Nullable
    WindowContainer getAnimatingContainer(int flags, int typesToCheck) {
        if (isSelfAnimating(flags, typesToCheck)) {
            return this;
        }
        if ((flags & PARENTS) != 0) {
            WindowContainer parent = getParent();
            while (parent != null) {
                if (parent.isSelfAnimating(flags, typesToCheck)) {
                    return parent;
                }
                parent = parent.getParent();
            }
        }
        if ((flags & CHILDREN) != 0) {
            for (int i = 0; i < mChildren.size(); ++i) {
                final WindowContainer wc = mChildren.get(i).getAnimatingContainer(
                        flags & ~PARENTS, typesToCheck);
                if (wc != null) {
                    return wc;
                }
            }
        }
        return null;
    }

由以下可以看到isSelfAnimating函数为自身的动画状态判断,而isAnimating为其父容器和子容器的递归的动画状态判断。同时可以确定的为其父容器ActivityRecord.isSelfAnimating=false,其自身的WindowState.isSelfAnimating=false,其自身WindowState没有子容器,那么只能去ActivityRecord的父容器Task看看了,重新查看log,出现以下信息:

08-06 18:07:01.936326  1282  1296 V WindowManager: Starting animation on Task{5ec3041 #300 visible=true type=standard mode=fullscreen translucent=true A=10142:com.google.android.gm U=0 StackId=300 sz=2}: type=8, anim=com.android.server.wm.RecentsAnimationController$TaskAnimationAdapter@98d4c24

08-06 18:07:01.938108  1282  1296 V WindowManager: Starting animation on Task{157ea58 #286 visible=true type=home mode=fullscreen translucent=false I=com.android.launcher3/com.android.searchlauncher.SearchLauncher U=0 StackId=283 sz=1}: type=8, anim=com.android.server.wm.RecentsAnimationController$TaskAnimationAdapter@634938d


08-06 18:07:02.655548  1282  3643 D WindowManager: onAnimationFinished(): controller=com.android.server.wm.RecentsAnimationController@7f9d03e reorderMode=1
08-06 18:07:02.655735  1282  3643 D WindowManager: cleanupAnimation(): Notify animation finished mPendingAnimations=2 reorderMode=1
08-06 18:07:02.657027  1282  3643 D WindowManager: onAnimationFinished(): targetStack=Task{ab75af1 #283 visible=false type=home mode=fullscreen translucent=true I=com.android.launcher3/com.android.searchlauncher.SearchLauncher U=0 StackId=283 sz=1} targetActivity=ActivityRecord{dd35a9d u0 com.android.launcher3/com.android.searchlauncher.SearchLauncher t286} mRestoreTargetBehindStack=Task{5ec3041 #300 visible=true type=standard mode=fullscreen translucent=true A=10142:com.google.android.gm U=0 StackId=300 sz=2}

以下可以看到在WindowManagerService.tryStartExitingAnimation运行时(08-06 18:07:02.142999),WelcomeTourActivity的Task正在进行RecentAnimation的动画,那么这里也就可以定位到问题原因为:

WelcomeTourActivity的Task在运行RecentAnimation的动画,而此时WelcomeTourActivity正处于Visible从true==>false的过程,致使运行到WMS.tryStartExitingAnimation时,WelcomeTourActivity的WindowState的属性mAnimatingExit==ture,但是由于WelcomeTourActivity的Task并没有正在的退出故而RecentsAnimationController是只Finish掉了SearchLauncher的动画,而对WelcomeTourActivity动画没有做Finish,WelcomeTourActivity为欢迎界面,在此之前已经消失,系统对WelcomeTourActivity视为非前台界面,故而就导致WelcomeTourActivity的WindowState一直处于EXITING状态。

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2021-08-15 15:43:16  更:2021-08-15 15:44:13 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 10:44:14-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码