From dd3592afdcece36f3d197e81b3197b6b74315e84 Mon Sep 17 00:00:00 2001 From: Louis Chang Date: Mon, 5 Nov 2018 11:04:14 +0800 Subject: [PATCH] Fix home can not be started while instrumenting We don't want to automatically start home activities while the home app is being instrumented because it prevents home activities unexpectedly resumed during testing. We should still allow launching home activities if requested (e.g. starting home activity when home key pressed). Bug: 118891218 Test: atest TaplTests Test: atest ActivityStackSupervisorTests Test: atest ActivityManagerMultiDisplayTests Change-Id: Ia362f875d38748a3dea40b5788a4d86bcc68392c --- .../server/wm/ActivityStackSupervisor.java | 14 ++++++-- .../android/server/wm/ActivityStarter.java | 8 ++--- .../wm/ActivityStackSupervisorTests.java | 36 ++++++++++++++++--- 3 files changed, 47 insertions(+), 11 deletions(-) diff --git a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java index 9bcee8a3ab239..9f2dd05454f38 100644 --- a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java +++ b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java @@ -789,7 +789,15 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D return startHomeOnDisplay(mCurrentUser, myReason, displayId); } - boolean canStartHomeOnDisplay(ActivityInfo homeInfo, int displayId) { + /** + * Check if home activity start should be allowed on a display. + * @param homeInfo {@code ActivityInfo} of the home activity that is going to be launched. + * @param displayId The id of the target display. + * @param allowInstrumenting Whether launching home should be allowed if being instrumented. + * @return {@code true} if allow to launch, {@code false} otherwise. + */ + boolean canStartHomeOnDisplay(ActivityInfo homeInfo, int displayId, + boolean allowInstrumenting) { if (mService.mFactoryTest == FactoryTest.FACTORY_TEST_LOW_LEVEL && mService.mTopAction == null) { // We are running in factory test mode, but unable to find the factory test app, so @@ -799,7 +807,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D final WindowProcessController app = mService.getProcessController(homeInfo.processName, homeInfo.applicationInfo.uid); - if (app != null && app.isInstrumenting()) { + if (!allowInstrumenting && app != null && app.isInstrumenting()) { // Don't do this if the home app is currently being instrumented. return false; } @@ -4240,7 +4248,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D return false; } - if (!canStartHomeOnDisplay(aInfo, displayId)) { + if (!canStartHomeOnDisplay(aInfo, displayId, false /* allowInstrumenting */)) { return false; } diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java index afc946b5deb09..83db8de3ff988 100644 --- a/services/core/java/com/android/server/wm/ActivityStarter.java +++ b/services/core/java/com/android/server/wm/ActivityStarter.java @@ -53,6 +53,7 @@ import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_TOP; import static android.view.Display.DEFAULT_DISPLAY; import static android.view.Display.INVALID_DISPLAY; +import static com.android.server.am.EventLogTags.AM_NEW_INTENT; import static com.android.server.wm.ActivityStack.ActivityState.RESUMED; import static com.android.server.wm.ActivityStackSupervisor.DEFER_RESUME; import static com.android.server.wm.ActivityStackSupervisor.ON_TOP; @@ -72,7 +73,6 @@ import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_USER_ import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM; import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME; import static com.android.server.wm.ActivityTaskManagerService.ANIMATE; -import static com.android.server.am.EventLogTags.AM_NEW_INTENT; import static com.android.server.wm.TaskRecord.REPARENT_KEEP_STACK_AT_FRONT; import static com.android.server.wm.TaskRecord.REPARENT_MOVE_STACK_TO_FRONT; @@ -114,9 +114,9 @@ import com.android.internal.app.HeavyWeightSwitcherActivity; import com.android.internal.app.IVoiceInteractor; import com.android.server.am.EventLogTags; import com.android.server.am.PendingIntentRecord; +import com.android.server.pm.InstantAppResolver; import com.android.server.wm.ActivityStackSupervisor.PendingActivityLaunch; import com.android.server.wm.LaunchParamsController.LaunchParams; -import com.android.server.pm.InstantAppResolver; import java.io.PrintWriter; import java.text.DateFormat; @@ -1284,8 +1284,8 @@ class ActivityStarter { // Do not start home activity if it cannot be launched on preferred display. We are not // doing this in ActivityStackSupervisor#canPlaceEntityOnDisplay because it might // fallback to launch on other displays. - if (r.isActivityTypeHome() - && !mSupervisor.canStartHomeOnDisplay(r.info, mPreferredDisplayId)) { + if (r.isActivityTypeHome() && !mSupervisor.canStartHomeOnDisplay(r.info, + mPreferredDisplayId, true /* allowInstrumenting */)) { Slog.w(TAG, "Cannot launch home on display " + mPreferredDisplayId); return START_CANCELED; } diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStackSupervisorTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStackSupervisorTests.java index c2ef478406e73..f692a571b0193 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ActivityStackSupervisorTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStackSupervisorTests.java @@ -25,12 +25,12 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN_OR_SPLIT import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED; import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY; import static android.content.pm.ActivityInfo.FLAG_ALWAYS_FOCUSABLE; +import static android.view.Display.DEFAULT_DISPLAY; import static com.android.server.wm.ActivityDisplay.POSITION_TOP; import static com.android.server.wm.ActivityStack.REMOVE_TASK_MODE_DESTROYING; import static com.android.server.wm.ActivityStackSupervisor.MATCH_TASK_IN_STACKS_OR_RECENT_TASKS_AND_RESTORE; - import static com.google.common.truth.Truth.assertThat; import static org.junit.Assert.assertEquals; @@ -54,6 +54,8 @@ import static org.mockito.Mockito.verify; import android.app.ActivityOptions; import android.app.WaitResult; +import android.content.pm.ActivityInfo; +import android.content.pm.ApplicationInfo; import android.graphics.Rect; import android.platform.test.annotations.Presubmit; @@ -436,7 +438,7 @@ public class ActivityStackSupervisorTests extends ActivityTestsBase { * Tests that home activities can be started on the displays that supports system decorations. */ @Test - public void testStartHomeOnAllDisplays() throws Exception { + public void testStartHomeOnAllDisplays() { // Create secondary displays. final TestActivityDisplay secondDisplay = spy(createNewActivityDisplay()); mSupervisor.addChild(secondDisplay, POSITION_TOP); @@ -450,7 +452,7 @@ public class ActivityStackSupervisorTests extends ActivityTestsBase { .create(any(), anyInt(), any(), any(), any(), any()); doReturn(true).when(mService.mStackSupervisor) .ensureVisibilityAndConfig(any(), anyInt(), anyBoolean(), anyBoolean()); - doReturn(true).when(mSupervisor).canStartHomeOnDisplay(any(), anyInt()); + doReturn(true).when(mSupervisor).canStartHomeOnDisplay(any(), anyInt(), anyBoolean()); mSupervisor.startHomeOnAllDisplays(0, "testStartHome"); @@ -463,7 +465,7 @@ public class ActivityStackSupervisorTests extends ActivityTestsBase { * Tests that home activities won't be started before booting when display added. */ @Test - public void testNotStartHomeBeforeBoot() throws Exception { + public void testNotStartHomeBeforeBoot() { final int displayId = 1; final boolean isBooting = mService.mAmInternal.isBooting(); final boolean isBooted = mService.mAmInternal.isBooted(); @@ -477,4 +479,30 @@ public class ActivityStackSupervisorTests extends ActivityTestsBase { mService.mAmInternal.setBooted(isBooted); } } + + /** + * Tests whether home can be started if being instrumented. + */ + @Test + public void testCanStartHomeWhenInstrumented() { + final ActivityInfo info = new ActivityInfo(); + info.applicationInfo = new ApplicationInfo(); + final WindowProcessController app = mock(WindowProcessController.class); + doReturn(app).when(mService).getProcessController(any(), anyInt()); + + // Can not start home if we don't want to start home while home is being instrumented. + doReturn(true).when(app).isInstrumenting(); + assertFalse(mSupervisor.canStartHomeOnDisplay(info, DEFAULT_DISPLAY, + false /* allowInstrumenting*/)); + + // Can start home for other cases. + assertTrue(mSupervisor.canStartHomeOnDisplay(info, DEFAULT_DISPLAY, + true /* allowInstrumenting*/)); + + doReturn(false).when(app).isInstrumenting(); + assertTrue(mSupervisor.canStartHomeOnDisplay(info, DEFAULT_DISPLAY, + false /* allowInstrumenting*/)); + assertTrue(mSupervisor.canStartHomeOnDisplay(info, DEFAULT_DISPLAY, + true /* allowInstrumenting*/)); + } }