Merge "Don't launch ResolverActivity in home stack" into qt-dev
am: c82290fe51
Change-Id: Ibcd852cc5e40b7ec06f115ec4e41f6209cc3d108
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index 4278860..802683a 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -916,8 +916,12 @@
}
}
+ static boolean isResolverActivity(String className) {
+ return ResolverActivity.class.getName().equals(className);
+ }
+
boolean isResolverActivity() {
- return ResolverActivity.class.getName().equals(mActivityComponent.getClassName());
+ return isResolverActivity(mActivityComponent.getClassName());
}
boolean isResolverOrChildActivity() {
diff --git a/services/core/java/com/android/server/wm/ActivityStartController.java b/services/core/java/com/android/server/wm/ActivityStartController.java
index 7eac07c..919141c 100644
--- a/services/core/java/com/android/server/wm/ActivityStartController.java
+++ b/services/core/java/com/android/server/wm/ActivityStartController.java
@@ -171,7 +171,12 @@
void startHomeActivity(Intent intent, ActivityInfo aInfo, String reason, int displayId) {
final ActivityOptions options = ActivityOptions.makeBasic();
options.setLaunchWindowingMode(WINDOWING_MODE_FULLSCREEN);
- options.setLaunchActivityType(ACTIVITY_TYPE_HOME);
+ if (!ActivityRecord.isResolverActivity(aInfo.name)) {
+ // The resolver activity shouldn't be put in home stack because when the foreground is
+ // standard type activity, the resolver activity should be put on the top of current
+ // foreground instead of bring home stack to front.
+ options.setLaunchActivityType(ACTIVITY_TYPE_HOME);
+ }
options.setLaunchDisplayId(displayId);
mLastHomeActivityStartResult = obtainStarter(intent, "startHomeActivity: " + reason)
.setOutActivity(tmpOutRecord)
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
index 45d5219..a9807fb 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
@@ -79,7 +79,6 @@
import androidx.test.filters.SmallTest;
import com.android.server.wm.LaunchParamsController.LaunchParamsModifier;
-import com.android.server.wm.TaskRecord.TaskRecordFactory;
import org.junit.Before;
import org.junit.Test;
@@ -330,21 +329,14 @@
any(), any(), any(), anyInt(), anyInt(), anyInt(), any(),
anyBoolean(), anyBoolean(), any(), any(), any());
- // instrument the stack and task used.
- final ActivityStack stack = mRootActivityContainer.getDefaultDisplay().createStack(
- WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
- final TaskRecord task = new TaskBuilder(mSupervisor)
- .setCreateStack(false)
- .build();
-
- // use factory that only returns spy task.
- final TaskRecordFactory factory = mock(TaskRecordFactory.class);
- TaskRecord.setTaskRecordFactory(factory);
-
- // return task when created.
- doReturn(task).when(factory).create(any(), anyInt(), any(), any(), any(), any());
+ // Use factory that only returns spy task.
+ mockTaskRecordFactory();
if (mockGetLaunchStack) {
+ // Instrument the stack and task used.
+ final ActivityStack stack = mRootActivityContainer.getDefaultDisplay().createStack(
+ WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
+
// Direct starter to use spy stack.
doReturn(stack).when(mRootActivityContainer)
.getLaunchStack(any(), any(), any(), anyBoolean());
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java b/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java
index 2991dff..09b511a 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java
@@ -72,6 +72,7 @@
import com.android.server.appop.AppOpsService;
import com.android.server.firewall.IntentFirewall;
import com.android.server.uri.UriGrantsManagerInternal;
+import com.android.server.wm.TaskRecord.TaskRecordFactory;
import com.android.server.wm.utils.MockTracker;
import org.junit.After;
@@ -160,6 +161,19 @@
}
/**
+ * Delegates task creation to {@link #TaskBuilder} to avoid the dependency of window hierarchy
+ * when starting activity in unit tests.
+ */
+ void mockTaskRecordFactory() {
+ final TaskRecord task = new TaskBuilder(mSupervisor).setCreateStack(false).build();
+ final TaskRecordFactory factory = mock(TaskRecordFactory.class);
+ TaskRecord.setTaskRecordFactory(factory);
+ doReturn(task).when(factory).create(any() /* service */, anyInt() /* taskId */,
+ any() /* info */, any() /* intent */, any() /* voiceSession */,
+ any() /* voiceInteractor */);
+ }
+
+ /**
* Builder for creating new activities.
*/
protected static class ActivityBuilder {
diff --git a/services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java b/services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java
index bac1ecd..b2084f8 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java
@@ -25,7 +25,6 @@
import static android.content.pm.ActivityInfo.FLAG_ALWAYS_FOCUSABLE;
import static android.view.Display.DEFAULT_DISPLAY;
-import static com.android.dx.mockito.inline.extended.ExtendedMockito.doAnswer;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.never;
@@ -71,10 +70,10 @@
import java.util.List;
/**
- * Tests for the {@link ActivityStackSupervisor} class.
+ * Tests for the {@link RootActivityContainer} class.
*
* Build/Install/Run:
- * atest WmTests:ActivityStackSupervisorTests
+ * atest WmTests:RootActivityContainerTests
*/
@MediumTest
@Presubmit
@@ -399,17 +398,15 @@
*/
@Test
public void testStartHomeOnAllDisplays() {
+ mockResolveHomeActivity();
+
// Create secondary displays.
final TestActivityDisplay secondDisplay = spy(createNewActivityDisplay());
mRootActivityContainer.addChild(secondDisplay, POSITION_TOP);
doReturn(true).when(secondDisplay).supportsSystemDecorations();
// Create mock tasks and other necessary mocks.
- TaskBuilder taskBuilder = new TaskBuilder(mService.mStackSupervisor).setCreateStack(false);
- final TaskRecord.TaskRecordFactory factory = mock(TaskRecord.TaskRecordFactory.class);
- TaskRecord.setTaskRecordFactory(factory);
- doAnswer(i -> taskBuilder.build()).when(factory)
- .create(any(), anyInt(), any(), any(), any(), any());
+ mockTaskRecordFactory();
doReturn(true).when(mRootActivityContainer)
.ensureVisibilityAndConfig(any(), anyInt(), anyBoolean(), anyBoolean());
doReturn(true).when(mRootActivityContainer).canStartHomeOnDisplay(
@@ -510,6 +507,26 @@
}
/**
+ * Tests that when starting {@link #ResolverActivity} for home, it should use the standard
+ * activity type (in a new stack) so the order of back stack won't be broken.
+ */
+ @Test
+ public void testStartResolverActivityForHome() {
+ final ActivityInfo info = new ActivityInfo();
+ info.applicationInfo = new ApplicationInfo();
+ info.applicationInfo.packageName = "android";
+ info.name = ResolverActivity.class.getName();
+ doReturn(info).when(mRootActivityContainer).resolveHomeActivity(anyInt(), any());
+ mockTaskRecordFactory();
+
+ mRootActivityContainer.startHomeOnDisplay(0 /* userId */, "test", DEFAULT_DISPLAY);
+ final ActivityRecord resolverActivity = mRootActivityContainer.topRunningActivity();
+
+ assertEquals(info, resolverActivity.info);
+ assertEquals(ACTIVITY_TYPE_STANDARD, resolverActivity.getActivityStack().getActivityType());
+ }
+
+ /**
* Tests that secondary home should be selected if default home not set.
*/
@Test
@@ -542,13 +559,7 @@
*/
@Test
public void testResolveSecondaryHomeActivityWhenDefaultHomeNotSupportMultiDisplay() {
- final Intent defaultHomeIntent = mService.getHomeIntent();
- final ActivityInfo aInfoDefault = new ActivityInfo();
- aInfoDefault.name = "fakeHomeActivity";
- aInfoDefault.applicationInfo = new ApplicationInfo();
- aInfoDefault.applicationInfo.packageName = "fakeHomePackage";
- doReturn(aInfoDefault).when(mRootActivityContainer).resolveHomeActivity(anyInt(),
- refEq(defaultHomeIntent));
+ mockResolveHomeActivity();
final List<ResolveInfo> resolutions = new ArrayList<>();
doReturn(resolutions).when(mRootActivityContainer).resolveActivities(anyInt(), any());
@@ -575,13 +586,7 @@
*/
@Test
public void testResolveSecondaryHomeActivityWhenDefaultHomeSupportMultiDisplay() {
- final Intent homeIntent = mService.getHomeIntent();
- final ActivityInfo aInfoDefault = new ActivityInfo();
- aInfoDefault.name = "fakeHomeActivity";
- aInfoDefault.applicationInfo = new ApplicationInfo();
- aInfoDefault.applicationInfo.packageName = "fakeHomePackage";
- doReturn(aInfoDefault).when(mRootActivityContainer).resolveHomeActivity(anyInt(),
- refEq(homeIntent));
+ final ActivityInfo aInfoDefault = mockResolveHomeActivity();
final List<ResolveInfo> resolutions = new ArrayList<>();
final ResolveInfo infoFake1 = new ResolveInfo();
@@ -612,13 +617,7 @@
*/
@Test
public void testResolveSecondaryHomeActivityWhenOtherActivitySupportMultiDisplay() {
- final Intent homeIntent = mService.getHomeIntent();
- final ActivityInfo aInfoDefault = new ActivityInfo();
- aInfoDefault.name = "fakeHomeActivity";
- aInfoDefault.applicationInfo = new ApplicationInfo();
- aInfoDefault.applicationInfo.packageName = "fakeHomePackage";
- doReturn(aInfoDefault).when(mRootActivityContainer).resolveHomeActivity(anyInt(),
- refEq(homeIntent));
+ mockResolveHomeActivity();
final List<ResolveInfo> resolutions = new ArrayList<>();
final ResolveInfo infoFake1 = new ResolveInfo();
@@ -646,4 +645,19 @@
resolvedInfo.first.applicationInfo.packageName);
assertEquals(infoFake1.activityInfo.name, resolvedInfo.first.name);
}
+
+ /**
+ * Mock {@link RootActivityContainerTests#resolveHomeActivity} for returning consistent activity
+ * info for test cases (the original implementation will resolve from the real package manager).
+ */
+ private ActivityInfo mockResolveHomeActivity() {
+ final Intent homeIntent = mService.getHomeIntent();
+ final ActivityInfo aInfoDefault = new ActivityInfo();
+ aInfoDefault.name = "fakeHomeActivity";
+ aInfoDefault.applicationInfo = new ApplicationInfo();
+ aInfoDefault.applicationInfo.packageName = "fakeHomePackage";
+ doReturn(aInfoDefault).when(mRootActivityContainer).resolveHomeActivity(anyInt(),
+ refEq(homeIntent));
+ return aInfoDefault;
+ }
}