Loading services/core/java/com/android/server/wm/Task.java +33 −15 Original line number Diff line number Diff line Loading @@ -319,6 +319,11 @@ class Task extends TaskFragment { */ boolean mInResumeTopActivity = false; /** * Used to identify if the activity that is installed from device's system image. */ boolean mIsEffectivelySystemApp; int mCurrentUser; String affinity; // The affinity name for this task, or null; may change identity. Loading Loading @@ -554,13 +559,24 @@ class Task extends TaskFragment { if (r.finishing) return false; if (mRoot == null || mRoot.finishing) { // Set this as the candidate root since it isn't finishing. mRoot = r; } final int uid = mRoot == r ? effectiveUid : r.info.applicationInfo.uid; if (mIgnoreRelinquishIdentity || (mRoot.info.flags & FLAG_RELINQUISH_TASK_IDENTITY) == 0 || (mRoot.info.applicationInfo.uid != Process.SYSTEM_UID && !mRoot.info.applicationInfo.isSystemApp() && mRoot.info.applicationInfo.uid != uid)) { // No need to relinquish identity, end search. return true; } // Only end search if we are ignore relinquishing identity or we are not relinquishing. return mIgnoreRelinquishIdentity || mNeverRelinquishIdentity || (r.info.flags & FLAG_RELINQUISH_TASK_IDENTITY) == 0; // Relinquish to next activity mRoot = r; return false; } } Loading Loading @@ -985,7 +1001,15 @@ class Task extends TaskFragment { * @param info The activity info which could be different from {@code r.info} if set. */ void setIntent(ActivityRecord r, @Nullable Intent intent, @Nullable ActivityInfo info) { if (this.intent == null || !mNeverRelinquishIdentity) { boolean updateIdentity = false; if (this.intent == null) { updateIdentity = true; } else if (!mNeverRelinquishIdentity) { final ActivityInfo activityInfo = info != null ? info : r.info; updateIdentity = (effectiveUid == Process.SYSTEM_UID || mIsEffectivelySystemApp || effectiveUid == activityInfo.applicationInfo.uid); } if (updateIdentity) { mCallingUid = r.launchedFromUid; mCallingPackage = r.launchedFromPackage; mCallingFeatureId = r.launchedFromFeatureId; Loading @@ -998,14 +1022,7 @@ class Task extends TaskFragment { private void setIntent(Intent _intent, ActivityInfo info) { if (!isLeafTask()) return; if (info.applicationInfo.uid == Process.SYSTEM_UID || info.applicationInfo.isSystemApp()) { // Only allow the apps that pre-installed on the system image to apply // relinquishTaskIdentity mNeverRelinquishIdentity = (info.flags & FLAG_RELINQUISH_TASK_IDENTITY) == 0; } else { mNeverRelinquishIdentity = true; } affinity = info.taskAffinity; if (intent == null) { // If this task already has an intent associated with it, don't set the root Loading @@ -1014,6 +1031,7 @@ class Task extends TaskFragment { rootAffinity = affinity; } effectiveUid = info.applicationInfo.uid; mIsEffectivelySystemApp = info.applicationInfo.isSystemApp(); stringName = null; if (info.targetActivity == null) { Loading services/tests/wmtests/src/com/android/server/wm/TaskTests.java +56 −17 Original line number Diff line number Diff line Loading @@ -899,22 +899,21 @@ public class TaskTests extends WindowTestsBase { /** * Test that root activity index is reported correctly when looking for the 'effective root' in * case when bottom activity is finishing. Ignore the relinquishing task identity if it's not a * system activity even with the FLAG_RELINQUISH_TASK_IDENTITY. * case when bottom activities are relinquishing task identity or finishing. */ @Test public void testFindRootIndex_effectiveRoot_finishingAndRelinquishing() { final Task task = getTestTask(); final ActivityRecord activity0 = new ActivityBuilder(mAtm).setCreateTask(true).build(); final Task task = activity0.getTask(); // Add extra two activities. Mark the one on the bottom with "relinquishTaskIdentity" and // one above as finishing. final ActivityRecord activity0 = task.getBottomMostActivity(); activity0.info.flags |= FLAG_RELINQUISH_TASK_IDENTITY; final ActivityRecord activity1 = new ActivityBuilder(mAtm).setTask(task).build(); activity1.finishing = true; new ActivityBuilder(mAtm).setTask(task).build(); assertEquals("The first non-finishing activity and non-relinquishing task identity " + "must be reported.", task.getChildAt(0), task.getRootActivity( + "must be reported.", task.getChildAt(2), task.getRootActivity( false /*ignoreRelinquishIdentity*/, true /*setToBottomIfNone*/)); } Loading @@ -934,21 +933,21 @@ public class TaskTests extends WindowTestsBase { } /** * Test that the root activity index is reported correctly when looking for the * 'effective root' for the case when all non-system activities have relinquishTaskIdentity set. * Test that the topmost activity index is reported correctly when looking for the * 'effective root' for the case when all activities have relinquishTaskIdentity set. */ @Test public void testFindRootIndex_effectiveRoot_relinquishingMultipleActivities() { final Task task = getTestTask(); final ActivityRecord activity0 = new ActivityBuilder(mAtm).setCreateTask(true).build(); final Task task = activity0.getTask(); // Set relinquishTaskIdentity for all activities in the task final ActivityRecord activity0 = task.getBottomMostActivity(); activity0.info.flags |= FLAG_RELINQUISH_TASK_IDENTITY; final ActivityRecord activity1 = new ActivityBuilder(mAtm).setTask(task).build(); activity1.info.flags |= FLAG_RELINQUISH_TASK_IDENTITY; assertEquals("The topmost activity in the task must be reported.", task.getChildAt(0), task.getRootActivity(false /*ignoreRelinquishIdentity*/, true /*setToBottomIfNone*/)); assertEquals("The topmost activity in the task must be reported.", task.getChildAt(task.getChildCount() - 1), task.getRootActivity( false /*ignoreRelinquishIdentity*/, true /*setToBottomIfNone*/)); } /** Test that bottom-most activity is reported in {@link Task#getRootActivity()}. */ Loading Loading @@ -1086,14 +1085,14 @@ public class TaskTests extends WindowTestsBase { } /** * Test {@link ActivityRecord#getTaskForActivityLocked(IBinder, boolean)} with non-system * activity that relinquishes task identity. * Test {@link ActivityRecord#getTaskForActivityLocked(IBinder, boolean)} with activity that * relinquishes task identity. */ @Test public void testGetTaskForActivity_onlyRoot_relinquishTaskIdentity() { final Task task = getTestTask(); final ActivityRecord activity0 = new ActivityBuilder(mAtm).setCreateTask(true).build(); final Task task = activity0.getTask(); // Make the current root activity relinquish task identity final ActivityRecord activity0 = task.getBottomMostActivity(); activity0.info.flags |= FLAG_RELINQUISH_TASK_IDENTITY; // Add an extra activity on top - this will be the new root final ActivityRecord activity1 = new ActivityBuilder(mAtm).setTask(task).build(); Loading @@ -1102,7 +1101,7 @@ public class TaskTests extends WindowTestsBase { assertEquals(task.mTaskId, ActivityRecord.getTaskForActivityLocked(activity0.token, true /* onlyRoot */)); assertEquals("No task must be reported for activity that is above root", INVALID_TASK_ID, assertEquals(task.mTaskId, ActivityRecord.getTaskForActivityLocked(activity1.token, true /* onlyRoot */)); assertEquals("No task must be reported for activity that is above root", INVALID_TASK_ID, ActivityRecord.getTaskForActivityLocked(activity2.token, true /* onlyRoot */)); Loading Loading @@ -1189,6 +1188,46 @@ public class TaskTests extends WindowTestsBase { verify(task).setIntent(eq(activity0)); } /** * Test {@link Task#updateEffectiveIntent()} when activity with relinquishTaskIdentity but * another with different uid. This should make the task use the root activity when updating the * intent. */ @Test public void testUpdateEffectiveIntent_relinquishingWithDifferentUid() { final ActivityRecord activity0 = new ActivityBuilder(mAtm) .setActivityFlags(FLAG_RELINQUISH_TASK_IDENTITY).setCreateTask(true).build(); final Task task = activity0.getTask(); // Add an extra activity on top new ActivityBuilder(mAtm).setUid(11).setTask(task).build(); spyOn(task); task.updateEffectiveIntent(); verify(task).setIntent(eq(activity0)); } /** * Test {@link Task#updateEffectiveIntent()} with activities set as relinquishTaskIdentity. * This should make the task use the topmost activity when updating the intent. */ @Test public void testUpdateEffectiveIntent_relinquishingMultipleActivities() { final ActivityRecord activity0 = new ActivityBuilder(mAtm) .setActivityFlags(FLAG_RELINQUISH_TASK_IDENTITY).setCreateTask(true).build(); final Task task = activity0.getTask(); // Add an extra activity on top final ActivityRecord activity1 = new ActivityBuilder(mAtm).setTask(task).build(); activity1.info.flags |= FLAG_RELINQUISH_TASK_IDENTITY; // Add an extra activity on top final ActivityRecord activity2 = new ActivityBuilder(mAtm).setTask(task).build(); spyOn(task); task.updateEffectiveIntent(); verify(task).setIntent(eq(activity2)); } @Test public void testSaveLaunchingStateWhenConfigurationChanged() { LaunchParamsPersister persister = mAtm.mTaskSupervisor.mLaunchParamsPersister; Loading Loading
services/core/java/com/android/server/wm/Task.java +33 −15 Original line number Diff line number Diff line Loading @@ -319,6 +319,11 @@ class Task extends TaskFragment { */ boolean mInResumeTopActivity = false; /** * Used to identify if the activity that is installed from device's system image. */ boolean mIsEffectivelySystemApp; int mCurrentUser; String affinity; // The affinity name for this task, or null; may change identity. Loading Loading @@ -554,13 +559,24 @@ class Task extends TaskFragment { if (r.finishing) return false; if (mRoot == null || mRoot.finishing) { // Set this as the candidate root since it isn't finishing. mRoot = r; } final int uid = mRoot == r ? effectiveUid : r.info.applicationInfo.uid; if (mIgnoreRelinquishIdentity || (mRoot.info.flags & FLAG_RELINQUISH_TASK_IDENTITY) == 0 || (mRoot.info.applicationInfo.uid != Process.SYSTEM_UID && !mRoot.info.applicationInfo.isSystemApp() && mRoot.info.applicationInfo.uid != uid)) { // No need to relinquish identity, end search. return true; } // Only end search if we are ignore relinquishing identity or we are not relinquishing. return mIgnoreRelinquishIdentity || mNeverRelinquishIdentity || (r.info.flags & FLAG_RELINQUISH_TASK_IDENTITY) == 0; // Relinquish to next activity mRoot = r; return false; } } Loading Loading @@ -985,7 +1001,15 @@ class Task extends TaskFragment { * @param info The activity info which could be different from {@code r.info} if set. */ void setIntent(ActivityRecord r, @Nullable Intent intent, @Nullable ActivityInfo info) { if (this.intent == null || !mNeverRelinquishIdentity) { boolean updateIdentity = false; if (this.intent == null) { updateIdentity = true; } else if (!mNeverRelinquishIdentity) { final ActivityInfo activityInfo = info != null ? info : r.info; updateIdentity = (effectiveUid == Process.SYSTEM_UID || mIsEffectivelySystemApp || effectiveUid == activityInfo.applicationInfo.uid); } if (updateIdentity) { mCallingUid = r.launchedFromUid; mCallingPackage = r.launchedFromPackage; mCallingFeatureId = r.launchedFromFeatureId; Loading @@ -998,14 +1022,7 @@ class Task extends TaskFragment { private void setIntent(Intent _intent, ActivityInfo info) { if (!isLeafTask()) return; if (info.applicationInfo.uid == Process.SYSTEM_UID || info.applicationInfo.isSystemApp()) { // Only allow the apps that pre-installed on the system image to apply // relinquishTaskIdentity mNeverRelinquishIdentity = (info.flags & FLAG_RELINQUISH_TASK_IDENTITY) == 0; } else { mNeverRelinquishIdentity = true; } affinity = info.taskAffinity; if (intent == null) { // If this task already has an intent associated with it, don't set the root Loading @@ -1014,6 +1031,7 @@ class Task extends TaskFragment { rootAffinity = affinity; } effectiveUid = info.applicationInfo.uid; mIsEffectivelySystemApp = info.applicationInfo.isSystemApp(); stringName = null; if (info.targetActivity == null) { Loading
services/tests/wmtests/src/com/android/server/wm/TaskTests.java +56 −17 Original line number Diff line number Diff line Loading @@ -899,22 +899,21 @@ public class TaskTests extends WindowTestsBase { /** * Test that root activity index is reported correctly when looking for the 'effective root' in * case when bottom activity is finishing. Ignore the relinquishing task identity if it's not a * system activity even with the FLAG_RELINQUISH_TASK_IDENTITY. * case when bottom activities are relinquishing task identity or finishing. */ @Test public void testFindRootIndex_effectiveRoot_finishingAndRelinquishing() { final Task task = getTestTask(); final ActivityRecord activity0 = new ActivityBuilder(mAtm).setCreateTask(true).build(); final Task task = activity0.getTask(); // Add extra two activities. Mark the one on the bottom with "relinquishTaskIdentity" and // one above as finishing. final ActivityRecord activity0 = task.getBottomMostActivity(); activity0.info.flags |= FLAG_RELINQUISH_TASK_IDENTITY; final ActivityRecord activity1 = new ActivityBuilder(mAtm).setTask(task).build(); activity1.finishing = true; new ActivityBuilder(mAtm).setTask(task).build(); assertEquals("The first non-finishing activity and non-relinquishing task identity " + "must be reported.", task.getChildAt(0), task.getRootActivity( + "must be reported.", task.getChildAt(2), task.getRootActivity( false /*ignoreRelinquishIdentity*/, true /*setToBottomIfNone*/)); } Loading @@ -934,21 +933,21 @@ public class TaskTests extends WindowTestsBase { } /** * Test that the root activity index is reported correctly when looking for the * 'effective root' for the case when all non-system activities have relinquishTaskIdentity set. * Test that the topmost activity index is reported correctly when looking for the * 'effective root' for the case when all activities have relinquishTaskIdentity set. */ @Test public void testFindRootIndex_effectiveRoot_relinquishingMultipleActivities() { final Task task = getTestTask(); final ActivityRecord activity0 = new ActivityBuilder(mAtm).setCreateTask(true).build(); final Task task = activity0.getTask(); // Set relinquishTaskIdentity for all activities in the task final ActivityRecord activity0 = task.getBottomMostActivity(); activity0.info.flags |= FLAG_RELINQUISH_TASK_IDENTITY; final ActivityRecord activity1 = new ActivityBuilder(mAtm).setTask(task).build(); activity1.info.flags |= FLAG_RELINQUISH_TASK_IDENTITY; assertEquals("The topmost activity in the task must be reported.", task.getChildAt(0), task.getRootActivity(false /*ignoreRelinquishIdentity*/, true /*setToBottomIfNone*/)); assertEquals("The topmost activity in the task must be reported.", task.getChildAt(task.getChildCount() - 1), task.getRootActivity( false /*ignoreRelinquishIdentity*/, true /*setToBottomIfNone*/)); } /** Test that bottom-most activity is reported in {@link Task#getRootActivity()}. */ Loading Loading @@ -1086,14 +1085,14 @@ public class TaskTests extends WindowTestsBase { } /** * Test {@link ActivityRecord#getTaskForActivityLocked(IBinder, boolean)} with non-system * activity that relinquishes task identity. * Test {@link ActivityRecord#getTaskForActivityLocked(IBinder, boolean)} with activity that * relinquishes task identity. */ @Test public void testGetTaskForActivity_onlyRoot_relinquishTaskIdentity() { final Task task = getTestTask(); final ActivityRecord activity0 = new ActivityBuilder(mAtm).setCreateTask(true).build(); final Task task = activity0.getTask(); // Make the current root activity relinquish task identity final ActivityRecord activity0 = task.getBottomMostActivity(); activity0.info.flags |= FLAG_RELINQUISH_TASK_IDENTITY; // Add an extra activity on top - this will be the new root final ActivityRecord activity1 = new ActivityBuilder(mAtm).setTask(task).build(); Loading @@ -1102,7 +1101,7 @@ public class TaskTests extends WindowTestsBase { assertEquals(task.mTaskId, ActivityRecord.getTaskForActivityLocked(activity0.token, true /* onlyRoot */)); assertEquals("No task must be reported for activity that is above root", INVALID_TASK_ID, assertEquals(task.mTaskId, ActivityRecord.getTaskForActivityLocked(activity1.token, true /* onlyRoot */)); assertEquals("No task must be reported for activity that is above root", INVALID_TASK_ID, ActivityRecord.getTaskForActivityLocked(activity2.token, true /* onlyRoot */)); Loading Loading @@ -1189,6 +1188,46 @@ public class TaskTests extends WindowTestsBase { verify(task).setIntent(eq(activity0)); } /** * Test {@link Task#updateEffectiveIntent()} when activity with relinquishTaskIdentity but * another with different uid. This should make the task use the root activity when updating the * intent. */ @Test public void testUpdateEffectiveIntent_relinquishingWithDifferentUid() { final ActivityRecord activity0 = new ActivityBuilder(mAtm) .setActivityFlags(FLAG_RELINQUISH_TASK_IDENTITY).setCreateTask(true).build(); final Task task = activity0.getTask(); // Add an extra activity on top new ActivityBuilder(mAtm).setUid(11).setTask(task).build(); spyOn(task); task.updateEffectiveIntent(); verify(task).setIntent(eq(activity0)); } /** * Test {@link Task#updateEffectiveIntent()} with activities set as relinquishTaskIdentity. * This should make the task use the topmost activity when updating the intent. */ @Test public void testUpdateEffectiveIntent_relinquishingMultipleActivities() { final ActivityRecord activity0 = new ActivityBuilder(mAtm) .setActivityFlags(FLAG_RELINQUISH_TASK_IDENTITY).setCreateTask(true).build(); final Task task = activity0.getTask(); // Add an extra activity on top final ActivityRecord activity1 = new ActivityBuilder(mAtm).setTask(task).build(); activity1.info.flags |= FLAG_RELINQUISH_TASK_IDENTITY; // Add an extra activity on top final ActivityRecord activity2 = new ActivityBuilder(mAtm).setTask(task).build(); spyOn(task); task.updateEffectiveIntent(); verify(task).setIntent(eq(activity2)); } @Test public void testSaveLaunchingStateWhenConfigurationChanged() { LaunchParamsPersister persister = mAtm.mTaskSupervisor.mLaunchParamsPersister; Loading