Loading services/core/java/com/android/server/wm/RunningTasks.java +73 −38 Original line number Diff line number Diff line Loading @@ -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. Loading @@ -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; Loading @@ -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; Loading @@ -79,22 +74,67 @@ class RunningTasks { mRecentTasks = root.mService.getRecentTasks(); 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); } 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); } // 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 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)); } final Task task = iter.next(); list.add(createRunningTaskInfo(task)); maxNum--; 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) { Loading @@ -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; Loading services/tests/wmtests/src/com/android/server/wm/RunningTasksTest.java +34 −66 Original line number Diff line number Diff line Loading @@ -60,55 +60,6 @@ public class RunningTasksTest extends WindowTestsBase { mRunningTasks = new RunningTasks(); } @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, 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, 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(); Loading @@ -120,7 +71,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; Loading @@ -145,7 +96,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; Loading @@ -162,46 +113,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, 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, 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")) Loading Loading
services/core/java/com/android/server/wm/RunningTasks.java +73 −38 Original line number Diff line number Diff line Loading @@ -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. Loading @@ -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; Loading @@ -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; Loading @@ -79,22 +74,67 @@ class RunningTasks { mRecentTasks = root.mService.getRecentTasks(); 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); } 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); } // 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 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)); } final Task task = iter.next(); list.add(createRunningTaskInfo(task)); maxNum--; 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) { Loading @@ -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; Loading
services/tests/wmtests/src/com/android/server/wm/RunningTasksTest.java +34 −66 Original line number Diff line number Diff line Loading @@ -60,55 +60,6 @@ public class RunningTasksTest extends WindowTestsBase { mRunningTasks = new RunningTasks(); } @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, 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, 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(); Loading @@ -120,7 +71,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; Loading @@ -145,7 +96,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; Loading @@ -162,46 +113,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, 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, 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")) Loading