android P版本 系統穩定性問題案例分析(一)

一、無鎖狀態下,滅屏後亮屏設置界面滑動無效。

問題分析:

(1)可在其他應用界面復現,非應用問題。

(2)問題必現,點擊動作有效但無動畫效果,滑動後界面不刷新但可確認對應位置在後臺已發生變化,非輸入系統錯誤。

(3)滑動後界面沒有刷新,截圖後與當前設備顯示相同,排除顯示系統的硬件問題,爲顯示系統的軟件問題。

 

問題排查:

(1)根據繪製流程添加log分析。performTraversals(performMeasure,performLayout,performDraw),此處沒有問題。

(2)分析performDraw流程添加log分析。performDraw(ViewTreeObserver.draw()/drawSoftware),發現performDraw正常運行,ViewTreeObserver.draw()在出現問題後不再調用。

(3)根據(2),繼續追查問題發現ViewRootImpl.draw()中[surface.isValid()=true],進而追蹤surface無效的原因。

(4)根據代碼發現每次滅屏後會調用ViewRootImpl.setWindowStopped(true)進而都會mSurface.release()。

(5)亮屏由於沒有鎖屏界面,滅屏時的界面沒有發生任何變化且非第一繪製,不會重新使能surface。

    void setWindowStopped(boolean stopped) {
        if (mStopped != stopped) {
            mStopped = stopped;
            final ThreadedRenderer renderer = mAttachInfo.mThreadedRenderer;
            if (renderer != null) {
                if (DEBUG_DRAW) Log.d(mTag, "WindowStopped on " + getTitle() + " set to " + mStopped);
                renderer.setStopped(mStopped);
            }
            if (!mStopped) {
                scheduleTraversals();
            } else {
                if (renderer != null) {
                    renderer.destroyHardwareResources(mView);
                }
            }

            for (int i = 0; i < mWindowStoppedCallbacks.size(); i++) {
                mWindowStoppedCallbacks.get(i).windowStopped(stopped);
            }

            if (mStopped) {
                mSurface.release();
            }
        }
    }

問題總結:

此問題是由於滅屏後mSurface.release(),而亮屏時沒有觸發重現使能surface而導致的。

 

二、桌面有手勢按鍵(quickstep)的時候,出現桌面anr事件:

----- pid 10005 at 2019-01-01 12:22:46 -----
Cmd line: com.android.launcher3

"main" prio=5 tid=1 Blocked
  | group="main" sCount=1 dsCount=0 flags=1 obj=0x75e5fab0 self=0x70f3a14c00
  | sysTid=10005 nice=-10 cgrp=default sched=0/0 handle=0x717a1b5548
  | state=S schedstat=( 481187776 24084236 354 ) utm=39 stm=8 core=1 HZ=100
  | stack=0x7ffbeae000-0x7ffbeb0000 stackSize=8MB
  | held mutexes=
  at com.android.quickstep.NormalizedIconLoader.getBitmapInfo(NormalizedIconLoader.java:-1)
  - waiting to lock <0x0b405da7> (a com.android.quickstep.NormalizedIconLoader) held by thread 10
  at com.android.quickstep.NormalizedIconLoader.getDefaultIcon(NormalizedIconLoader.java:58)
  - locked <0x0d1af254> (a android.util.SparseArray)
  at com.android.systemui.shared.recents.model.RecentsTaskLoader.loadTaskData(RecentsTaskLoader.java:185)
  at com.android.quickstep.views.RecentsView.loadVisibleTaskData(RecentsView.java:672)
  at com.android.quickstep.views.RecentsView.resetTaskVisuals(RecentsView.java:567)
  at com.android.quickstep.views.RecentsView.applyLoadPlan(RecentsView.java:543)
  at com.android.quickstep.views.RecentsView.lambda$w02bBzSWizaR4dIzSj9kQ73I7BA(RecentsView.java:-1)
  at com.android.quickstep.views.-$$Lambda$RecentsView$w02bBzSWizaR4dIzSj9kQ73I7BA.accept(lambda:-1)
  at com.android.quickstep.RecentsModel.lambda$loadTasks$1(RecentsModel.java:142)
  at com.android.quickstep.-$$Lambda$RecentsModel$rZAN1-eRHSYycmOWL-UzK9dzJ1Q.run(lambda:-1)
  at com.android.launcher3.util.LooperExecutor.execute(LooperExecutor.java:43)
  at com.android.quickstep.RecentsModel.loadTasks(RecentsModel.java:142)
  at com.android.quickstep.views.RecentsView.setCurrentTask(RecentsView.java:775)
  at com.android.quickstep.views.RecentsView.showTask(RecentsView.java:745)
  at com.android.quickstep.WindowTransformSwipeHandler.onLauncherStart(WindowTransformSwipeHandler.java:409)
  at com.android.quickstep.WindowTransformSwipeHandler.lambda$oTmdTx9KEnt4AhNDszi5oKfUOY4(WindowTransformSwipeHandler.java:-1)
  at com.android.quickstep.-$$Lambda$WindowTransformSwipeHandler$oTmdTx9KEnt4AhNDszi5oKfUOY4.onActivityStart(lambda:-1)
  at com.android.launcher3.BaseDraggingActivity.onStart(BaseDraggingActivity.java:235)
  at com.android.launcher3.Launcher.onStart(Launcher.java:848)
  at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1391)
  at android.app.Activity.performStart(Activity.java:7157)
  at android.app.ActivityThread.handleStartActivity(ActivityThread.java:2968)
  at android.app.servertransaction.TransactionExecutor.performLifecycleSequence(TransactionExecutor.java:180)
  at android.app.servertransaction.TransactionExecutor.cycleToPath(TransactionExecutor.java:165)
  at android.app.servertransaction.TransactionExecutor.executeLifecycleState(TransactionExecutor.java:142)
  at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:70)
  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1836)
  at android.os.Handler.dispatchMessage(Handler.java:106)
  at android.os.Looper.loop(Looper.java:193)
  at android.app.ActivityThread.main(ActivityThread.java:6702)
  at java.lang.reflect.Method.invoke(Native method)
  at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:911)


