OSDN Git Service

Move RecentsImpl task stack listener to background.
authorWinson Chung <winsonc@google.com>
Mon, 24 Apr 2017 19:23:47 +0000 (12:23 -0700)
committerWinson Chung <winsonc@google.com>
Mon, 24 Apr 2017 22:21:11 +0000 (15:21 -0700)
- In RecentsTaskLoader, synchronize on anything that might use the
  thumbnail cache
- In RecentsLoadPlan, remove synchronization when preloading/executing
  since that is done in the loader now
- In RecentsImpl, synchronize on anything that might use the dummy stack
  view

Bug: 37550083
Test: Launch Overview and some other tasks, ensure everything still works

Change-Id: I36d04566ebb04296f67a3233730c1dc5bc1569f4

packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java
packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java

index 143d934..7bc591f 100644 (file)
@@ -192,8 +192,9 @@ public class RecentsActivity extends Activity implements ViewTreeObserver.OnPreD
                         // and the old last stack active time, they were not visible and in the
                         // TaskStack so we don't need to remove any associated TaskViews but we do
                         // need to load the task id's from the system
-                        RecentsTaskLoadPlan loadPlan = Recents.getTaskLoader().createLoadPlan(ctx);
-                        loadPlan.preloadRawTasks(false /* includeFrontMostExcludedTask */);
+                        RecentsTaskLoader loader = Recents.getTaskLoader();
+                        RecentsTaskLoadPlan loadPlan = loader.createLoadPlan(ctx);
+                        loader.preloadRawTasks(loadPlan, false /* includeFrontMostExcludedTask */);
                         List<ActivityManager.RecentTaskInfo> tasks = loadPlan.getRawTasks();
                         for (int i = tasks.size() - 1; i >= 0; i--) {
                             ActivityManager.RecentTaskInfo task = tasks.get(i);
index 164138e..53a9eae 100644 (file)
@@ -108,36 +108,39 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener
      * task stacks and update recents accordingly.
      */
     class TaskStackListenerImpl extends TaskStackListener {
+
         @Override
-        public void onTaskStackChanged() {
+        public void onTaskStackChangedBackground() {
             // Preloads the next task
             RecentsConfiguration config = Recents.getConfiguration();
             if (config.svelteLevel == RecentsConfiguration.SVELTE_NONE) {
-                RecentsTaskLoader loader = Recents.getTaskLoader();
-                SystemServicesProxy ssp = Recents.getSystemServices();
-                ActivityManager.RunningTaskInfo runningTaskInfo = ssp.getRunningTask();
 
                 // Load the next task only if we aren't svelte
+                SystemServicesProxy ssp = Recents.getSystemServices();
+                ActivityManager.RunningTaskInfo runningTaskInfo = ssp.getRunningTask();
+                RecentsTaskLoader loader = Recents.getTaskLoader();
                 RecentsTaskLoadPlan plan = loader.createLoadPlan(mContext);
                 loader.preloadTasks(plan, -1, false /* includeFrontMostExcludedTask */);
-                RecentsTaskLoadPlan.Options launchOpts = new RecentsTaskLoadPlan.Options();
+
                 // This callback is made when a new activity is launched and the old one is paused
                 // so ignore the current activity and try and preload the thumbnail for the
                 // previous one.
-                if (runningTaskInfo != null) {
-                    launchOpts.runningTaskId = runningTaskInfo.id;
+                VisibilityReport visibilityReport;
+                synchronized (mDummyStackView) {
+                    mDummyStackView.setTasks(plan.getTaskStack(), false /* allowNotify */);
+                    updateDummyStackViewLayout(plan.getTaskStack(),
+                            getWindowRect(null /* windowRectOverride */));
+
+                    // Launched from app is always the worst case (in terms of how many
+                    // thumbnails/tasks visible)
+                    RecentsActivityLaunchState launchState = new RecentsActivityLaunchState();
+                    launchState.launchedFromApp = true;
+                    mDummyStackView.updateLayoutAlgorithm(true /* boundScroll */, launchState);
+                    visibilityReport = mDummyStackView.computeStackVisibilityReport();
                 }
-                mDummyStackView.setTasks(plan.getTaskStack(), false /* allowNotify */);
-                updateDummyStackViewLayout(plan.getTaskStack(),
-                        getWindowRect(null /* windowRectOverride */));
 
-                // Launched from app is always the worst case (in terms of how many thumbnails/tasks
-                // visible)
-                RecentsActivityLaunchState launchState = new RecentsActivityLaunchState();
-                launchState.launchedFromApp = true;
-                mDummyStackView.updateLayoutAlgorithm(true /* boundScroll */, launchState);
-
-                VisibilityReport visibilityReport = mDummyStackView.computeStackVisibilityReport();
+                RecentsTaskLoadPlan.Options launchOpts = new RecentsTaskLoadPlan.Options();
+                launchOpts.runningTaskId = runningTaskInfo != null ? runningTaskInfo.id : -1;
                 launchOpts.numVisibleTasks = visibilityReport.numVisibleTasks;
                 launchOpts.numVisibleTaskThumbnails = visibilityReport.numVisibleThumbnails;
                 launchOpts.onlyLoadForCache = true;
@@ -221,9 +224,10 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener
     }
 
     public void onConfigurationChanged() {
-        Resources res = mContext.getResources();
         reloadResources();
-        mDummyStackView.reloadOnConfigurationChange();
+        synchronized (mDummyStackView) {
+            mDummyStackView.reloadOnConfigurationChange();
+        }
     }
 
     /**
@@ -393,7 +397,6 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener
 
             RecentsTaskLoader loader = Recents.getTaskLoader();
             sInstanceLoadPlan = loader.createLoadPlan(mContext);
-            sInstanceLoadPlan.preloadRawTasks(!isHomeStackVisible.value);
             loader.preloadTasks(sInstanceLoadPlan, runningTask.id, !isHomeStackVisible.value);
             TaskStack stack = sInstanceLoadPlan.getTaskStack();
             if (stack.getTaskCount() > 0) {
@@ -633,16 +636,18 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener
         calculateWindowStableInsets(systemInsets, windowRect);
         windowRect.offsetTo(0, 0);
 
-        TaskStackLayoutAlgorithm stackLayout = mDummyStackView.getStackAlgorithm();
+        synchronized (mDummyStackView) {
+            TaskStackLayoutAlgorithm stackLayout = mDummyStackView.getStackAlgorithm();
 
-        // Rebind the header bar and draw it for the transition
-        stackLayout.setSystemInsets(systemInsets);
-        if (stack != null) {
-            stackLayout.getTaskStackBounds(displayRect, windowRect, systemInsets.top,
-                    systemInsets.left, systemInsets.right, mTaskStackBounds);
-            stackLayout.reset();
-            stackLayout.initialize(displayRect, windowRect, mTaskStackBounds,
-                    TaskStackLayoutAlgorithm.StackState.getStackStateForStack(stack));
+            // Rebind the header bar and draw it for the transition
+            stackLayout.setSystemInsets(systemInsets);
+            if (stack != null) {
+                stackLayout.getTaskStackBounds(displayRect, windowRect, systemInsets.top,
+                        systemInsets.left, systemInsets.right, mTaskStackBounds);
+                stackLayout.reset();
+                stackLayout.initialize(displayRect, windowRect, mTaskStackBounds,
+                        TaskStackLayoutAlgorithm.StackState.getStackStateForStack(stack));
+            }
         }
     }
 
@@ -663,47 +668,52 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener
      */
     private void updateHeaderBarLayout(TaskStack stack, Rect windowRectOverride) {
         Rect windowRect = getWindowRect(windowRectOverride);
-        updateDummyStackViewLayout(stack, windowRect);
-        if (stack != null) {
-            TaskStackLayoutAlgorithm stackLayout = mDummyStackView.getStackAlgorithm();
-            mDummyStackView.setTasks(stack, false /* allowNotifyStackChanges */);
-            // Get the width of a task view so that we know how wide to draw the header bar.
-            int taskViewWidth = 0;
-            if (mDummyStackView.useGridLayout()) {
-                TaskGridLayoutAlgorithm gridLayout = mDummyStackView.getGridAlgorithm();
-                gridLayout.initialize(windowRect);
-                taskViewWidth = (int) gridLayout.getTransform(0 /* taskIndex */,
-                        stack.getTaskCount(), new TaskViewTransform(), stackLayout).rect.width();
-            } else {
-                Rect taskViewBounds = stackLayout.getUntransformedTaskViewBounds();
-                if (!taskViewBounds.isEmpty()) {
-                    taskViewWidth = taskViewBounds.width();
+        int taskViewWidth = 0;
+        boolean useGridLayout = false;
+        synchronized (mDummyStackView) {
+            useGridLayout = mDummyStackView.useGridLayout();
+            updateDummyStackViewLayout(stack, windowRect);
+            if (stack != null) {
+                TaskStackLayoutAlgorithm stackLayout = mDummyStackView.getStackAlgorithm();
+                mDummyStackView.setTasks(stack, false /* allowNotifyStackChanges */);
+                // Get the width of a task view so that we know how wide to draw the header bar.
+                if (useGridLayout) {
+                    TaskGridLayoutAlgorithm gridLayout = mDummyStackView.getGridAlgorithm();
+                    gridLayout.initialize(windowRect);
+                    taskViewWidth = (int) gridLayout.getTransform(0 /* taskIndex */,
+                            stack.getTaskCount(), new TaskViewTransform(),
+                            stackLayout).rect.width();
+                } else {
+                    Rect taskViewBounds = stackLayout.getUntransformedTaskViewBounds();
+                    if (!taskViewBounds.isEmpty()) {
+                        taskViewWidth = taskViewBounds.width();
+                    }
                 }
             }
+        }
 
-            if (taskViewWidth > 0) {
-                synchronized (mHeaderBarLock) {
-                    if (mHeaderBar.getMeasuredWidth() != taskViewWidth ||
-                            mHeaderBar.getMeasuredHeight() != mTaskBarHeight) {
-                        if (mDummyStackView.useGridLayout()) {
-                            mHeaderBar.setShouldDarkenBackgroundColor(true);
-                            mHeaderBar.setNoUserInteractionState();
-                        }
-                        mHeaderBar.forceLayout();
-                        mHeaderBar.measure(
-                                MeasureSpec.makeMeasureSpec(taskViewWidth, MeasureSpec.EXACTLY),
-                                MeasureSpec.makeMeasureSpec(mTaskBarHeight, MeasureSpec.EXACTLY));
+        if (stack != null && taskViewWidth > 0) {
+            synchronized (mHeaderBarLock) {
+                if (mHeaderBar.getMeasuredWidth() != taskViewWidth ||
+                        mHeaderBar.getMeasuredHeight() != mTaskBarHeight) {
+                    if (useGridLayout) {
+                        mHeaderBar.setShouldDarkenBackgroundColor(true);
+                        mHeaderBar.setNoUserInteractionState();
                     }
-                    mHeaderBar.layout(0, 0, taskViewWidth, mTaskBarHeight);
+                    mHeaderBar.forceLayout();
+                    mHeaderBar.measure(
+                            MeasureSpec.makeMeasureSpec(taskViewWidth, MeasureSpec.EXACTLY),
+                            MeasureSpec.makeMeasureSpec(mTaskBarHeight, MeasureSpec.EXACTLY));
                 }
+                mHeaderBar.layout(0, 0, taskViewWidth, mTaskBarHeight);
+            }
 
-                // Update the transition bitmap to match the new header bar height
-                if (mThumbTransitionBitmapCache == null ||
-                        (mThumbTransitionBitmapCache.getWidth() != taskViewWidth) ||
-                        (mThumbTransitionBitmapCache.getHeight() != mTaskBarHeight)) {
-                    mThumbTransitionBitmapCache = Bitmap.createBitmap(taskViewWidth,
-                            mTaskBarHeight, Bitmap.Config.ARGB_8888);
-                }
+            // Update the transition bitmap to match the new header bar height
+            if (mThumbTransitionBitmapCache == null ||
+                    (mThumbTransitionBitmapCache.getWidth() != taskViewWidth) ||
+                    (mThumbTransitionBitmapCache.getHeight() != mTaskBarHeight)) {
+                mThumbTransitionBitmapCache = Bitmap.createBitmap(taskViewWidth,
+                        mTaskBarHeight, Bitmap.Config.ARGB_8888);
             }
         }
     }
@@ -764,16 +774,21 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener
      * Creates the activity options for an app->recents transition.
      */
     private ActivityOptions getThumbnailTransitionActivityOptions(
-            ActivityManager.RunningTaskInfo runningTask, TaskStackView stackView,
-                    Rect windowOverrideRect) {
+            ActivityManager.RunningTaskInfo runningTask, Rect windowOverrideRect) {
         if (runningTask != null && runningTask.stackId == FREEFORM_WORKSPACE_STACK_ID) {
             ArrayList<AppTransitionAnimationSpec> specs = new ArrayList<>();
-            ArrayList<Task> tasks = stackView.getStack().getStackTasks();
-            TaskStackLayoutAlgorithm stackLayout = stackView.getStackAlgorithm();
-            TaskStackViewScroller stackScroller = stackView.getScroller();
+            ArrayList<Task> tasks;
+            TaskStackLayoutAlgorithm stackLayout;
+            TaskStackViewScroller stackScroller;
 
-            stackView.updateLayoutAlgorithm(true /* boundScroll */);
-            stackView.updateToInitialState();
+            synchronized (mDummyStackView) {
+                tasks = mDummyStackView.getStack().getStackTasks();
+                stackLayout = mDummyStackView.getStackAlgorithm();
+                stackScroller = mDummyStackView.getScroller();
+
+                mDummyStackView.updateLayoutAlgorithm(true /* boundScroll */);
+                mDummyStackView.updateToInitialState();
+            }
 
             for (int i = tasks.size() - 1; i >= 0; i--) {
                 Task task = tasks.get(i);
@@ -795,7 +810,7 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener
         } else {
             // Update the destination rect
             Task toTask = new Task();
-            TaskViewTransform toTransform = getThumbnailTransitionTransform(stackView, toTask,
+            TaskViewTransform toTransform = getThumbnailTransitionTransform(mDummyStackView, toTask,
                     windowOverrideRect);
             Bitmap thumbnail = drawThumbnailTransitionBitmap(toTask, toTransform,
                             mThumbTransitionBitmapCache);
@@ -919,8 +934,10 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener
         updateHeaderBarLayout(stack, windowOverrideRect);
 
         // Prepare the dummy stack for the transition
-        TaskStackLayoutAlgorithm.VisibilityReport stackVr =
-                mDummyStackView.computeStackVisibilityReport();
+        TaskStackLayoutAlgorithm.VisibilityReport stackVr;
+        synchronized (mDummyStackView) {
+            stackVr = mDummyStackView.computeStackVisibilityReport();
+        }
 
         // Update the remaining launch state
         launchState.launchedNumVisibleTasks = stackVr.numVisibleTasks;
@@ -936,8 +953,7 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener
             opts = getUnknownTransitionActivityOptions();
         } else if (useThumbnailTransition) {
             // Try starting with a thumbnail transition
-            opts = getThumbnailTransitionActivityOptions(runningTask, mDummyStackView,
-                    windowOverrideRect);
+            opts = getThumbnailTransitionActivityOptions(runningTask, windowOverrideRect);
         } else {
             // If there is no thumbnail transition, but is launching from home into recents, then
             // use a quick home transition
index 2f12282..cd747cc 100644 (file)
@@ -149,6 +149,10 @@ public class SystemServicesProxy {
      * to reduce IPC calls from system services. These callbacks will be called on the main thread.
      */
     public abstract static class TaskStackListener {
+        /**
+         * NOTE: This call is made of the thread that the binder call comes in on.
+         */
+        public void onTaskStackChangedBackground() { }
         public void onTaskStackChanged() { }
         public void onTaskSnapshotChanged(int taskId, TaskSnapshot snapshot) { }
         public void onActivityPinned(String packageName) { }
@@ -187,8 +191,20 @@ public class SystemServicesProxy {
      * This simply passes callbacks to listeners through {@link H}.
      * */
     private android.app.TaskStackListener mTaskStackListener = new android.app.TaskStackListener() {
+
+        private final List<SystemServicesProxy.TaskStackListener> mTmpListeners = new ArrayList<>();
+
         @Override
         public void onTaskStackChanged() throws RemoteException {
+            // Call the task changed callback for the non-ui thread listeners first
+            synchronized (mTaskStackListeners) {
+                mTmpListeners.clear();
+                mTmpListeners.addAll(mTaskStackListeners);
+            }
+            for (int i = mTmpListeners.size() - 1; i >= 0; i--) {
+                mTmpListeners.get(i).onTaskStackChangedBackground();
+            }
+
             mHandler.removeMessages(H.ON_TASK_STACK_CHANGED);
             mHandler.sendEmptyMessage(H.ON_TASK_STACK_CHANGED);
         }
@@ -309,10 +325,7 @@ public class SystemServicesProxy {
      * Returns the single instance of the {@link SystemServicesProxy}.
      * This should only be called on the main thread.
      */
-    public static SystemServicesProxy getInstance(Context context) {
-        if (!Looper.getMainLooper().isCurrentThread()) {
-            throw new RuntimeException("Must be called on the UI thread");
-        }
+    public static synchronized SystemServicesProxy getInstance(Context context) {
         if (sSystemServicesProxy == null) {
             sSystemServicesProxy = new SystemServicesProxy(context);
         }
@@ -1136,13 +1149,15 @@ public class SystemServicesProxy {
     public void registerTaskStackListener(TaskStackListener listener) {
         if (mIam == null) return;
 
-        mTaskStackListeners.add(listener);
-        if (mTaskStackListeners.size() == 1) {
-            // Register mTaskStackListener to IActivityManager only once if needed.
-            try {
-                mIam.registerTaskStackListener(mTaskStackListener);
-            } catch (Exception e) {
-                Log.w(TAG, "Failed to call registerTaskStackListener", e);
+        synchronized (mTaskStackListeners) {
+            mTaskStackListeners.add(listener);
+            if (mTaskStackListeners.size() == 1) {
+                // Register mTaskStackListener to IActivityManager only once if needed.
+                try {
+                    mIam.registerTaskStackListener(mTaskStackListener);
+                } catch (Exception e) {
+                    Log.w(TAG, "Failed to call registerTaskStackListener", e);
+                }
             }
         }
     }
@@ -1245,74 +1260,76 @@ public class SystemServicesProxy {
 
         @Override
         public void handleMessage(Message msg) {
-            switch (msg.what) {
-                case ON_TASK_STACK_CHANGED: {
-                    for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) {
-                        mTaskStackListeners.get(i).onTaskStackChanged();
+            synchronized (mTaskStackListeners) {
+                switch (msg.what) {
+                    case ON_TASK_STACK_CHANGED: {
+                        for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) {
+                            mTaskStackListeners.get(i).onTaskStackChanged();
+                        }
+                        break;
                     }
-                    break;
-                }
-                case ON_TASK_SNAPSHOT_CHANGED: {
-                    for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) {
-                        mTaskStackListeners.get(i).onTaskSnapshotChanged(msg.arg1,
-                                (TaskSnapshot) msg.obj);
+                    case ON_TASK_SNAPSHOT_CHANGED: {
+                        for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) {
+                            mTaskStackListeners.get(i).onTaskSnapshotChanged(msg.arg1,
+                                    (TaskSnapshot) msg.obj);
+                        }
+                        break;
                     }
-                    break;
-                }
-                case ON_ACTIVITY_PINNED: {
-                    for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) {
-                        mTaskStackListeners.get(i).onActivityPinned((String) msg.obj);
+                    case ON_ACTIVITY_PINNED: {
+                        for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) {
+                            mTaskStackListeners.get(i).onActivityPinned((String) msg.obj);
+                        }
+                        break;
                     }
-                    break;
-                }
-                case ON_ACTIVITY_UNPINNED: {
-                    for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) {
-                        mTaskStackListeners.get(i).onActivityUnpinned();
+                    case ON_ACTIVITY_UNPINNED: {
+                        for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) {
+                            mTaskStackListeners.get(i).onActivityUnpinned();
+                        }
+                        break;
                     }
-                    break;
-                }
-                case ON_PINNED_ACTIVITY_RESTART_ATTEMPT: {
-                    for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) {
-                        mTaskStackListeners.get(i).onPinnedActivityRestartAttempt();
+                    case ON_PINNED_ACTIVITY_RESTART_ATTEMPT: {
+                        for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) {
+                            mTaskStackListeners.get(i).onPinnedActivityRestartAttempt();
+                        }
+                        break;
                     }
-                    break;
-                }
-                case ON_PINNED_STACK_ANIMATION_STARTED: {
-                    for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) {
-                        mTaskStackListeners.get(i).onPinnedStackAnimationStarted();
+                    case ON_PINNED_STACK_ANIMATION_STARTED: {
+                        for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) {
+                            mTaskStackListeners.get(i).onPinnedStackAnimationStarted();
+                        }
+                        break;
                     }
-                    break;
-                }
-                case ON_PINNED_STACK_ANIMATION_ENDED: {
-                    for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) {
-                        mTaskStackListeners.get(i).onPinnedStackAnimationEnded();
+                    case ON_PINNED_STACK_ANIMATION_ENDED: {
+                        for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) {
+                            mTaskStackListeners.get(i).onPinnedStackAnimationEnded();
+                        }
+                        break;
                     }
-                    break;
-                }
-                case ON_ACTIVITY_FORCED_RESIZABLE: {
-                    for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) {
-                        mTaskStackListeners.get(i).onActivityForcedResizable(
-                                (String) msg.obj, msg.arg1, msg.arg2);
+                    case ON_ACTIVITY_FORCED_RESIZABLE: {
+                        for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) {
+                            mTaskStackListeners.get(i).onActivityForcedResizable(
+                                    (String) msg.obj, msg.arg1, msg.arg2);
+                        }
+                        break;
                     }
-                    break;
-                }
-                case ON_ACTIVITY_DISMISSING_DOCKED_STACK: {
-                    for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) {
-                        mTaskStackListeners.get(i).onActivityDismissingDockedStack();
+                    case ON_ACTIVITY_DISMISSING_DOCKED_STACK: {
+                        for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) {
+                            mTaskStackListeners.get(i).onActivityDismissingDockedStack();
+                        }
+                        break;
                     }
-                    break;
-                }
-                case ON_ACTIVITY_LAUNCH_ON_SECONDARY_DISPLAY_FAILED: {
-                    for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) {
-                        mTaskStackListeners.get(i).onActivityLaunchOnSecondaryDisplayFailed();
+                    case ON_ACTIVITY_LAUNCH_ON_SECONDARY_DISPLAY_FAILED: {
+                        for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) {
+                            mTaskStackListeners.get(i).onActivityLaunchOnSecondaryDisplayFailed();
+                        }
+                        break;
                     }
-                    break;
-                }
-                case ON_TASK_PROFILE_LOCKED: {
-                    for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) {
-                        mTaskStackListeners.get(i).onTaskProfileLocked(msg.arg1, msg.arg2);
+                    case ON_TASK_PROFILE_LOCKED: {
+                        for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) {
+                            mTaskStackListeners.get(i).onTaskProfileLocked(msg.arg1, msg.arg2);
+                        }
+                        break;
                     }
-                    break;
                 }
             }
         }
index 78c71a1..4b53cd1 100644 (file)
@@ -103,8 +103,10 @@ public class RecentsTaskLoadPlan {
     /**
      * An optimization to preload the raw list of tasks. The raw tasks are saved in least-recent
      * to most-recent order.
+     *
+     * Note: Do not lock, callers should synchronize on the loader before making this call.
      */
-    public synchronized void preloadRawTasks(boolean includeFrontMostExcludedTask) {
+    void preloadRawTasks(boolean includeFrontMostExcludedTask) {
         int currentUserId = UserHandle.USER_CURRENT;
         updateCurrentQuietProfilesCache(currentUserId);
         SystemServicesProxy ssp = Recents.getSystemServices();
@@ -123,8 +125,11 @@ public class RecentsTaskLoadPlan {
      * The tasks will be ordered by:
      * - least-recent to most-recent stack tasks
      * - least-recent to most-recent freeform tasks
+     *
+     * Note: Do not lock, since this can be calling back to the loader, which separately also drives
+     * this call (callers should synchronize on the loader before making this call).
      */
-    public synchronized void preloadPlan(RecentsTaskLoader loader, int runningTaskId,
+    void preloadPlan(RecentsTaskLoader loader, int runningTaskId,
             boolean includeFrontMostExcludedTask) {
         Resources res = mContext.getResources();
         ArrayList<Task> allTasks = new ArrayList<>();
@@ -223,8 +228,11 @@ public class RecentsTaskLoadPlan {
 
     /**
      * Called to apply the actual loading based on the specified conditions.
+     *
+     * Note: Do not lock, since this can be calling back to the loader, which separately also drives
+     * this call (callers should synchronize on the loader before making this call).
      */
-    public synchronized void executePlan(Options opts, RecentsTaskLoader loader) {
+    void executePlan(Options opts, RecentsTaskLoader loader) {
         Resources res = mContext.getResources();
 
         // Iterate through each of the tasks and load them according to the load conditions.
index 5e78b61..6dde117 100644 (file)
@@ -31,6 +31,7 @@ import android.os.Looper;
 import android.util.Log;
 import android.util.LruCache;
 
+import com.android.internal.annotations.GuardedBy;
 import com.android.systemui.R;
 import com.android.systemui.recents.Recents;
 import com.android.systemui.recents.RecentsConfiguration;
@@ -243,7 +244,9 @@ public class RecentsTaskLoader {
     private final TaskResourceLoadQueue mLoadQueue;
     private final BackgroundTaskLoader mLoader;
     private final HighResThumbnailLoader mHighResThumbnailLoader;
+    @GuardedBy("this")
     private final TaskKeyStrongCache<ThumbnailData> mThumbnailCache = new TaskKeyStrongCache<>();
+    @GuardedBy("this")
     private final TaskKeyStrongCache<ThumbnailData> mTempCache = new TaskKeyStrongCache<>();
     private final int mMaxThumbnailCacheSize;
     private final int mMaxIconCacheSize;
@@ -318,14 +321,20 @@ public class RecentsTaskLoader {
         return plan;
     }
 
+    /** Preloads raw recents tasks using the specified plan to store the output. */
+    public synchronized void preloadRawTasks(RecentsTaskLoadPlan plan,
+            boolean includeFrontMostExcludedTask) {
+        plan.preloadRawTasks(includeFrontMostExcludedTask);
+    }
+
     /** Preloads recents tasks using the specified plan to store the output. */
-    public void preloadTasks(RecentsTaskLoadPlan plan, int runningTaskId,
+    public synchronized void preloadTasks(RecentsTaskLoadPlan plan, int runningTaskId,
             boolean includeFrontMostExcludedTask) {
         plan.preloadPlan(this, runningTaskId, includeFrontMostExcludedTask);
     }
 
     /** Begins loading the heavy task data according to the specified options. */
-    public void loadTasks(Context context, RecentsTaskLoadPlan plan,
+    public synchronized void loadTasks(Context context, RecentsTaskLoadPlan plan,
             RecentsTaskLoadPlan.Options opts) {
         if (opts == null) {
             throw new RuntimeException("Requires load options");
@@ -380,8 +389,7 @@ public class RecentsTaskLoader {
      * Handles signals from the system, trimming memory when requested to prevent us from running
      * out of memory.
      */
-    public void onTrimMemory(int level) {
-        RecentsConfiguration config = Recents.getConfiguration();
+    public synchronized void onTrimMemory(int level) {
         switch (level) {
             case ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN:
                 // Stop the loader immediately when the UI is no longer visible
@@ -516,7 +524,7 @@ public class RecentsTaskLoader {
     /**
      * Returns the cached thumbnail if the task key is not expired, updating the cache if it is.
      */
-    ThumbnailData getAndUpdateThumbnail(Task.TaskKey taskKey, boolean loadIfNotCached,
+    synchronized ThumbnailData getAndUpdateThumbnail(Task.TaskKey taskKey, boolean loadIfNotCached,
             boolean storeInCache) {
         SystemServicesProxy ssp = Recents.getSystemServices();
 
@@ -616,7 +624,7 @@ public class RecentsTaskLoader {
         }
     }
 
-    public void dump(String prefix, PrintWriter writer) {
+    public synchronized void dump(String prefix, PrintWriter writer) {
         String innerPrefix = prefix + "  ";
 
         writer.print(prefix); writer.println(TAG);