Loading services/core/java/com/android/server/wm/ActivityRecord.java +5 −1 Original line number Diff line number Diff line Loading @@ -916,8 +916,12 @@ final class ActivityRecord extends ConfigurationContainer { } } 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() { Loading services/core/java/com/android/server/wm/ActivityStartController.java +6 −1 Original line number Diff line number Diff line Loading @@ -171,7 +171,12 @@ public class ActivityStartController { void startHomeActivity(Intent intent, ActivityInfo aInfo, String reason, int displayId) { final ActivityOptions options = ActivityOptions.makeBasic(); options.setLaunchWindowingMode(WINDOWING_MODE_FULLSCREEN); 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) Loading services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java +6 −14 Original line number Diff line number Diff line Loading @@ -79,7 +79,6 @@ import android.view.Gravity; 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; Loading Loading @@ -330,21 +329,14 @@ public class ActivityStarterTests extends ActivityTestsBase { any(), any(), any(), anyInt(), anyInt(), anyInt(), any(), anyBoolean(), anyBoolean(), any(), any(), any()); // instrument the stack and task used. // 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 */); 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()); if (mockGetLaunchStack) { // Direct starter to use spy stack. doReturn(stack).when(mRootActivityContainer) .getLaunchStack(any(), any(), any(), anyBoolean()); Loading services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java +14 −0 Original line number Diff line number Diff line Loading @@ -72,6 +72,7 @@ import com.android.server.am.PendingIntentController; 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; Loading Loading @@ -159,6 +160,19 @@ class ActivityTestsBase { return display; } /** * 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. */ Loading services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java +43 −29 Original line number Diff line number Diff line Loading @@ -25,7 +25,6 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMAR 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; Loading Loading @@ -71,10 +70,10 @@ import java.util.Arrays; 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 Loading Loading @@ -399,17 +398,15 @@ public class RootActivityContainerTests extends ActivityTestsBase { */ @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( Loading Loading @@ -509,6 +506,26 @@ public class RootActivityContainerTests extends ActivityTestsBase { verify(mRootActivityContainer, never()).resolveSecondaryHomeActivity(anyInt(), anyInt()); } /** * 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. */ Loading Loading @@ -542,13 +559,7 @@ public class RootActivityContainerTests extends ActivityTestsBase { */ @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()); Loading @@ -575,13 +586,7 @@ public class RootActivityContainerTests extends ActivityTestsBase { */ @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(); Loading Loading @@ -612,13 +617,7 @@ public class RootActivityContainerTests extends ActivityTestsBase { */ @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(); Loading Loading @@ -646,4 +645,19 @@ public class RootActivityContainerTests extends ActivityTestsBase { 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; } } Loading
services/core/java/com/android/server/wm/ActivityRecord.java +5 −1 Original line number Diff line number Diff line Loading @@ -916,8 +916,12 @@ final class ActivityRecord extends ConfigurationContainer { } } 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() { Loading
services/core/java/com/android/server/wm/ActivityStartController.java +6 −1 Original line number Diff line number Diff line Loading @@ -171,7 +171,12 @@ public class ActivityStartController { void startHomeActivity(Intent intent, ActivityInfo aInfo, String reason, int displayId) { final ActivityOptions options = ActivityOptions.makeBasic(); options.setLaunchWindowingMode(WINDOWING_MODE_FULLSCREEN); 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) Loading
services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java +6 −14 Original line number Diff line number Diff line Loading @@ -79,7 +79,6 @@ import android.view.Gravity; 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; Loading Loading @@ -330,21 +329,14 @@ public class ActivityStarterTests extends ActivityTestsBase { any(), any(), any(), anyInt(), anyInt(), anyInt(), any(), anyBoolean(), anyBoolean(), any(), any(), any()); // instrument the stack and task used. // 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 */); 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()); if (mockGetLaunchStack) { // Direct starter to use spy stack. doReturn(stack).when(mRootActivityContainer) .getLaunchStack(any(), any(), any(), anyBoolean()); Loading
services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java +14 −0 Original line number Diff line number Diff line Loading @@ -72,6 +72,7 @@ import com.android.server.am.PendingIntentController; 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; Loading Loading @@ -159,6 +160,19 @@ class ActivityTestsBase { return display; } /** * 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. */ Loading
services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java +43 −29 Original line number Diff line number Diff line Loading @@ -25,7 +25,6 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMAR 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; Loading Loading @@ -71,10 +70,10 @@ import java.util.Arrays; 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 Loading Loading @@ -399,17 +398,15 @@ public class RootActivityContainerTests extends ActivityTestsBase { */ @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( Loading Loading @@ -509,6 +506,26 @@ public class RootActivityContainerTests extends ActivityTestsBase { verify(mRootActivityContainer, never()).resolveSecondaryHomeActivity(anyInt(), anyInt()); } /** * 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. */ Loading Loading @@ -542,13 +559,7 @@ public class RootActivityContainerTests extends ActivityTestsBase { */ @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()); Loading @@ -575,13 +586,7 @@ public class RootActivityContainerTests extends ActivityTestsBase { */ @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(); Loading Loading @@ -612,13 +617,7 @@ public class RootActivityContainerTests extends ActivityTestsBase { */ @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(); Loading Loading @@ -646,4 +645,19 @@ public class RootActivityContainerTests extends ActivityTestsBase { 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; } }