summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerService.java3
-rw-r--r--services/core/java/com/android/server/am/ActivityStackSupervisor.java110
-rw-r--r--services/core/java/com/android/server/am/ActivityStartController.java7
-rw-r--r--services/core/java/com/android/server/am/ActivityTaskManagerService.java77
-rw-r--r--services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java5
-rw-r--r--services/tests/servicestests/src/com/android/server/am/ActivityStackSupervisorTests.java33
-rw-r--r--services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java44
7 files changed, 175 insertions, 104 deletions
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index e8c6365b38cb..c6fdf15d67e2 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -129,7 +129,6 @@ import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_CLEANUP;
import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_CONFIGURATION;
-import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_LOCKTASK;
import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_SWITCH;
import static com.android.server.am.ActivityTaskManagerDebugConfig.POSTFIX_CONFIGURATION;
import static com.android.server.am.ActivityTaskManagerDebugConfig.POSTFIX_LOCKTASK;
@@ -8380,7 +8379,7 @@ public class ActivityManagerService extends IActivityManager.Stub
throw e.rethrowAsRuntimeException();
}
}
- mAtmInternal.startHomeActivity(currentUserId, "systemReady");
+ mAtmInternal.startHomeOnAllDisplays(currentUserId, "systemReady");
mAtmInternal.showSystemReadyErrorDialogsIfNeeded();
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 17454b42524c..87226bf15ecf 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -44,6 +44,7 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECOND
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import static android.app.WindowConfiguration.activityTypeToString;
import static android.app.WindowConfiguration.windowingModeToString;
+import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_INSTANCE;
import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_TASK;
import static android.content.pm.PackageManager.NOTIFY_PACKAGE_USE_ACTIVITY;
@@ -115,8 +116,8 @@ import android.app.ActivityManager.RunningTaskInfo;
import android.app.ActivityManager.StackInfo;
import android.app.ActivityManagerInternal;
import android.app.ActivityOptions;
+import android.app.AppGlobals;
import android.app.AppOpsManager;
-import android.app.IApplicationThread;
import android.app.ProfilerInfo;
import android.app.ResultInfo;
import android.app.WaitResult;
@@ -146,6 +147,7 @@ import android.hardware.power.V1_0.PowerHint;
import android.os.Binder;
import android.os.Bundle;
import android.os.Debug;
+import android.os.FactoryTest;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
@@ -786,10 +788,24 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
r.moveFocusableActivityToTop(myReason);
return resumeFocusedStacksTopActivitiesLocked(r.getStack(), prev, null);
}
- return mService.startHomeActivityLocked(mCurrentUser, myReason, displayId);
+ return startHomeOnDisplay(mCurrentUser, myReason, displayId);
}
- boolean canStartHomeOnDisplay(ActivityInfo homeActivity, int displayId) {
+ boolean canStartHomeOnDisplay(ActivityInfo homeInfo, int displayId) {
+ 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
+ // just sit around displaying the error message and don't try to start anything.
+ return false;
+ }
+
+ final WindowProcessController app =
+ mService.getProcessController(homeInfo.processName, homeInfo.applicationInfo.uid);
+ if (app != null && app.isInstrumenting()) {
+ // Don't do this if the home app is currently being instrumented.
+ return false;
+ }
+
if (displayId == DEFAULT_DISPLAY || (displayId != INVALID_DISPLAY
&& displayId == mService.mVr2dDisplayId)) {
// No restrictions to default display or vr 2d display.
@@ -802,8 +818,8 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
return false;
}
- final boolean supportMultipleInstance = homeActivity.launchMode != LAUNCH_SINGLE_TASK
- && homeActivity.launchMode != LAUNCH_SINGLE_INSTANCE;
+ final boolean supportMultipleInstance = homeInfo.launchMode != LAUNCH_SINGLE_TASK
+ && homeInfo.launchMode != LAUNCH_SINGLE_INSTANCE;
if (!supportMultipleInstance) {
// Can't launch home on other displays if it requested to be single instance.
return false;
@@ -1037,12 +1053,14 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
final ActivityDisplay display = mActivityDisplays.get(displayNdx);
for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
+ // We cannot only check the top stack on each display since there might have
+ // always-on-top stacks (e.g. pinned stack).
final ActivityStack stack = display.getChildAt(stackNdx);
- if (!isTopDisplayFocusedStack(stack) || stack.numActivities() == 0) {
+ if (stack.numActivities() == 0) {
continue;
}
final ActivityRecord resumedActivity = stack.getResumedActivity();
- if (resumedActivity == null || !resumedActivity.idle) {
+ if (resumedActivity != null && !resumedActivity.idle) {
if (DEBUG_STATES) Slog.d(TAG_STATES, "allResumedActivitiesIdle: stack="
+ stack.mStackId + " " + resumedActivity + " not idle");
return false;
@@ -1895,7 +1913,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
}
/**
- * Called when the frontmost task is idle.
+ * Called when all resumed tasks/stacks are idle.
* @return the state of mService.mAm.mBooting before this was called.
*/
@GuardedBy("mService")
@@ -1950,7 +1968,9 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
r.idle = true;
//Slog.i(TAG, "IDLE: mBooted=" + mBooted + ", fromTimeout=" + fromTimeout);
- if (isTopDisplayFocusedStack(r.getStack()) || fromTimeout) {
+
+ // Make sure we can finish booting when all resumed activities are idle.
+ if ((!mService.isBooted() && allResumedActivitiesIdle()) || fromTimeout) {
booting = checkFinishBootingLocked();
}
@@ -4107,7 +4127,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
if (DEBUG_STACK) Slog.v(TAG, "Display added displayId=" + displayId);
synchronized (mService.mGlobalLock) {
getActivityDisplayOrCreateLocked(displayId);
- mService.startHomeActivityLocked(mCurrentUser, "displayAdded", displayId);
+ startHomeOnDisplay(mCurrentUser, "displayAdded", displayId);
}
}
@@ -4185,6 +4205,76 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
return activityDisplay;
}
+ boolean startHomeOnAllDisplays(int userId, String reason) {
+ boolean homeStarted = false;
+ for (int i = mActivityDisplays.size() - 1; i >= 0; i--) {
+ final int displayId = mActivityDisplays.get(i).mDisplayId;
+ homeStarted |= startHomeOnDisplay(userId, reason, displayId);
+ }
+ return homeStarted;
+ }
+
+ /**
+ * This starts home activity on displays that can have system decorations and only if the
+ * home activity can have multiple instances.
+ */
+ boolean startHomeOnDisplay(int userId, String reason, int displayId) {
+ final Intent homeIntent = mService.getHomeIntent();
+ final ActivityInfo aInfo = resolveHomeActivity(userId, homeIntent);
+ if (aInfo == null) {
+ return false;
+ }
+
+ if (!canStartHomeOnDisplay(aInfo, displayId)) {
+ return false;
+ }
+
+ // Update the reason for ANR debugging to verify if the user activity is the one that
+ // actually launched.
+ final String myReason = reason + ":" + userId + ":" + UserHandle.getUserId(
+ aInfo.applicationInfo.uid);
+ mService.getActivityStartController().startHomeActivity(homeIntent, aInfo, myReason,
+ displayId);
+ return true;
+ }
+
+ /**
+ * This resolves the home activity info and updates the home component of the given intent.
+ * @return the home activity info if any.
+ */
+ private ActivityInfo resolveHomeActivity(int userId, Intent homeIntent) {
+ final int flags = ActivityManagerService.STOCK_PM_FLAGS;
+ final ComponentName comp = homeIntent.getComponent();
+ ActivityInfo aInfo = null;
+ try {
+ if (comp != null) {
+ // Factory test.
+ aInfo = AppGlobals.getPackageManager().getActivityInfo(comp, flags, userId);
+ } else {
+ final String resolvedType =
+ homeIntent.resolveTypeIfNeeded(mService.mContext.getContentResolver());
+ final ResolveInfo info = AppGlobals.getPackageManager()
+ .resolveIntent(homeIntent, resolvedType, flags, userId);
+ if (info != null) {
+ aInfo = info.activityInfo;
+ }
+ }
+ } catch (RemoteException e) {
+ // ignore
+ }
+
+ if (aInfo == null) {
+ Slog.wtf(TAG, "No home screen found for " + homeIntent, new Throwable());
+ return null;
+ }
+
+ homeIntent.setComponent(new ComponentName(aInfo.applicationInfo.packageName, aInfo.name));
+ aInfo = new ActivityInfo(aInfo);
+ aInfo.applicationInfo = mService.getAppInfoForUser(aInfo.applicationInfo, userId);
+ homeIntent.setFlags(homeIntent.getFlags() | FLAG_ACTIVITY_NEW_TASK);
+ return aInfo;
+ }
+
@VisibleForTesting
void addChild(ActivityDisplay activityDisplay, int position) {
positionChildAt(activityDisplay, position);
diff --git a/services/core/java/com/android/server/am/ActivityStartController.java b/services/core/java/com/android/server/am/ActivityStartController.java
index 20d5ab201307..3151ec9c1b83 100644
--- a/services/core/java/com/android/server/am/ActivityStartController.java
+++ b/services/core/java/com/android/server/am/ActivityStartController.java
@@ -20,8 +20,8 @@ import static android.app.ActivityManager.START_SUCCESS;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
-
import static android.os.FactoryTest.FACTORY_TEST_LOW_LEVEL;
+
import static com.android.server.am.ActivityTaskManagerDebugConfig.TAG_ATM;
import static com.android.server.am.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME;
@@ -35,7 +35,6 @@ import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.os.Binder;
-import android.os.FactoryTest;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
@@ -167,10 +166,6 @@ public class ActivityStartController {
}
void startHomeActivity(Intent intent, ActivityInfo aInfo, String reason, int displayId) {
- if (!mSupervisor.canStartHomeOnDisplay(aInfo, displayId)) {
- return;
- }
-
final ActivityOptions options = ActivityOptions.makeBasic();
options.setLaunchWindowingMode(WINDOWING_MODE_FULLSCREEN);
options.setLaunchActivityType(ACTIVITY_TYPE_HOME);
diff --git a/services/core/java/com/android/server/am/ActivityTaskManagerService.java b/services/core/java/com/android/server/am/ActivityTaskManagerService.java
index 5b0a4a9b0596..5e3c1da2310b 100644
--- a/services/core/java/com/android/server/am/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityTaskManagerService.java
@@ -85,13 +85,10 @@ import static com.android.server.am.ActivityManagerServiceDumpProcessesProto.HEA
import static com.android.server.am.ActivityManagerServiceDumpProcessesProto.HOME_PROC;
import static com.android.server.am.ActivityManagerServiceDumpProcessesProto.LAUNCHING_ACTIVITY;
import static com.android.server.am.ActivityManagerServiceDumpProcessesProto.PREVIOUS_PROC;
-import static com.android.server.am.ActivityManagerServiceDumpProcessesProto
- .PREVIOUS_PROC_VISIBLE_TIME_MS;
+import static com.android.server.am.ActivityManagerServiceDumpProcessesProto.PREVIOUS_PROC_VISIBLE_TIME_MS;
import static com.android.server.am.ActivityManagerServiceDumpProcessesProto.SCREEN_COMPAT_PACKAGES;
-import static com.android.server.am.ActivityManagerServiceDumpProcessesProto.ScreenCompatPackage
- .MODE;
-import static com.android.server.am.ActivityManagerServiceDumpProcessesProto.ScreenCompatPackage
- .PACKAGE;
+import static com.android.server.am.ActivityManagerServiceDumpProcessesProto.ScreenCompatPackage.MODE;
+import static com.android.server.am.ActivityManagerServiceDumpProcessesProto.ScreenCompatPackage.PACKAGE;
import static com.android.server.am.ActivityStack.REMOVE_TASK_MODE_DESTROYING;
import static com.android.server.am.ActivityStackSupervisor.DEFER_RESUME;
import static com.android.server.am.ActivityStackSupervisor.MATCH_TASK_IN_STACKS_ONLY;
@@ -5353,65 +5350,6 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
return intent;
}
- /**
- * This starts home activity on displays that can have system decorations and only if the
- * home activity can have multiple instances.
- */
- boolean startHomeActivityLocked(int userId, String reason, int displayId) {
- if (mFactoryTest == FactoryTest.FACTORY_TEST_LOW_LEVEL && mTopAction == null) {
- // We are running in factory test mode, but unable to find the factory test app, so just
- // sit around displaying the error message and don't try to start anything.
- return false;
- }
-
- final Intent intent = getHomeIntent();
- ActivityInfo aInfo = resolveActivityInfo(intent, STOCK_PM_FLAGS, userId);
- if (aInfo != null) {
- intent.setComponent(new ComponentName(aInfo.applicationInfo.packageName, aInfo.name));
- // Don't do this if the home app is currently being instrumented.
- aInfo = new ActivityInfo(aInfo);
- aInfo.applicationInfo = getAppInfoForUser(aInfo.applicationInfo, userId);
- WindowProcessController app =
- getProcessController(aInfo.processName, aInfo.applicationInfo.uid);
- if (app == null || !app.isInstrumenting()) {
- intent.setFlags(intent.getFlags() | FLAG_ACTIVITY_NEW_TASK);
- final int resolvedUserId = UserHandle.getUserId(aInfo.applicationInfo.uid);
- // For ANR debugging to verify if the user activity is the one that actually
- // launched.
- final String myReason = reason + ":" + userId + ":" + resolvedUserId;
- getActivityStartController().startHomeActivity(intent, aInfo, myReason, displayId);
- }
- } else {
- Slog.wtf(TAG, "No home screen found for " + intent, new Throwable());
- }
-
- return true;
- }
-
- private ActivityInfo resolveActivityInfo(Intent intent, int flags, int userId) {
- ActivityInfo ai = null;
- final ComponentName comp = intent.getComponent();
- try {
- if (comp != null) {
- // Factory test.
- ai = AppGlobals.getPackageManager().getActivityInfo(comp, flags, userId);
- } else {
- ResolveInfo info = AppGlobals.getPackageManager().resolveIntent(
- intent,
- intent.resolveTypeIfNeeded(mContext.getContentResolver()),
- flags, userId);
-
- if (info != null) {
- ai = info.activityInfo;
- }
- }
- } catch (RemoteException e) {
- // ignore
- }
-
- return ai;
- }
-
ApplicationInfo getAppInfoForUser(ApplicationInfo info, int userId) {
if (info == null) return null;
ApplicationInfo newInfo = new ApplicationInfo(info);
@@ -6127,7 +6065,14 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
@Override
public boolean startHomeActivity(int userId, String reason) {
synchronized (mGlobalLock) {
- return startHomeActivityLocked(userId, reason, DEFAULT_DISPLAY);
+ return mStackSupervisor.startHomeOnDisplay(userId, reason, DEFAULT_DISPLAY);
+ }
+ }
+
+ @Override
+ public boolean startHomeOnAllDisplays(int userId, String reason) {
+ synchronized (mGlobalLock) {
+ return mStackSupervisor.startHomeOnAllDisplays(userId, reason);
}
}
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java b/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java
index b011da60b210..caa2da3f5125 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java
@@ -33,8 +33,8 @@ import android.os.RemoteException;
import android.os.SystemClock;
import android.service.voice.IVoiceInteractionSession;
import android.util.SparseIntArray;
-
import android.util.proto.ProtoOutputStream;
+
import com.android.internal.app.IVoiceInteractor;
import com.android.server.am.ActivityServiceConnectionsHolder;
import com.android.server.am.PendingIntentRecord;
@@ -48,7 +48,6 @@ import java.io.PrintWriter;
import java.lang.ref.WeakReference;
import java.util.List;
import java.util.Set;
-import java.util.function.Predicate;
/**
* Activity Task manager local system service interface.
@@ -348,6 +347,8 @@ public abstract class ActivityTaskManagerInternal {
/** @return The intent used to launch the home activity. */
public abstract Intent getHomeIntent();
public abstract boolean startHomeActivity(int userId, String reason);
+ /** Start home activities on all displays that support system decorations. */
+ public abstract boolean startHomeOnAllDisplays(int userId, String reason);
/** @return true if the given process is the factory test process. */
public abstract boolean isFactoryTestProcess(WindowProcessController wpc);
public abstract void updateTopComponentForFactoryTest();
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityStackSupervisorTests.java b/services/tests/servicestests/src/com/android/server/am/ActivityStackSupervisorTests.java
index bdceec79eb29..8ab22105c3ae 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityStackSupervisorTests.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityStackSupervisorTests.java
@@ -26,16 +26,21 @@ 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 com.android.server.am.ActivityDisplay.POSITION_TOP;
import static com.android.server.am.ActivityStack.REMOVE_TASK_MODE_DESTROYING;
import static com.android.server.am.ActivityStackSupervisor.MATCH_TASK_IN_STACKS_OR_RECENT_TASKS_AND_RESTORE;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
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.contains;
import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
@@ -427,4 +432,32 @@ public class ActivityStackSupervisorTests extends ActivityTestsBase {
verify(targetStack, times(1)).resumeTopActivityUncheckedLocked(
eq(activity), eq(null /* targetOptions */));
}
+
+
+ /**
+ * Tests that home activities can be started on the displays that supports system decorations.
+ */
+ @Test
+ public void testStartHomeOnAllDisplays() throws Exception {
+ // Create secondary displays.
+ final TestActivityDisplay secondDisplay = spy(createNewActivityDisplay());
+ mSupervisor.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());
+ doReturn(true).when(mService.mStackSupervisor)
+ .ensureVisibilityAndConfig(any(), anyInt(), anyBoolean(), anyBoolean());
+ doReturn(true).when(mSupervisor).canStartHomeOnDisplay(any(), anyInt());
+
+ mSupervisor.startHomeOnAllDisplays(0, "testStartHome");
+
+ assertTrue(mSupervisor.getDefaultDisplay().getTopStack().isActivityTypeHome());
+ assertNotNull(secondDisplay.getTopStack());
+ assertTrue(secondDisplay.getTopStack().isActivityTypeHome());
+ }
}
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 adf861b8d936..57960efee3c7 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java
@@ -170,6 +170,7 @@ public class ActivityTestsBase {
// Makes sure the supervisor is using with the spy object.
atm.mStackSupervisor.setService(atm);
doReturn(mock(IPackageManager.class)).when(am).getPackageManager();
+ doReturn(mock(IPackageManager.class)).when(atm).getPackageManager();
PackageManagerInternal mockPackageManager = mock(PackageManagerInternal.class);
doReturn(mockPackageManager).when(am).getPackageManagerInternalLocked();
doReturn(null).when(mockPackageManager).getDefaultHomeActivity(anyInt());
@@ -417,6 +418,10 @@ public class ActivityTestsBase {
private ActivityTaskManagerInternal mInternal;
private PackageManagerInternal mPmInternal;
+ // ActivityStackSupervisor may be created more than once while setting up AMS and ATMS.
+ // We keep the reference in order to prevent creating it twice.
+ private ActivityStackSupervisor mTestStackSupervisor;
+
TestActivityTaskManagerService(Context context) {
super(context);
mSupportsMultiWindow = true;
@@ -447,24 +452,27 @@ public class ActivityTestsBase {
@Override
final protected ActivityStackSupervisor createStackSupervisor() {
- final ActivityStackSupervisor supervisor = spy(createTestSupervisor());
- final KeyguardController keyguardController = mock(KeyguardController.class);
-
- // Invoked during {@link ActivityStack} creation.
- doNothing().when(supervisor).updateUIDsPresentOnDisplay();
- // Always keep things awake.
- doReturn(true).when(supervisor).hasAwakeDisplay();
- // Called when moving activity to pinned stack.
- doNothing().when(supervisor).ensureActivitiesVisibleLocked(any(), anyInt(), anyBoolean());
- // Do not schedule idle timeouts
- doNothing().when(supervisor).scheduleIdleTimeoutLocked(any());
- // unit test version does not handle launch wake lock
- doNothing().when(supervisor).acquireLaunchWakelock();
- doReturn(keyguardController).when(supervisor).getKeyguardController();
-
- supervisor.initialize();
-
- return supervisor;
+ if (mTestStackSupervisor == null) {
+ final ActivityStackSupervisor supervisor = spy(createTestSupervisor());
+ final KeyguardController keyguardController = mock(KeyguardController.class);
+
+ // Invoked during {@link ActivityStack} creation.
+ doNothing().when(supervisor).updateUIDsPresentOnDisplay();
+ // Always keep things awake.
+ doReturn(true).when(supervisor).hasAwakeDisplay();
+ // Called when moving activity to pinned stack.
+ doNothing().when(supervisor).ensureActivitiesVisibleLocked(any(), anyInt(),
+ anyBoolean());
+ // Do not schedule idle timeouts
+ doNothing().when(supervisor).scheduleIdleTimeoutLocked(any());
+ // unit test version does not handle launch wake lock
+ doNothing().when(supervisor).acquireLaunchWakelock();
+ doReturn(keyguardController).when(supervisor).getKeyguardController();
+
+ supervisor.initialize();
+ mTestStackSupervisor = supervisor;
+ }
+ return mTestStackSupervisor;
}
protected ActivityStackSupervisor createTestSupervisor() {