diff options
4 files changed, 96 insertions, 10 deletions
diff --git a/services/core/java/com/android/server/wm/ActivityStack.java b/services/core/java/com/android/server/wm/ActivityStack.java index 593e5e73a3b9..a84635de32cc 100644 --- a/services/core/java/com/android/server/wm/ActivityStack.java +++ b/services/core/java/com/android/server/wm/ActivityStack.java @@ -1305,8 +1305,17 @@ class ActivityStack extends Task { /** * Make sure that all activities that need to be visible in the stack (that is, they * currently can be seen by the user) actually are and update their configuration. + * @param starting The top most activity in the task. + * The activity is either starting or resuming. + * Caller should ensure starting activity is visible. + * @param preserveWindows Flag indicating whether windows should be preserved when updating + * configuration in {@link mEnsureActivitiesVisibleHelper}. + * @param configChanges Parts of the configuration that changed for this activity for evaluating + * if the screen should be frozen as part of + * {@link mEnsureActivitiesVisibleHelper}. + * */ - void ensureActivitiesVisible(ActivityRecord starting, int configChanges, + void ensureActivitiesVisible(@Nullable ActivityRecord starting, int configChanges, boolean preserveWindows) { ensureActivitiesVisible(starting, configChanges, preserveWindows, true /* notifyClients */); } @@ -1315,9 +1324,19 @@ class ActivityStack extends Task { * Ensure visibility with an option to also update the configuration of visible activities. * @see #ensureActivitiesVisible(ActivityRecord, int, boolean) * @see RootWindowContainer#ensureActivitiesVisible(ActivityRecord, int, boolean) + * @param starting The top most activity in the task. + * The activity is either starting or resuming. + * Caller should ensure starting activity is visible. + * @param notifyClients Flag indicating whether the visibility updates should be sent to the + * clients in {@link mEnsureActivitiesVisibleHelper}. + * @param preserveWindows Flag indicating whether windows should be preserved when updating + * configuration in {@link mEnsureActivitiesVisibleHelper}. + * @param configChanges Parts of the configuration that changed for this activity for evaluating + * if the screen should be frozen as part of + * {@link mEnsureActivitiesVisibleHelper}. */ // TODO: Should be re-worked based on the fact that each task as a stack in most cases. - void ensureActivitiesVisible(ActivityRecord starting, int configChanges, + void ensureActivitiesVisible(@Nullable ActivityRecord starting, int configChanges, boolean preserveWindows, boolean notifyClients) { mTopActivityOccludesKeyguard = false; mTopDismissingKeyguardActivity = null; diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java index 79e8ee3ec54b..bcdd6e39e85c 100644 --- a/services/core/java/com/android/server/wm/ActivityStarter.java +++ b/services/core/java/com/android/server/wm/ActivityStarter.java @@ -1539,7 +1539,10 @@ class ActivityStarter { * * Note: This method should only be called from {@link #startActivityUnchecked}. */ - private int startActivityInner(final ActivityRecord r, ActivityRecord sourceRecord, + + // TODO(b/152429287): Make it easier to exercise code paths through startActivityInner + @VisibleForTesting + int startActivityInner(final ActivityRecord r, ActivityRecord sourceRecord, IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor, int startFlags, boolean doResume, ActivityOptions options, Task inTask, boolean restrictedBgActivity) { @@ -1660,7 +1663,10 @@ class ActivityStarter { // Also, we don't want to resume activities in a task that currently has an overlay // as the starting activity just needs to be in the visible paused state until the // over is removed. - mTargetStack.ensureActivitiesVisible(mStartActivity, 0, !PRESERVE_WINDOWS); + // Passing {@code null} as the start parameter ensures all activities are made + // visible. + mTargetStack.ensureActivitiesVisible(null /* starting */, + 0 /* configChanges */, !PRESERVE_WINDOWS); // Go ahead and tell window manager to execute app transition for this activity // since the app transition will not be triggered through the resume channel. mTargetStack.getDisplay().mDisplayContent.executeAppTransition(); diff --git a/services/core/java/com/android/server/wm/EnsureActivitiesVisibleHelper.java b/services/core/java/com/android/server/wm/EnsureActivitiesVisibleHelper.java index c92de2b84df6..c4e03f5c65f5 100644 --- a/services/core/java/com/android/server/wm/EnsureActivitiesVisibleHelper.java +++ b/services/core/java/com/android/server/wm/EnsureActivitiesVisibleHelper.java @@ -21,6 +21,7 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM; import static com.android.server.wm.ActivityStack.TAG_VISIBILITY; import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_VISIBILITY; +import android.annotation.Nullable; import android.util.Slog; import com.android.internal.util.function.pooled.PooledConsumer; @@ -42,6 +43,16 @@ class EnsureActivitiesVisibleHelper { mContiner = container; } + /** + * Update all attributes except {@link mContiner} to use in subsequent calculations. + * + * @param starting The activity that is being started + * @param configChanges Parts of the configuration that changed for this activity for evaluating + * if the screen should be frozen. + * @param preserveWindows Flag indicating whether windows should be preserved when updating. + * @param notifyClients Flag indicating whether the configuration and visibility changes shoulc + * be sent to the clients. + */ void reset(ActivityRecord starting, int configChanges, boolean preserveWindows, boolean notifyClients) { mStarting = starting; @@ -60,8 +71,17 @@ class EnsureActivitiesVisibleHelper { * Ensure visibility with an option to also update the configuration of visible activities. * @see ActivityStack#ensureActivitiesVisible(ActivityRecord, int, boolean) * @see RootWindowContainer#ensureActivitiesVisible(ActivityRecord, int, boolean) + * @param starting The top most activity in the task. + * The activity is either starting or resuming. + * Caller should ensure starting activity is visible. + * + * @param configChanges Parts of the configuration that changed for this activity for evaluating + * if the screen should be frozen. + * @param preserveWindows Flag indicating whether windows should be preserved when updating. + * @param notifyClients Flag indicating whether the configuration and visibility changes shoulc + * be sent to the clients. */ - void process(ActivityRecord starting, int configChanges, boolean preserveWindows, + void process(@Nullable ActivityRecord starting, int configChanges, boolean preserveWindows, boolean notifyClients) { reset(starting, configChanges, preserveWindows, notifyClients); 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 edc9756d6d0e..02d1f9b43e91 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java @@ -49,6 +49,7 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.spy; import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn; import static com.android.dx.mockito.inline.extended.ExtendedMockito.times; import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify; +import static com.android.server.wm.ActivityStackSupervisor.PRESERVE_WINDOWS; import static com.android.server.wm.WindowContainer.POSITION_BOTTOM; import static com.android.server.wm.WindowContainer.POSITION_TOP; @@ -56,10 +57,10 @@ import static com.google.common.truth.Truth.assertThat; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyInt; -import static org.mockito.ArgumentMatchers.anyObject; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; @@ -99,7 +100,6 @@ import org.junit.runner.RunWith; @Presubmit @RunWith(WindowTestRunner.class) public class ActivityStarterTests extends ActivityTestsBase { - private ActivityStarter mStarter; private ActivityStartController mController; private ActivityMetricsLogger mActivityMetricsLogger; private PackageManagerInternal mMockPackageManager; @@ -127,8 +127,6 @@ public class ActivityStarterTests extends ActivityTestsBase { mController = mock(ActivityStartController.class); mActivityMetricsLogger = mock(ActivityMetricsLogger.class); clearInvocations(mActivityMetricsLogger); - mStarter = new ActivityStarter(mController, mService, mService.mStackSupervisor, - mock(ActivityStartInterceptor.class)); } @Test @@ -181,6 +179,7 @@ public class ActivityStarterTests extends ActivityTestsBase { * {@link ActivityStarter#execute} based on these preconditions and ensures the result matches * the expected. It is important to note that the method also checks side effects of the start, * such as ensuring {@link ActivityOptions#abort()} is called in the relevant scenarios. + * * @param preconditions A bitmask representing the preconditions for the launch * @param launchFlags The launch flags to be provided by the launch {@link Intent}. * @param expectedResult The expected result from the launch. @@ -202,7 +201,7 @@ public class ActivityStarterTests extends ActivityTestsBase { final WindowProcessController wpc = containsConditions(preconditions, PRECONDITION_NO_CALLER_APP) ? null : new WindowProcessController(service, ai, null, 0, -1, null, listener); - doReturn(wpc).when(service).getProcessController(anyObject()); + doReturn(wpc).when(service).getProcessController(any()); final Intent intent = new Intent(); intent.setFlags(launchFlags); @@ -1034,4 +1033,46 @@ public class ActivityStarterTests extends ActivityTestsBase { verify(recentTasks, times(1)).add(any()); } + + @Test + public void testStartActivityInner_allSplitScreenPrimaryActivitiesVisible() { + // Given + final ActivityStarter starter = prepareStarter(0, false); + + starter.setReason("testAllSplitScreenPrimaryActivitiesAreResumed"); + + final ActivityRecord targetRecord = new ActivityBuilder(mService).build(); + targetRecord.setFocusable(false); + targetRecord.setVisibility(false); + final ActivityRecord sourceRecord = new ActivityBuilder(mService).build(); + + final ActivityStack stack = spy( + mRootWindowContainer.getDefaultTaskDisplayArea() + .createStack(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, ACTIVITY_TYPE_STANDARD, + /* onTop */true)); + + stack.addChild(targetRecord); + + doReturn(stack).when(mRootWindowContainer) + .getLaunchStack(any(), any(), any(), anyBoolean(), any(), anyInt(), anyInt()); + + starter.mStartActivity = new ActivityBuilder(mService).build(); + + // When + starter.startActivityInner( + /* r */targetRecord, + /* sourceRecord */ sourceRecord, + /* voiceSession */null, + /* voiceInteractor */ null, + /* startFlags */ 0, + /* doResume */true, + /* options */null, + /* inTask */null, + /* restrictedBgActivity */false); + + // Then + verify(stack).ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS); + verify(targetRecord).makeVisibleIfNeeded(null, true); + assertTrue(targetRecord.mVisibleRequested); + } } |