"Binder:10005_3" prio=5 tid=10 Waiting
  | group="main" sCount=1 dsCount=0 flags=1 obj=0x12e04f78 self=0x70ed23c000
  | sysTid=10018 nice=0 cgrp=default sched=0/0 handle=0x70debee4f0
  | state=S schedstat=( 51705932 1946846 88 ) utm=2 stm=2 core=2 HZ=100
  | stack=0x70deaf3000-0x70deaf5000 stackSize=1009KB
  | held mutexes=
  at java.lang.Object.wait(Native method)
  - waiting on <0x095edfc0> (a java.lang.Object)
  at java.lang.Thread.parkFor$(Thread.java:2137)
  - locked <0x095edfc0> (a java.lang.Object)
  at sun.misc.Unsafe.park(Unsafe.java:358)
  at java.util.concurrent.locks.LockSupport.park(LockSupport.java:190)
  at java.util.concurrent.FutureTask.awaitDone(FutureTask.java:450)
  at java.util.concurrent.FutureTask.get(FutureTask.java:192)
  at com.android.launcher3.LauncherAppState.getInstance(LauncherAppState.java:66)
  at com.android.launcher3.LauncherAppState.getIDP(LauncherAppState.java:174)
  at com.android.launcher3.graphics.LauncherIcons.<init>(LauncherIcons.java:133)
  at com.android.launcher3.graphics.LauncherIcons.obtain(LauncherIcons.java:91)
  at com.android.quickstep.NormalizedIconLoader.getBitmapInfo(NormalizedIconLoader.java:76)
  - locked <0x0b405da7> (a com.android.quickstep.NormalizedIconLoader)
  at com.android.quickstep.NormalizedIconLoader.getBadgedActivityIcon(NormalizedIconLoader.java:88)
  at com.android.systemui.shared.recents.model.IconLoader.createNewIconForTask(IconLoader.java:134)
  at com.android.systemui.shared.recents.model.IconLoader.getAndInvalidateIfModified(IconLoader.java:94)
  at com.android.systemui.shared.recents.model.RecentsTaskLoader.getAndUpdateActivityIcon(RecentsTaskLoader.java:325)
  at com.android.systemui.shared.recents.model.RecentsTaskLoadPlan.executePlan(RecentsTaskLoadPlan.java:182)
  at com.android.systemui.shared.recents.model.RecentsTaskLoader.loadTasks(RecentsTaskLoader.java:173)
  - locked <0x0411f4f9> (a com.android.quickstep.RecentsModel$1)
  at com.android.quickstep.RecentsModel.onTaskStackChangedBackground(RecentsModel.java:214)
  at com.android.systemui.shared.system.TaskStackChangeListeners.onTaskStackChanged(TaskStackChangeListeners.java:79)
  at android.app.ITaskStackListener$Stub.onTransact(ITaskStackListener.java:50)
  at android.os.Binder.execTransact(Binder.java:731)

問題分析:

從anr文件上來看是
(1)線程"Binder:10005_3" locked <0x0b405da7> (a com.android.quickstep.NormalizedIconLoader)
(2)主線程"main" waiting to lock <0x0b405da7> (a com.android.quickstep.NormalizedIconLoader) held by thread 1

那麼可以確認是由於線程"Binder:10005_3"運行時間過長而導致的UI線程出現ANR的。

進一步分析"Binder:10005_3"發現,"Binder:10005_3"是在運行LauncherAppState.getInstance耗時太長造成的,而耗時太長的原因是由於線程使用FutureTask屬性在阻塞等待其他線程的喚醒,而等待的線程是那個呢?我們看下LauncherAppState.getInstance的代碼:

    public static LauncherAppState getInstance(final Context context) {
        if (INSTANCE == null) {
            if (Looper.myLooper() == Looper.getMainLooper()) {
                INSTANCE = new LauncherAppState(context.getApplicationContext());
            } else {
                try {
                    return new MainThreadExecutor().submit(new Callable<LauncherAppState>() {
                        @Override
                        public LauncherAppState call() throws Exception {
                            return LauncherAppState.getInstance(context);
                        }
                    }).get();
                } catch (InterruptedException|ExecutionException e) {
                    throw new RuntimeException(e);
                }
            }
        }
        return INSTANCE;
    }

從上面函數可以看到LauncherAppState是一個典型的單例模式,而它的創建被限制在了UI線程中,也就是說只有UI線程才能創建這個單例模式的LauncherAppState,而線程"Binder:10005_3"創建時需要用到MainThreadExecutor去阻塞的等待主線程"main"創建完成之後才能繼續運行(此處使用了Future類併發編程模型)。而主線程"main"此時卻在等待着線程"Binder:10005_3"一直locked的鎖 <0x0b405da7>,而此行爲也導致了主線程"main"的Loop流程阻塞,進而導致線程"Binder:10005_3"永遠無法拿到LauncherAppState的實現。

問題流程圖如下:

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章