From 9f6affdde2555c91e5dd98ae16d58cddad651261 Mon Sep 17 00:00:00 2001 From: Bryce Lee Date: Fri, 1 Sep 2017 09:18:35 -0700 Subject: [PATCH] Do not consider overlays when finding task to reuse. An overlay should not be considered the top activity in a task when considering a task when launching an activity. Doing so will alter the behavior of launch modes, such as singleTop and singleTask. In these cases, the developer has chosen such mode with the expectation that their task will not have activities from other tasks placed on top, which is the case for features such as locking a work profile. This changelist addresses the issue by not considering an overlay to be the top activity when finding a task based on ActivityRecord. Fixes: 64839155 Test: bit FrameworksServicesTests:com.android.server.am.ActivityStackTests#testFindTaskWithOverlay Change-Id: I2684baf6929e5af321404e2eef597f456ff87ee8 --- .../com/android/server/am/ActivityStack.java | 4 +++- .../com/android/server/am/TaskRecord.java | 6 ++++- .../android/server/am/ActivityStackTests.java | 24 +++++++++++++++++++ .../android/server/am/ActivityTestsBase.java | 6 +++++ 4 files changed, 38 insertions(+), 2 deletions(-) diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java index 4d525f232b2a7..d62d9357e43f0 100644 --- a/services/core/java/com/android/server/am/ActivityStack.java +++ b/services/core/java/com/android/server/am/ActivityStack.java @@ -953,7 +953,9 @@ class ActivityStack extends ConfigurationContai if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Skipping " + task + ": different user"); continue; } - final ActivityRecord r = task.getTopActivity(); + + // Overlays should not be considered as the task's logical top activity. + final ActivityRecord r = task.getTopActivity(false /* includeOverlays */); if (r == null || r.finishing || r.userId != userId || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) { if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Skipping " + task + ": mismatch root " + r); diff --git a/services/core/java/com/android/server/am/TaskRecord.java b/services/core/java/com/android/server/am/TaskRecord.java index 261797e3113ce..1bbb06871cc2a 100644 --- a/services/core/java/com/android/server/am/TaskRecord.java +++ b/services/core/java/com/android/server/am/TaskRecord.java @@ -1138,9 +1138,13 @@ final class TaskRecord extends ConfigurationContainer implements TaskWindowConta } ActivityRecord getTopActivity() { + return getTopActivity(true /* includeOverlays */); + } + + ActivityRecord getTopActivity(boolean includeOverlays) { for (int i = mActivities.size() - 1; i >= 0; --i) { final ActivityRecord r = mActivities.get(i); - if (r.finishing) { + if (r.finishing || (!includeOverlays && r.mTaskOverlay)) { continue; } return r; diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityStackTests.java b/services/tests/servicestests/src/com/android/server/am/ActivityStackTests.java index 80e241c0581f0..02fba082ca98d 100644 --- a/services/tests/servicestests/src/com/android/server/am/ActivityStackTests.java +++ b/services/tests/servicestests/src/com/android/server/am/ActivityStackTests.java @@ -24,6 +24,7 @@ import static org.junit.Assert.assertNull; import android.app.ActivityManager; import android.content.ComponentName; import android.content.pm.ActivityInfo; +import android.os.UserHandle; import android.platform.test.annotations.Presubmit; import android.support.test.filters.SmallTest; import android.support.test.runner.AndroidJUnit4; @@ -44,6 +45,8 @@ public class ActivityStackTests extends ActivityTestsBase { private static final int TEST_STACK_ID = 100; private static final ComponentName testActivityComponent = ComponentName.unflattenFromString("com.foo/.BarActivity"); + private static final ComponentName testOverlayComponent = + ComponentName.unflattenFromString("com.foo/.OverlayActivity"); @Test public void testEmptyTaskCleanupOnRemove() throws Exception { @@ -98,4 +101,25 @@ public class ActivityStackTests extends ActivityTestsBase { testStack.stopActivityLocked(activityRecord); } + + @Test + public void testFindTaskWithOverlay() throws Exception { + final ActivityManagerService service = createActivityManagerService(); + final TaskRecord task = createTask(service, testActivityComponent, TEST_STACK_ID); + final ActivityRecord activityRecord = createActivity(service, testActivityComponent, task, + 0); + // Overlay must be for a different user to prevent recognizing a matching top activity + final ActivityRecord taskOverlay = createActivity(service, testOverlayComponent, task, + UserHandle.PER_USER_RANGE * 2); + taskOverlay.mTaskOverlay = true; + + final ActivityStack testStack = service.mStackSupervisor.getStack(TEST_STACK_ID); + final ActivityStackSupervisor.FindTaskResult result = + new ActivityStackSupervisor.FindTaskResult(); + testStack.findTaskLocked(activityRecord, result); + + assertEquals(task.getTopActivity(false /* includeOverlays */), activityRecord); + assertEquals(task.getTopActivity(true /* includeOverlays */), taskOverlay); + assertNotNull(result.r); + } } diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java b/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java index c03a95789be48..a6c0cf17bd057 100644 --- a/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java +++ b/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java @@ -87,11 +87,17 @@ public class ActivityTestsBase { protected static ActivityRecord createActivity(ActivityManagerService service, ComponentName component, TaskRecord task) { + return createActivity(service, component, task, 0 /* userId */); + } + + protected static ActivityRecord createActivity(ActivityManagerService service, + ComponentName component, TaskRecord task, int uid) { Intent intent = new Intent(); intent.setComponent(component); final ActivityInfo aInfo = new ActivityInfo(); aInfo.applicationInfo = new ApplicationInfo(); aInfo.applicationInfo.packageName = component.getPackageName(); + aInfo.applicationInfo.uid = uid; AttributeCache.init(service.mContext); final ActivityRecord activity = new ActivityRecord(service, null /* caller */, 0 /* launchedFromPid */, 0, null, intent, null,