diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java index 9172897b48693..63f363e1cc149 100644 --- a/services/core/java/com/android/server/wm/Task.java +++ b/services/core/java/com/android/server/wm/Task.java @@ -425,8 +425,7 @@ class Task extends WindowContainer { int maxRecents; /** Only used for persistable tasks, otherwise 0. The last time this task was moved. Used for - * determining the order when restoring. Sign indicates whether last task movement was to front - * (positive) or back (negative). Absolute value indicates time. */ + * determining the order when restoring. */ long mLastTimeMoved; /** If original intent did not allow relinquishing task identity, save that information */ @@ -952,6 +951,11 @@ class Task extends WindowContainer { removeImmediately(); if (isLeafTask()) { mAtmService.getTaskChangeNotificationController().notifyTaskRemoved(mTaskId); + + final TaskDisplayArea taskDisplayArea = getDisplayArea(); + if (taskDisplayArea != null) { + taskDisplayArea.onLeafTaskRemoved(mTaskId); + } } } @@ -1525,15 +1529,14 @@ class Task extends WindowContainer { mStackSupervisor.updateTopResumedActivityIfNeeded(); } - void updateTaskMovement(boolean toFront) { + void updateTaskMovement(boolean toTop, int position) { + EventLogTags.writeWmTaskMoved(mTaskId, toTop ? 1 : 0, position); + final TaskDisplayArea taskDisplayArea = getDisplayArea(); + if (taskDisplayArea != null && isLeafTask()) { + taskDisplayArea.onLeafTaskMoved(this, toTop); + } if (isPersistable) { mLastTimeMoved = System.currentTimeMillis(); - // Sign is used to keep tasks sorted when persisted. Tasks sent to the bottom most - // recently will be most negative, tasks sent to the bottom before that will be less - // negative. Similarly for recent tasks moved to the top which will be most positive. - if (!toFront) { - mLastTimeMoved *= -1; - } } mRootWindowContainer.invalidateTaskLayers(); } @@ -3180,6 +3183,7 @@ class Task extends WindowContainer { @Override void positionChildAt(int position, WindowContainer child, boolean includingParents) { + final boolean toTop = position >= (mChildren.size() - 1); position = getAdjustedChildPosition(child, position); super.positionChildAt(position, child, includingParents); @@ -3187,10 +3191,9 @@ class Task extends WindowContainer { if (DEBUG_TASK_MOVEMENT) Slog.d(TAG_WM, "positionChildAt: child=" + child + " position=" + position + " parent=" + this); - final int toTop = position >= (mChildren.size() - 1) ? 1 : 0; final Task task = child.asTask(); if (task != null) { - EventLogTags.writeWmTaskMoved(task.mTaskId, toTop, position); + task.updateTaskMovement(toTop, position); } } @@ -6877,9 +6880,6 @@ class Task extends WindowContainer { if (!deferResume) { mRootWindowContainer.resumeFocusedStacksTopActivities(); } - EventLogTags.writeWmTaskToFront(tr.mUserId, tr.mTaskId); - mAtmService.getTaskChangeNotificationController() - .notifyTaskMovedToFront(tr.getTaskInfo()); } finally { mDisplayContent.continueUpdateImeTarget(); } @@ -7265,7 +7265,6 @@ class Task extends WindowContainer { Slog.i(TAG_WM, "positionChildAt: positioning task=" + task + " at " + position); } positionChildAt(position, task, includingParents); - task.updateTaskMovement(toTop); getDisplayContent().layoutAndAssignWindowLayersIfNeeded(); @@ -7402,7 +7401,6 @@ class Task extends WindowContainer { } positionChildAt(POSITION_TOP, child, true /* includingParents */); - child.updateTaskMovement(true); final DisplayContent displayContent = getDisplayContent(); displayContent.layoutAndAssignWindowLayersIfNeeded(); @@ -7415,7 +7413,6 @@ class Task extends WindowContainer { final Task nextFocusableStack = getDisplayArea().getNextFocusableStack( child.getRootTask(), true /* ignoreCurrent */); positionChildAtBottom(child, nextFocusableStack == null /* includingParents */); - child.updateTaskMovement(true); } @VisibleForTesting @@ -7440,12 +7437,6 @@ class Task extends WindowContainer { } final boolean isTop = getTopChild() == child; - - final Task task = child.asTask(); - if (task != null) { - task.updateTaskMovement(isTop); - } - if (isTop) { final DisplayContent displayContent = getDisplayContent(); displayContent.layoutAndAssignWindowLayersIfNeeded(); diff --git a/services/core/java/com/android/server/wm/TaskDisplayArea.java b/services/core/java/com/android/server/wm/TaskDisplayArea.java index 2b32e40f73326..890f56e50bacc 100644 --- a/services/core/java/com/android/server/wm/TaskDisplayArea.java +++ b/services/core/java/com/android/server/wm/TaskDisplayArea.java @@ -16,6 +16,7 @@ package com.android.server.wm; +import static android.app.ActivityTaskManager.INVALID_TASK_ID; import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME; import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS; import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD; @@ -152,6 +153,12 @@ final class TaskDisplayArea extends DisplayArea { */ private boolean mRemoved; + + /** + * The id of a leaf task that most recently being moved to front. + */ + private int mLastLeafTaskToFrontId; + TaskDisplayArea(DisplayContent displayContent, WindowManagerService service, String name, int displayAreaFeature) { super(service, Type.ANY, name, displayAreaFeature); @@ -382,7 +389,7 @@ final class TaskDisplayArea extends DisplayArea { this /* child */, true /* includingParents */); } - child.updateTaskMovement(moveToTop); + child.updateTaskMovement(moveToTop, targetPosition); mDisplayContent.layoutAndAssignWindowLayersIfNeeded(); @@ -405,6 +412,30 @@ final class TaskDisplayArea extends DisplayArea { } } + void onLeafTaskRemoved(int taskId) { + if (mLastLeafTaskToFrontId == taskId) { + mLastLeafTaskToFrontId = INVALID_TASK_ID; + } + } + + void onLeafTaskMoved(Task t, boolean toTop) { + if (!toTop) { + if (t.mTaskId == mLastLeafTaskToFrontId) { + mLastLeafTaskToFrontId = INVALID_TASK_ID; + } + return; + } + if (t.mTaskId == mLastLeafTaskToFrontId || t.topRunningActivityLocked() == null) { + return; + } + + mLastLeafTaskToFrontId = t.mTaskId; + EventLogTags.writeWmTaskToFront(t.mUserId, t.mTaskId); + // Notifying only when a leak task moved to front. Or the listeners would be notified + // couple times from the leaf task all the way up to the root task. + mAtmService.getTaskChangeNotificationController().notifyTaskMovedToFront(t.getTaskInfo()); + } + @Override boolean forAllTaskDisplayAreas(Function callback, boolean traverseTopToBottom) { diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskStackChangedListenerTest.java b/services/tests/wmtests/src/com/android/server/wm/TaskStackChangedListenerTest.java index ca3f815698e8e..fa2c942b0883d 100644 --- a/services/tests/wmtests/src/com/android/server/wm/TaskStackChangedListenerTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/TaskStackChangedListenerTest.java @@ -219,19 +219,13 @@ public class TaskStackChangedListenerTest { activity.setDetachedFromWindowLatch(onDetachedFromWindowLatch); final int id = activity.getTaskId(); - // Test for onTaskCreated. - waitForCallback(taskCreatedLaunchLatch); + // Test for onTaskCreated and onTaskMovedToFront + waitForCallback(taskMovedToFrontLatch); + assertEquals(0, taskCreatedLaunchLatch.getCount()); assertEquals(id, params[0]); ComponentName componentName = (ComponentName) params[1]; assertEquals(ActivityTaskChangeCallbacks.class.getName(), componentName.getClassName()); - // Test for onTaskMovedToFront. - assertEquals(1, taskMovedToFrontLatch.getCount()); - mService.moveTaskToFront(null, getInstrumentation().getContext().getPackageName(), id, 0, - null); - waitForCallback(taskMovedToFrontLatch); - assertEquals(activity.getTaskId(), params[0]); - // Test for onTaskRemovalStarted. assertEquals(1, taskRemovalStartedLatch.getCount()); assertEquals(1, taskRemovedLatch.getCount());