diff options
author | 2022-11-03 14:13:35 +0000 | |
---|---|---|
committer | 2022-11-03 14:13:35 +0000 | |
commit | 66457f5e2033e1ce5069bf89cdf84e24e5bc32fe (patch) | |
tree | 495625f8a51d28d3736d952cb657f2afa2a32751 | |
parent | a76cb1859738a3f2b70345144fcc6cc639513161 (diff) | |
parent | a1df4706c18b6d0b871091ab5f518a803de1afde (diff) |
Merge "Sort running task by focus and visibility" into stage-aosp-master
-rw-r--r-- | services/core/java/com/android/server/wm/RunningTasks.java | 111 | ||||
-rw-r--r-- | services/tests/wmtests/src/com/android/server/wm/RunningTasksTest.java | 103 |
2 files changed, 108 insertions, 106 deletions
diff --git a/services/core/java/com/android/server/wm/RunningTasks.java b/services/core/java/com/android/server/wm/RunningTasks.java index 120fec0fe0e6..33f019e0c9fb 100644 --- a/services/core/java/com/android/server/wm/RunningTasks.java +++ b/services/core/java/com/android/server/wm/RunningTasks.java @@ -20,16 +20,15 @@ import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME; import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS; import android.app.ActivityManager.RunningTaskInfo; +import android.os.SystemClock; import android.os.UserHandle; import android.util.ArraySet; import com.android.internal.util.function.pooled.PooledConsumer; import com.android.internal.util.function.pooled.PooledLambda; -import java.util.Comparator; -import java.util.Iterator; +import java.util.ArrayList; import java.util.List; -import java.util.TreeSet; /** * Class for resolving the set of running tasks in the system. @@ -41,15 +40,13 @@ class RunningTasks { static final int FLAG_CROSS_USERS = 1 << 2; static final int FLAG_KEEP_INTENT_EXTRA = 1 << 3; - // Comparator to sort by last active time (descending) - private static final Comparator<Task> LAST_ACTIVE_TIME_COMPARATOR = - (o1, o2) -> { - return o1.lastActiveTime == o2.lastActiveTime - ? Integer.signum(o2.mTaskId - o1.mTaskId) : - Long.signum(o2.lastActiveTime - o1.lastActiveTime); - }; - - private final TreeSet<Task> mTmpSortedSet = new TreeSet<>(LAST_ACTIVE_TIME_COMPARATOR); + // Tasks are sorted in order {focusedVisibleTasks, visibleTasks, invisibleTasks}. + private final ArrayList<Task> mTmpSortedTasks = new ArrayList<>(); + // mTmpVisibleTasks, mTmpInvisibleTasks and mTmpFocusedTasks are sorted from top + // to bottom. + private final ArrayList<Task> mTmpVisibleTasks = new ArrayList<>(); + private final ArrayList<Task> mTmpInvisibleTasks = new ArrayList<>(); + private final ArrayList<Task> mTmpFocusedTasks = new ArrayList<>(); private int mCallingUid; private int mUserId; @@ -67,8 +64,6 @@ class RunningTasks { return; } - // Gather all of the tasks across all of the tasks, and add them to the sorted set - mTmpSortedSet.clear(); mCallingUid = callingUid; mUserId = UserHandle.getUserId(callingUid); mCrossUser = (flags & FLAG_CROSS_USERS) == FLAG_CROSS_USERS; @@ -79,22 +74,67 @@ class RunningTasks { mRecentTasks = recentTasks; mKeepIntentExtra = (flags & FLAG_KEEP_INTENT_EXTRA) == FLAG_KEEP_INTENT_EXTRA; - final PooledConsumer c = PooledLambda.obtainConsumer(RunningTasks::processTask, this, - PooledLambda.__(Task.class)); - root.forAllLeafTasks(c, false); - c.recycle(); + if (root instanceof RootWindowContainer) { + ((RootWindowContainer) root).forAllDisplays(dc -> { + final Task focusedTask = dc.mFocusedApp != null ? dc.mFocusedApp.getTask() : null; + if (focusedTask != null) { + mTmpFocusedTasks.add(focusedTask); + } + processTaskInWindowContainer(dc); + }); + } else { + final DisplayContent dc = root.getDisplayContent(); + final Task focusedTask = dc != null + ? (dc.mFocusedApp != null ? dc.mFocusedApp.getTask() : null) + : null; + // May not be include focusedTask if root is DisplayArea. + final boolean rootContainsFocusedTask = focusedTask != null + && focusedTask.isDescendantOf(root); + if (rootContainsFocusedTask) { + mTmpFocusedTasks.add(focusedTask); + } + processTaskInWindowContainer(root); + } - // Take the first {@param maxNum} tasks and create running task infos for them - final Iterator<Task> iter = mTmpSortedSet.iterator(); - while (iter.hasNext()) { - if (maxNum == 0) { - break; + final int visibleTaskCount = mTmpVisibleTasks.size(); + for (int i = 0; i < mTmpFocusedTasks.size(); i++) { + final Task focusedTask = mTmpFocusedTasks.get(i); + final boolean containsFocusedTask = mTmpVisibleTasks.remove(focusedTask); + if (containsFocusedTask) { + // Put the visible focused task at the first position. + mTmpSortedTasks.add(focusedTask); } + } + if (!mTmpVisibleTasks.isEmpty()) { + mTmpSortedTasks.addAll(mTmpVisibleTasks); + } + if (!mTmpInvisibleTasks.isEmpty()) { + mTmpSortedTasks.addAll(mTmpInvisibleTasks); + } - final Task task = iter.next(); - list.add(createRunningTaskInfo(task)); - maxNum--; + // Take the first {@param maxNum} tasks and create running task infos for them + final int size = Math.min(maxNum, mTmpSortedTasks.size()); + final long now = SystemClock.elapsedRealtime(); + for (int i = 0; i < size; i++) { + final Task task = mTmpSortedTasks.get(i); + // Override the last active to current time for the visible tasks because the visible + // tasks can be considered to be currently active, the values are descending as + // the item order. + final long visibleActiveTime = i < visibleTaskCount ? now + size - i : -1; + list.add(createRunningTaskInfo(task, visibleActiveTime)); } + + mTmpFocusedTasks.clear(); + mTmpVisibleTasks.clear(); + mTmpInvisibleTasks.clear(); + mTmpSortedTasks.clear(); + } + + private void processTaskInWindowContainer(WindowContainer wc) { + final PooledConsumer c = PooledLambda.obtainConsumer(RunningTasks::processTask, this, + PooledLambda.__(Task.class)); + wc.forAllLeafTasks(c, true); + c.recycle(); } private void processTask(Task task) { @@ -121,25 +161,20 @@ class RunningTasks { // home & recent tasks return; } - if (task.isVisible()) { - // For the visible task, update the last active time so that it can be used to determine - // the order of the tasks (it may not be set for newly created tasks) - task.touchActiveTime(); - if (!task.isFocused()) { - // TreeSet doesn't allow the same value and make sure this task is lower than the - // focused one. - task.lastActiveTime -= mTmpSortedSet.size(); - } + mTmpVisibleTasks.add(task); + } else { + mTmpInvisibleTasks.add(task); } - - mTmpSortedSet.add(task); } /** Constructs a {@link RunningTaskInfo} from a given {@param task}. */ - private RunningTaskInfo createRunningTaskInfo(Task task) { + private RunningTaskInfo createRunningTaskInfo(Task task, long visibleActiveTime) { final RunningTaskInfo rti = new RunningTaskInfo(); task.fillTaskInfo(rti, !mKeepIntentExtra); + if (visibleActiveTime > 0) { + rti.lastActiveTime = visibleActiveTime; + } // Fill in some deprecated values rti.id = rti.taskId; return rti; diff --git a/services/tests/wmtests/src/com/android/server/wm/RunningTasksTest.java b/services/tests/wmtests/src/com/android/server/wm/RunningTasksTest.java index b1acae20afb0..eab2e156e9aa 100644 --- a/services/tests/wmtests/src/com/android/server/wm/RunningTasksTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/RunningTasksTest.java @@ -42,7 +42,6 @@ import org.junit.Test; import org.junit.runner.RunWith; import java.util.ArrayList; -import java.util.List; /** * Build/Install/Run: @@ -66,55 +65,6 @@ public class RunningTasksTest extends WindowTestsBase { } @Test - public void testCollectTasksByLastActiveTime() { - // Create a number of stacks with tasks (of incrementing active time) - final ArrayList<DisplayContent> displays = new ArrayList<>(); - final DisplayContent display = new TestDisplayContent.Builder(mAtm, 1000, 2500).build(); - displays.add(display); - - final int numStacks = 2; - for (int stackIndex = 0; stackIndex < numStacks; stackIndex++) { - final Task stack = new TaskBuilder(mSupervisor) - .setDisplay(display) - .setOnTop(false) - .build(); - } - - final int numTasks = 10; - int activeTime = 0; - final List<Task> rootTasks = new ArrayList<>(); - display.getDefaultTaskDisplayArea().forAllRootTasks(task -> { - rootTasks.add(task); - }, false /* traverseTopToBottom */); - for (int i = 0; i < numTasks; i++) { - final Task task = - createTask(rootTasks.get(i % numStacks), ".Task" + i, i, activeTime++, null); - doReturn(false).when(task).isVisible(); - } - - // Ensure that the latest tasks were returned in order of decreasing last active time, - // collected from all tasks across all the stacks - final int numFetchTasks = 5; - ArrayList<RunningTaskInfo> tasks = new ArrayList<>(); - mRunningTasks.getTasks(5, tasks, FLAG_ALLOWED | FLAG_CROSS_USERS, - mAtm.getRecentTasks(), mRootWindowContainer, -1 /* callingUid */, PROFILE_IDS); - assertThat(tasks).hasSize(numFetchTasks); - for (int i = 0; i < numFetchTasks; i++) { - assertEquals(numTasks - i - 1, tasks.get(i).id); - } - - // Ensure that requesting more than the total number of tasks only returns the subset - // and does not crash - tasks.clear(); - mRunningTasks.getTasks(100, tasks, FLAG_ALLOWED | FLAG_CROSS_USERS, - mAtm.getRecentTasks(), mRootWindowContainer, -1 /* callingUid */, PROFILE_IDS); - assertThat(tasks).hasSize(numTasks); - for (int i = 0; i < numTasks; i++) { - assertEquals(numTasks - i - 1, tasks.get(i).id); - } - } - - @Test public void testTaskInfo_expectNoExtrasByDefault() { final DisplayContent display = new TestDisplayContent.Builder(mAtm, 1000, 2500).build(); final int numTasks = 10; @@ -125,7 +75,7 @@ public class RunningTasksTest extends WindowTestsBase { .build(); final Bundle data = new Bundle(); data.putInt("key", 100); - createTask(stack, ".Task" + i, i, i, data); + createTask(stack, ".Task" + i, i, data); } final int numFetchTasks = 5; @@ -150,7 +100,7 @@ public class RunningTasksTest extends WindowTestsBase { .build(); final Bundle data = new Bundle(); data.putInt("key", 100); - createTask(stack, ".Task" + i, i, i, data); + createTask(stack, ".Task" + i, i, data); } final int numFetchTasks = 5; @@ -167,46 +117,63 @@ public class RunningTasksTest extends WindowTestsBase { } @Test - public void testUpdateLastActiveTimeOfVisibleTasks() { + public void testGetTasksSortByFocusAndVisibility() { final DisplayContent display = new TestDisplayContent.Builder(mAtm, 1000, 2500).build(); + final Task stack = new TaskBuilder(mSupervisor) + .setDisplay(display) + .setOnTop(true) + .build(); + final int numTasks = 10; final ArrayList<Task> tasks = new ArrayList<>(); for (int i = 0; i < numTasks; i++) { - final Task task = createTask(null, ".Task" + i, i, i, null); + final Task task = createTask(stack, ".Task" + i, i, null); doReturn(false).when(task).isVisible(); tasks.add(task); } - final Task visibleTask = tasks.get(0); - doReturn(true).when(visibleTask).isVisible(); - - final Task focusedTask = tasks.get(1); + final Task focusedTask = tasks.get(numTasks - 1); doReturn(true).when(focusedTask).isVisible(); - doReturn(true).when(focusedTask).isFocused(); + display.mFocusedApp = focusedTask.getTopNonFinishingActivity(); + + final Task visibleTaskTop = tasks.get(numTasks - 2); + doReturn(true).when(visibleTaskTop).isVisible(); - // Ensure that the last active time of visible tasks were updated while the focused one had - // the largest last active time. + final Task visibleTaskBottom = tasks.get(numTasks - 3); + doReturn(true).when(visibleTaskBottom).isVisible(); + + // Ensure that the focused Task is on top, visible tasks below, then invisible tasks. final int numFetchTasks = 5; final ArrayList<RunningTaskInfo> fetchTasks = new ArrayList<>(); mRunningTasks.getTasks(numFetchTasks, fetchTasks, FLAG_ALLOWED | FLAG_CROSS_USERS | FLAG_KEEP_INTENT_EXTRA, mAtm.getRecentTasks(), mRootWindowContainer, -1 /* callingUid */, PROFILE_IDS); assertThat(fetchTasks).hasSize(numFetchTasks); - assertEquals(fetchTasks.get(0).id, focusedTask.mTaskId); - assertEquals(fetchTasks.get(1).id, visibleTask.mTaskId); + for (int i = 0; i < numFetchTasks; i++) { + assertEquals(numTasks - i - 1, fetchTasks.get(i).id); + } + + // Ensure that requesting more than the total number of tasks only returns the subset + // and does not crash + fetchTasks.clear(); + mRunningTasks.getTasks(100, fetchTasks, + FLAG_ALLOWED | FLAG_CROSS_USERS | FLAG_KEEP_INTENT_EXTRA, + mAtm.getRecentTasks(), mRootWindowContainer, -1 /* callingUid */, PROFILE_IDS); + assertThat(fetchTasks).hasSize(numTasks); + for (int i = 0; i < numTasks; i++) { + assertEquals(numTasks - i - 1, fetchTasks.get(i).id); + } } /** - * Create a task with a single activity in it, with the given last active time. + * Create a task with a single activity in it. */ - private Task createTask(Task stack, String className, int taskId, - int lastActiveTime, Bundle extras) { + private Task createTask(Task stack, String className, int taskId, Bundle extras) { final Task task = new TaskBuilder(mAtm.mTaskSupervisor) .setComponent(new ComponentName(mContext.getPackageName(), className)) .setTaskId(taskId) .setParentTaskFragment(stack) .build(); - task.lastActiveTime = lastActiveTime; final ActivityRecord activity = new ActivityBuilder(mAtm) .setTask(task) .setComponent(new ComponentName(mContext.getPackageName(), ".TaskActivity")) @@ -227,7 +194,7 @@ public class RunningTasksTest extends WindowTestsBase { .setDisplay(i % 2 == 0 ? display0 : display1) .setOnTop(true) .build(); - final Task task = createTask(stack, ".Task" + i, i, i, null); + final Task task = createTask(stack, ".Task" + i, i, null); tasks.add(task); } |