Loading services/core/java/com/android/server/am/ActivityStack.java +18 −13 Original line number Diff line number Diff line Loading @@ -347,6 +347,9 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai private final Rect mTmpRect2 = new Rect(); private final ActivityOptions mTmpOptions = ActivityOptions.makeBasic(); /** List for processing through a set of activities */ private final ArrayList<ActivityRecord> mTmpActivities = new ArrayList<>(); /** Run all ActivityStacks through this */ protected final ActivityStackSupervisor mStackSupervisor; Loading Loading @@ -4405,11 +4408,15 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai "Removing app " + app + " from history with " + i + " entries"); for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) { final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities; for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) { final ActivityRecord r = activities.get(activityNdx); --i; mTmpActivities.clear(); mTmpActivities.addAll(activities); while (!mTmpActivities.isEmpty()) { final int targetIndex = mTmpActivities.size() - 1; final ActivityRecord r = mTmpActivities.remove(targetIndex); if (DEBUG_CLEANUP) Slog.v(TAG_CLEANUP, "Record #" + i + " " + r + ": app=" + r.app); "Record #" + targetIndex + " " + r + ": app=" + r.app); if (r.app == app) { if (r.visible) { hasVisibleActivities = true; Loading Loading @@ -4827,9 +4834,11 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai ComponentName homeActivity = null; for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) { final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities; int numActivities = activities.size(); for (int activityNdx = 0; activityNdx < numActivities; ++activityNdx) { ActivityRecord r = activities.get(activityNdx); mTmpActivities.clear(); mTmpActivities.addAll(activities); while (!mTmpActivities.isEmpty()) { ActivityRecord r = mTmpActivities.remove(0); final boolean sameComponent = (r.packageName.equals(packageName) && (filterByClasses == null || filterByClasses.contains(r.realActivity.getClassName()))) Loading Loading @@ -4862,12 +4871,8 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai r.app = null; } lastTask = r.getTask(); if (finishActivityLocked(r, Activity.RESULT_CANCELED, null, "force-stop", true)) { // r has been deleted from mActivities, accommodate. --numActivities; --activityNdx; } finishActivityLocked(r, Activity.RESULT_CANCELED, null, "force-stop", true); } } } Loading services/core/java/com/android/server/am/TaskRecord.java +1 −1 Original line number Diff line number Diff line Loading @@ -2002,7 +2002,7 @@ class TaskRecord extends ConfigurationContainer implements TaskWindowContainerLi } else if (intent != null) { sb.append(" I="); sb.append(intent.getComponent().flattenToShortString()); } else if (affinityIntent != null) { } else if (affinityIntent != null && affinityIntent.getComponent() != null) { sb.append(" aI="); sb.append(affinityIntent.getComponent().flattenToShortString()); } else { Loading services/tests/servicestests/src/com/android/server/am/ActivityStackTests.java +41 −0 Original line number Diff line number Diff line Loading @@ -486,4 +486,45 @@ public class ActivityStackTests extends ActivityTestsBase { verify(lifecycleManager, times(1)).scheduleTransaction(eq(app.thread), eq(r.appToken), any(DestroyActivityItem.class)); } @Test public void testFinishDisabledPackageActivities() throws Exception { final ActivityRecord firstActivity = new ActivityBuilder(mService).setTask(mTask).build(); final ActivityRecord secondActivity = new ActivityBuilder(mService).setTask(mTask).build(); // Making the second activity a task overlay without an app means it will be removed from // the task's activities as well once first activity is removed. secondActivity.mTaskOverlay = true; secondActivity.app = null; assertEquals(mTask.mActivities.size(), 2); mStack.finishDisabledPackageActivitiesLocked(firstActivity.packageName, null, true /* doit */, true /* evenPersistent */, UserHandle.USER_ALL); assertTrue(mTask.mActivities.isEmpty()); assertTrue(mStack.getAllTasks().isEmpty()); } @Test public void testHandleAppDied() throws Exception { final ActivityRecord firstActivity = new ActivityBuilder(mService).setTask(mTask).build(); final ActivityRecord secondActivity = new ActivityBuilder(mService).setTask(mTask).build(); // Making the first activity a task overlay means it will be removed from the task's // activities as well once second activity is removed as handleAppDied processes the // activity list in reverse. firstActivity.mTaskOverlay = true; firstActivity.app = null; // second activity will be immediately removed as it has no state. secondActivity.haveState = false; assertEquals(mTask.mActivities.size(), 2); mStack.handleAppDiedLocked(secondActivity.app); assertTrue(mTask.mActivities.isEmpty()); assertTrue(mStack.getAllTasks().isEmpty()); } } services/tests/servicestests/src/com/android/server/am/ActivityStarterTests.java +5 −5 Original line number Diff line number Diff line Loading @@ -197,11 +197,6 @@ public class ActivityStarterTests extends ActivityTestsBase { final ActivityInfo aInfo = containsConditions(preconditions, PRECONDITION_NO_ACTIVITY_INFO) ? null : new ActivityInfo(); if (aInfo != null) { aInfo.applicationInfo = new ApplicationInfo(); aInfo.applicationInfo.packageName = ActivityBuilder.DEFAULT_PACKAGE; } IVoiceInteractionSession voiceSession = containsConditions(preconditions, PRECONDITION_SOURCE_VOICE_SESSION) ? mock(IVoiceInteractionSession.class) : null; Loading @@ -210,6 +205,11 @@ public class ActivityStarterTests extends ActivityTestsBase { final ActivityBuilder builder = new ActivityBuilder(service).setTask( new TaskBuilder(service.mStackSupervisor).setVoiceSession(voiceSession).build()); if (aInfo != null) { aInfo.applicationInfo = new ApplicationInfo(); aInfo.applicationInfo.packageName = builder.getDefaultComponentPackageName(); } // Offset uid by one from {@link ActivityInfo} to simulate different uids. if (containsConditions(preconditions, PRECONDITION_DIFFERENT_UID)) { builder.setUid(aInfo.applicationInfo.uid + 1); Loading services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java +22 −6 Original line number Diff line number Diff line Loading @@ -67,6 +67,12 @@ public class ActivityTestsBase { private final Context mContext = InstrumentationRegistry.getContext(); private HandlerThread mHandlerThread; // Default package name static final String DEFAULT_COMPONENT_PACKAGE_NAME = "com.foo"; // Default base activity name private static final String DEFAULT_COMPONENT_CLASS_NAME = ".BarActivity"; @Before public void setUp() throws Exception { if (!sOneTimeSetupDone) { Loading Loading @@ -106,11 +112,7 @@ public class ActivityTestsBase { // An id appended to the end of the component name to make it unique private static int sCurrentActivityId = 0; // Default package name static final String DEFAULT_PACKAGE = "com.foo"; // Default base activity name private static final String DEFAULT_BASE_ACTIVITY_NAME = ".BarActivity"; private final ActivityManagerService mService; Loading Loading @@ -149,11 +151,15 @@ public class ActivityTestsBase { return this; } String getDefaultComponentPackageName() { return DEFAULT_COMPONENT_PACKAGE_NAME; } ActivityRecord build() { if (mComponent == null) { final int id = sCurrentActivityId++; mComponent = ComponentName.createRelative(DEFAULT_PACKAGE, DEFAULT_BASE_ACTIVITY_NAME + id); mComponent = ComponentName.createRelative(DEFAULT_COMPONENT_PACKAGE_NAME, DEFAULT_COMPONENT_CLASS_NAME + id); } if (mCreateTask) { Loading Loading @@ -191,6 +197,9 @@ public class ActivityTestsBase { * Builder for creating new tasks. */ protected static class TaskBuilder { // Default package name static final String DEFAULT_PACKAGE = "com.bar"; private final ActivityStackSupervisor mSupervisor; private ComponentName mComponent; Loading Loading @@ -252,6 +261,11 @@ public class ActivityTestsBase { aInfo.applicationInfo.packageName = mPackage; Intent intent = new Intent(); if (mComponent == null) { mComponent = ComponentName.createRelative(DEFAULT_COMPONENT_PACKAGE_NAME, DEFAULT_COMPONENT_CLASS_NAME); } intent.setComponent(mComponent); intent.setFlags(mFlags); Loading Loading @@ -312,6 +326,8 @@ public class ActivityTestsBase { doNothing().when(supervisor).ensureActivitiesVisibleLocked(any(), anyInt(), anyBoolean()); // Do not schedule idle timeouts doNothing().when(supervisor).scheduleIdleTimeoutLocked(any()); // unit test version does not handle launch wake lock doNothing().when(supervisor).acquireLaunchWakelock(); supervisor.initialize(); Loading Loading
services/core/java/com/android/server/am/ActivityStack.java +18 −13 Original line number Diff line number Diff line Loading @@ -347,6 +347,9 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai private final Rect mTmpRect2 = new Rect(); private final ActivityOptions mTmpOptions = ActivityOptions.makeBasic(); /** List for processing through a set of activities */ private final ArrayList<ActivityRecord> mTmpActivities = new ArrayList<>(); /** Run all ActivityStacks through this */ protected final ActivityStackSupervisor mStackSupervisor; Loading Loading @@ -4405,11 +4408,15 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai "Removing app " + app + " from history with " + i + " entries"); for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) { final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities; for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) { final ActivityRecord r = activities.get(activityNdx); --i; mTmpActivities.clear(); mTmpActivities.addAll(activities); while (!mTmpActivities.isEmpty()) { final int targetIndex = mTmpActivities.size() - 1; final ActivityRecord r = mTmpActivities.remove(targetIndex); if (DEBUG_CLEANUP) Slog.v(TAG_CLEANUP, "Record #" + i + " " + r + ": app=" + r.app); "Record #" + targetIndex + " " + r + ": app=" + r.app); if (r.app == app) { if (r.visible) { hasVisibleActivities = true; Loading Loading @@ -4827,9 +4834,11 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai ComponentName homeActivity = null; for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) { final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities; int numActivities = activities.size(); for (int activityNdx = 0; activityNdx < numActivities; ++activityNdx) { ActivityRecord r = activities.get(activityNdx); mTmpActivities.clear(); mTmpActivities.addAll(activities); while (!mTmpActivities.isEmpty()) { ActivityRecord r = mTmpActivities.remove(0); final boolean sameComponent = (r.packageName.equals(packageName) && (filterByClasses == null || filterByClasses.contains(r.realActivity.getClassName()))) Loading Loading @@ -4862,12 +4871,8 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai r.app = null; } lastTask = r.getTask(); if (finishActivityLocked(r, Activity.RESULT_CANCELED, null, "force-stop", true)) { // r has been deleted from mActivities, accommodate. --numActivities; --activityNdx; } finishActivityLocked(r, Activity.RESULT_CANCELED, null, "force-stop", true); } } } Loading
services/core/java/com/android/server/am/TaskRecord.java +1 −1 Original line number Diff line number Diff line Loading @@ -2002,7 +2002,7 @@ class TaskRecord extends ConfigurationContainer implements TaskWindowContainerLi } else if (intent != null) { sb.append(" I="); sb.append(intent.getComponent().flattenToShortString()); } else if (affinityIntent != null) { } else if (affinityIntent != null && affinityIntent.getComponent() != null) { sb.append(" aI="); sb.append(affinityIntent.getComponent().flattenToShortString()); } else { Loading
services/tests/servicestests/src/com/android/server/am/ActivityStackTests.java +41 −0 Original line number Diff line number Diff line Loading @@ -486,4 +486,45 @@ public class ActivityStackTests extends ActivityTestsBase { verify(lifecycleManager, times(1)).scheduleTransaction(eq(app.thread), eq(r.appToken), any(DestroyActivityItem.class)); } @Test public void testFinishDisabledPackageActivities() throws Exception { final ActivityRecord firstActivity = new ActivityBuilder(mService).setTask(mTask).build(); final ActivityRecord secondActivity = new ActivityBuilder(mService).setTask(mTask).build(); // Making the second activity a task overlay without an app means it will be removed from // the task's activities as well once first activity is removed. secondActivity.mTaskOverlay = true; secondActivity.app = null; assertEquals(mTask.mActivities.size(), 2); mStack.finishDisabledPackageActivitiesLocked(firstActivity.packageName, null, true /* doit */, true /* evenPersistent */, UserHandle.USER_ALL); assertTrue(mTask.mActivities.isEmpty()); assertTrue(mStack.getAllTasks().isEmpty()); } @Test public void testHandleAppDied() throws Exception { final ActivityRecord firstActivity = new ActivityBuilder(mService).setTask(mTask).build(); final ActivityRecord secondActivity = new ActivityBuilder(mService).setTask(mTask).build(); // Making the first activity a task overlay means it will be removed from the task's // activities as well once second activity is removed as handleAppDied processes the // activity list in reverse. firstActivity.mTaskOverlay = true; firstActivity.app = null; // second activity will be immediately removed as it has no state. secondActivity.haveState = false; assertEquals(mTask.mActivities.size(), 2); mStack.handleAppDiedLocked(secondActivity.app); assertTrue(mTask.mActivities.isEmpty()); assertTrue(mStack.getAllTasks().isEmpty()); } }
services/tests/servicestests/src/com/android/server/am/ActivityStarterTests.java +5 −5 Original line number Diff line number Diff line Loading @@ -197,11 +197,6 @@ public class ActivityStarterTests extends ActivityTestsBase { final ActivityInfo aInfo = containsConditions(preconditions, PRECONDITION_NO_ACTIVITY_INFO) ? null : new ActivityInfo(); if (aInfo != null) { aInfo.applicationInfo = new ApplicationInfo(); aInfo.applicationInfo.packageName = ActivityBuilder.DEFAULT_PACKAGE; } IVoiceInteractionSession voiceSession = containsConditions(preconditions, PRECONDITION_SOURCE_VOICE_SESSION) ? mock(IVoiceInteractionSession.class) : null; Loading @@ -210,6 +205,11 @@ public class ActivityStarterTests extends ActivityTestsBase { final ActivityBuilder builder = new ActivityBuilder(service).setTask( new TaskBuilder(service.mStackSupervisor).setVoiceSession(voiceSession).build()); if (aInfo != null) { aInfo.applicationInfo = new ApplicationInfo(); aInfo.applicationInfo.packageName = builder.getDefaultComponentPackageName(); } // Offset uid by one from {@link ActivityInfo} to simulate different uids. if (containsConditions(preconditions, PRECONDITION_DIFFERENT_UID)) { builder.setUid(aInfo.applicationInfo.uid + 1); Loading
services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java +22 −6 Original line number Diff line number Diff line Loading @@ -67,6 +67,12 @@ public class ActivityTestsBase { private final Context mContext = InstrumentationRegistry.getContext(); private HandlerThread mHandlerThread; // Default package name static final String DEFAULT_COMPONENT_PACKAGE_NAME = "com.foo"; // Default base activity name private static final String DEFAULT_COMPONENT_CLASS_NAME = ".BarActivity"; @Before public void setUp() throws Exception { if (!sOneTimeSetupDone) { Loading Loading @@ -106,11 +112,7 @@ public class ActivityTestsBase { // An id appended to the end of the component name to make it unique private static int sCurrentActivityId = 0; // Default package name static final String DEFAULT_PACKAGE = "com.foo"; // Default base activity name private static final String DEFAULT_BASE_ACTIVITY_NAME = ".BarActivity"; private final ActivityManagerService mService; Loading Loading @@ -149,11 +151,15 @@ public class ActivityTestsBase { return this; } String getDefaultComponentPackageName() { return DEFAULT_COMPONENT_PACKAGE_NAME; } ActivityRecord build() { if (mComponent == null) { final int id = sCurrentActivityId++; mComponent = ComponentName.createRelative(DEFAULT_PACKAGE, DEFAULT_BASE_ACTIVITY_NAME + id); mComponent = ComponentName.createRelative(DEFAULT_COMPONENT_PACKAGE_NAME, DEFAULT_COMPONENT_CLASS_NAME + id); } if (mCreateTask) { Loading Loading @@ -191,6 +197,9 @@ public class ActivityTestsBase { * Builder for creating new tasks. */ protected static class TaskBuilder { // Default package name static final String DEFAULT_PACKAGE = "com.bar"; private final ActivityStackSupervisor mSupervisor; private ComponentName mComponent; Loading Loading @@ -252,6 +261,11 @@ public class ActivityTestsBase { aInfo.applicationInfo.packageName = mPackage; Intent intent = new Intent(); if (mComponent == null) { mComponent = ComponentName.createRelative(DEFAULT_COMPONENT_PACKAGE_NAME, DEFAULT_COMPONENT_CLASS_NAME); } intent.setComponent(mComponent); intent.setFlags(mFlags); Loading Loading @@ -312,6 +326,8 @@ public class ActivityTestsBase { doNothing().when(supervisor).ensureActivitiesVisibleLocked(any(), anyInt(), anyBoolean()); // Do not schedule idle timeouts doNothing().when(supervisor).scheduleIdleTimeoutLocked(any()); // unit test version does not handle launch wake lock doNothing().when(supervisor).acquireLaunchWakelock(); supervisor.initialize(); Loading