A Case Study of android P Version System Stability

Keywords: Java Android Lambda Programming

1. In the unlocked state, the interface sliding of the bright screen setting after the screen is extinguished is invalid.

Problem analysis:

(1) Can be reproduced in other application interfaces, non-application problems.

(2) Problem must be found, click action is effective but no animation effect, the interface does not refresh after sliding, but can confirm that the corresponding position has changed in the background, non-input system error.

(3) The interface is not refreshed after sliding, and the screenshot is the same as the current device display. The hardware problem of the display system is excluded, which is the software problem of the display system.

 

Questionnaire:

(1) Add log analysis according to the drawing process. Performance Traversals (Performance Measure, Performance Layout, Performance Draw), no problem here.

(2) Analyzing the performance Draw process by adding log analysis. PerfmDraw (ViewTreeObserver.draw()/drawSoftware) found that PerfmDraw was running normally and ViewTreeObserver.draw() was not called after a problem occurred.

(3) According to (2), continue to track down the problem and find out [surface.isValid()= true] in ViewRootImpl.draw(), and then trace the reason why surface is invalid.

(4) According to the code, the view RootImpl. setWindowStopped (true) will be called after each screen extinction, and then mSurface.release().

(5) Because there is no lock screen interface for the bright screen, there is no change in the interface when the screen is extinguished and it is not the first drawing, so the surface will not be re-enabled.

    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();
            }
        }
    }

Summary of the problems:

This problem is due to mSurface.release() after the screen is off, and no trigger to recreate enabled surface when the screen is on.

 

2. When there is a quickstep on the desktop, the desktop anr event occurs:

----- 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)

Problem analysis:

From the anr file, it is
(1) Thread "Binder: 10005_3" locked <0x0b405da7> (a com.android.quickstep.NormalizedIconLoader)
(2) The main thread "main" waiting to lock <0x0b405da7> (a com.android.quickstep.NormalizedIconLoader) held by thread 1

It can be confirmed that the ANR of UI threads is caused by the long running time of the thread "Binder:10005_3".

Further analysis of "Binder:10005_3" reveals that "Binder:10005_3" is caused by the long running time of LauncherAppState.getInstance. The reason for the long running time is that the thread uses the FutureTask property to block awakening of other threads, and what is the waiting thread? Let's look at LauncherAppState.getInstance's code:

    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;
    }

As you can see from the above function, Launcher App State is a typical singleton mode, and its creation is limited to UI threads, that is, only UI threads can create Launcher App State of this singleton mode, while the thread "Binder:10005_3" needs to be created using MainThreadExecutor to block the waiting main thread "main" creation. You can't continue running until you've built it (the Future class concurrent programming model is used here). The main thread "main" is waiting for the lock < 0x0b405da7> of the thread "Binder:10005_3" which has been locked all the time. This behavior also results in the blockage of the main thread "main" Loop process, which leads to the thread "Binder:10005_3" can never get the implementation of Launcher AppState.

The flow chart of the problem is as follows:

 

 

Posted by katuki on Mon, 09 Sep 2019 21:00:17 -0700