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
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index 4d525f23..d62d935 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 @@
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 261797e3..1bbb068 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 @@
}
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 80e241c..02fba08 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 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 @@
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 @@
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 c03a957..a6c0cf1 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 @@
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,