Unify WM test setup for system services (47/n)
Needed before we can unify objects in hierarchy.
Bug: 80414790
Bug: 122846381
Test: Existing test pass
Change-Id: Ib3bca1f7ad2b15b5426d198d3c5608e3cba640f7
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 19c818f..d759be2 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -1480,8 +1480,9 @@
public ActivityTaskManagerService mActivityTaskManager;
@VisibleForTesting
public ActivityTaskManagerInternal mAtmInternal;
+ UriGrantsManagerInternal mUgmInternal;
@VisibleForTesting
- public UriGrantsManagerInternal mUgmInternal;
+ public final ActivityManagerInternal mInternal;
final ActivityThread mSystemThread;
private final class AppDeathRecipient implements IBinder.DeathRecipient {
@@ -2413,6 +2414,8 @@
mProcStartHandler = null;
mHiddenApiBlacklist = null;
mFactoryTest = FACTORY_TEST_OFF;
+ mUgmInternal = LocalServices.getService(UriGrantsManagerInternal.class);
+ mInternal = new LocalService();
}
// Note: This method is invoked on the main thread but may need to attach various
@@ -2566,6 +2569,7 @@
Slog.w(TAG, "Setting background thread cpuset failed");
}
+ mInternal = new LocalService();
}
public void setSystemServiceManager(SystemServiceManager mgr) {
@@ -2583,7 +2587,7 @@
mBatteryStatsService.publish();
mAppOpsService.publish(mContext);
Slog.d("AppOps", "AppOpsService published");
- LocalServices.addService(ActivityManagerInternal.class, new LocalService());
+ LocalServices.addService(ActivityManagerInternal.class, mInternal);
mActivityTaskManager.onActivityManagerInternalAdded();
mUgmInternal.onActivityManagerInternalAdded();
mPendingIntentController.onActivityManagerInternalAdded();
diff --git a/services/core/java/com/android/server/wm/ActivityDisplay.java b/services/core/java/com/android/server/wm/ActivityDisplay.java
index f1cd721..5a0dfd0 100644
--- a/services/core/java/com/android/server/wm/ActivityDisplay.java
+++ b/services/core/java/com/android/server/wm/ActivityDisplay.java
@@ -41,6 +41,7 @@
import static com.android.server.am.ActivityDisplayProto.SINGLE_TASK_INSTANCE;
import static com.android.server.am.ActivityDisplayProto.STACKS;
import static com.android.server.wm.ActivityStack.ActivityState.RESUMED;
+import static com.android.server.wm.ActivityStack.REMOVE_TASK_MODE_DESTROYING;
import static com.android.server.wm.ActivityStack.STACK_VISIBILITY_VISIBLE;
import static com.android.server.wm.ActivityStackSupervisor.TAG_TASKS;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_STACK;
@@ -173,18 +174,10 @@
mService = root.mService;
mDisplayId = display.getDisplayId();
mDisplay = display;
- mDisplayContent = createDisplayContent();
+ mDisplayContent = mService.mWindowManager.mRoot.createDisplayContent(mDisplay, this);
mDisplayContent.reconfigureDisplayLocked();
- updateBounds();
- }
-
- protected DisplayContent createDisplayContent() {
- return mService.mWindowManager.mRoot.createDisplayContent(mDisplay, this);
- }
-
- private void updateBounds() {
- mDisplay.getRealSize(mTmpDisplaySize);
- setBounds(0, 0, mTmpDisplaySize.x, mTmpDisplaySize.y);
+ onRequestedOverrideConfigurationChanged(
+ mDisplayContent.getRequestedOverrideConfiguration());
}
void onDisplayChanged() {
@@ -200,7 +193,8 @@
}
}
- updateBounds();
+ mDisplay.getRealSize(mTmpDisplaySize);
+ setBounds(0, 0, mTmpDisplaySize.x, mTmpDisplaySize.y);
if (mDisplayContent != null) {
mDisplayContent.updateDisplayInfo();
mService.mWindowManager.requestTraversal();
@@ -1541,6 +1535,17 @@
return mSingleTaskInstance;
}
+ @VisibleForTesting
+ void removeAllTasks() {
+ for (int i = getChildCount() - 1; i >= 0; --i) {
+ final ActivityStack stack = getChildAt(i);
+ final ArrayList<TaskRecord> tasks = stack.getAllTasks();
+ for (int j = tasks.size() - 1; j >= 0; --j) {
+ stack.removeTask(tasks.get(j), "removeAllTasks", REMOVE_TASK_MODE_DESTROYING);
+ }
+ }
+ }
+
public void dump(PrintWriter pw, String prefix) {
pw.println(prefix + "displayId=" + mDisplayId + " stacks=" + mStacks.size()
+ (mSingleTaskInstance ? " mSingleTaskInstance" : ""));
diff --git a/services/core/java/com/android/server/wm/ActivityStack.java b/services/core/java/com/android/server/wm/ActivityStack.java
index 12eab50..b7f8d76 100644
--- a/services/core/java/com/android/server/wm/ActivityStack.java
+++ b/services/core/java/com/android/server/wm/ActivityStack.java
@@ -2813,7 +2813,7 @@
// Launching this app's activity, make sure the app is no longer
// considered stopped.
try {
- AppGlobals.getPackageManager().setPackageStoppedState(
+ mService.getPackageManager().setPackageStoppedState(
next.packageName, false, next.mUserId); /* TODO: Verify if correct userid */
} catch (RemoteException e1) {
} catch (IllegalArgumentException e) {
diff --git a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
index 1c56a10..9639125 100644
--- a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
@@ -250,7 +250,7 @@
RecentTasks mRecentTasks;
/** Helper class to abstract out logic for fetching the set of currently running tasks */
- RunningTasks mRunningTasks;
+ private RunningTasks mRunningTasks;
final ActivityStackSupervisorHandler mHandler;
final Looper mLooper;
@@ -444,7 +444,7 @@
}
mInitialized = true;
- mRunningTasks = createRunningTasks();
+ setRunningTasks(new RunningTasks());
mActivityMetricsLogger = new ActivityMetricsLogger(this, mService.mContext,
mHandler.getLooper());
@@ -485,13 +485,20 @@
}
void setRecentTasks(RecentTasks recentTasks) {
+ if (mRecentTasks != null) {
+ mRecentTasks.unregisterCallback(this);
+ }
mRecentTasks = recentTasks;
mRecentTasks.registerCallback(this);
}
@VisibleForTesting
- RunningTasks createRunningTasks() {
- return new RunningTasks();
+ void setRunningTasks(RunningTasks runningTasks) {
+ mRunningTasks = runningTasks;
+ }
+
+ RunningTasks getRunningTasks() {
+ return mRunningTasks;
}
/**
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index a3ab27e..88b330b 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -43,7 +43,6 @@
import static android.content.pm.ConfigurationInfo.GL_ES_VERSION_UNDEFINED;
import static android.content.pm.PackageManager.FEATURE_ACTIVITIES_ON_SECONDARY_DISPLAYS;
import static android.content.pm.PackageManager.FEATURE_FREEFORM_WINDOW_MANAGEMENT;
-import static android.content.pm.PackageManager.FEATURE_PC;
import static android.content.pm.PackageManager.FEATURE_PICTURE_IN_PICTURE;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static android.content.res.Configuration.UI_MODE_TYPE_TELEVISION;
@@ -361,7 +360,7 @@
/* Global service lock used by the package the owns this service. */
final WindowManagerGlobalLock mGlobalLock = new WindowManagerGlobalLock();
/**
- * It is the same instance as {@link mGlobalLock}, just declared as a type that the
+ * It is the same instance as {@link #mGlobalLock}, just declared as a type that the
* locked-region-code-injection does't recognize it. It is used to skip wrapping priority
* booster for places that are already in the scope of another booster (e.g. computing oom-adj).
*
@@ -730,7 +729,6 @@
final boolean forceRtl = Settings.Global.getInt(resolver, DEVELOPMENT_FORCE_RTL, 0) != 0;
final boolean forceResizable = Settings.Global.getInt(
resolver, DEVELOPMENT_FORCE_RESIZABLE_ACTIVITIES, 0) != 0;
- final boolean isPc = mContext.getPackageManager().hasSystemFeature(FEATURE_PC);
// Transfer any global setting for forcing RTL layout, into a System Property
DisplayProperties.debug_force_rtl(forceRtl);
@@ -761,10 +759,6 @@
mSupportsPictureInPicture = false;
mSupportsMultiDisplay = false;
}
- mWindowManager.setForceResizableTasks(mForceResizableActivities);
- mWindowManager.setSupportsPictureInPicture(mSupportsPictureInPicture);
- mWindowManager.setSupportsFreeformWindowManagement(mSupportsFreeformWindowManagement);
- mWindowManager.setIsPc(isPc);
mWindowManager.mRoot.onSettingsRetrieved();
// This happens before any activities are started, so we can change global configuration
// in-place.
@@ -821,8 +815,7 @@
new TaskChangeNotificationController(mGlobalLock, mStackSupervisor, mH);
mLockTaskController = new LockTaskController(mContext, mStackSupervisor, mH);
mActivityStartController = new ActivityStartController(this);
- mRecentTasks = createRecentTasks();
- mStackSupervisor.setRecentTasks(mRecentTasks);
+ setRecentTasks(new RecentTasks(this, mStackSupervisor));
mVrController = new VrController(mGlobalLock);
mKeyguardController = mStackSupervisor.getKeyguardController();
}
@@ -890,8 +883,10 @@
return mode == AppOpsManager.MODE_ALLOWED;
}
- protected RecentTasks createRecentTasks() {
- return new RecentTasks(this, mStackSupervisor);
+ @VisibleForTesting
+ protected void setRecentTasks(RecentTasks recentTasks) {
+ mRecentTasks = recentTasks;
+ mStackSupervisor.setRecentTasks(recentTasks);
}
RecentTasks getRecentTasks() {
diff --git a/services/core/java/com/android/server/wm/DisplayRotation.java b/services/core/java/com/android/server/wm/DisplayRotation.java
index 282ed42..410cc94 100644
--- a/services/core/java/com/android/server/wm/DisplayRotation.java
+++ b/services/core/java/com/android/server/wm/DisplayRotation.java
@@ -295,7 +295,8 @@
false /* forceRelayout */);
}
- private void setUserRotation(int userRotationMode, int userRotation) {
+ @VisibleForTesting
+ void setUserRotation(int userRotationMode, int userRotation) {
if (isDefaultDisplay) {
// We'll be notified via settings listener, so we don't need to update internal values.
final ContentResolver res = mContext.getContentResolver();
diff --git a/services/core/java/com/android/server/wm/DisplayWindowSettings.java b/services/core/java/com/android/server/wm/DisplayWindowSettings.java
index 207e8ef..8507918 100644
--- a/services/core/java/com/android/server/wm/DisplayWindowSettings.java
+++ b/services/core/java/com/android/server/wm/DisplayWindowSettings.java
@@ -275,14 +275,14 @@
// This display used to be in freeform, but we don't support freeform anymore, so fall
// back to fullscreen.
if (windowingMode == WindowConfiguration.WINDOWING_MODE_FREEFORM
- && !mService.mSupportsFreeformWindowManagement) {
+ && !mService.mAtmService.mSupportsFreeformWindowManagement) {
return WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
}
// No record is present so use default windowing mode policy.
if (windowingMode == WindowConfiguration.WINDOWING_MODE_UNDEFINED) {
final boolean forceDesktopMode = mService.mForceDesktopModeOnExternalDisplays
&& displayId != Display.DEFAULT_DISPLAY;
- windowingMode = mService.mSupportsFreeformWindowManagement
+ windowingMode = mService.mAtmService.mSupportsFreeformWindowManagement
&& (mService.mIsPc || forceDesktopMode)
? WindowConfiguration.WINDOWING_MODE_FREEFORM
: WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
diff --git a/services/core/java/com/android/server/wm/DockedStackDividerController.java b/services/core/java/com/android/server/wm/DockedStackDividerController.java
index b1bc2197..120ce3e 100644
--- a/services/core/java/com/android/server/wm/DockedStackDividerController.java
+++ b/services/core/java/com/android/server/wm/DockedStackDividerController.java
@@ -355,7 +355,9 @@
void getTouchRegion(Rect outRegion) {
outRegion.set(mTouchRegion);
- outRegion.offset(mWindow.getFrameLw().left, mWindow.getFrameLw().top);
+ if (mWindow != null) {
+ outRegion.offset(mWindow.getFrameLw().left, mWindow.getFrameLw().top);
+ }
}
private void resetDragResizingChangeReported() {
diff --git a/services/core/java/com/android/server/wm/RootActivityContainer.java b/services/core/java/com/android/server/wm/RootActivityContainer.java
index 66d42db..3401de6 100644
--- a/services/core/java/com/android/server/wm/RootActivityContainer.java
+++ b/services/core/java/com/android/server/wm/RootActivityContainer.java
@@ -227,15 +227,10 @@
mStackSupervisor.mRootActivityContainer = this;
}
- @VisibleForTesting
- void setWindowContainer(RootWindowContainer container) {
- mRootWindowContainer = container;
- mRootWindowContainer.setRootActivityContainer(this);
- }
-
void setWindowManager(WindowManagerService wm) {
mWindowManager = wm;
- setWindowContainer(mWindowManager.mRoot);
+ mRootWindowContainer = mWindowManager.mRoot;
+ mRootWindowContainer.setRootActivityContainer(this);
mDisplayManager = mService.mContext.getSystemService(DisplayManager.class);
mDisplayManager.registerDisplayListener(this, mService.mUiHandler);
mDisplayManagerInternal = LocalServices.getService(DisplayManagerInternal.class);
@@ -2266,7 +2261,7 @@
@WindowConfiguration.ActivityType int ignoreActivityType,
@WindowConfiguration.WindowingMode int ignoreWindowingMode, int callingUid,
boolean allowed) {
- mStackSupervisor.mRunningTasks.getTasks(maxNum, list, ignoreActivityType,
+ mStackSupervisor.getRunningTasks().getTasks(maxNum, list, ignoreActivityType,
ignoreWindowingMode, mActivityDisplays, callingUid, allowed);
}
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index fd86faa..3a2eb57 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -380,7 +380,7 @@
boolean isResizeable() {
return ActivityInfo.isResizeableMode(mResizeMode) || mSupportsPictureInPicture
- || mWmService.mForceResizableTasks;
+ || mWmService.mAtmService.mForceResizableActivities;
}
/**
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index 79367a0..cc2112e 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -1666,7 +1666,7 @@
* default bounds.
*/
Rect getPictureInPictureBounds(float aspectRatio, Rect stackBounds) {
- if (!mWmService.mSupportsPictureInPicture) {
+ if (!mWmService.mAtmService.mSupportsPictureInPicture) {
return null;
}
@@ -1762,7 +1762,7 @@
* Sets the current picture-in-picture aspect ratio.
*/
void setPictureInPictureAspectRatio(float aspectRatio) {
- if (!mWmService.mSupportsPictureInPicture) {
+ if (!mWmService.mAtmService.mSupportsPictureInPicture) {
return;
}
@@ -1792,7 +1792,7 @@
* Sets the current picture-in-picture actions.
*/
void setPictureInPictureActions(List<RemoteAction> actions) {
- if (!mWmService.mSupportsPictureInPicture) {
+ if (!mWmService.mAtmService.mSupportsPictureInPicture) {
return;
}
diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java
index bbef261..29d232f 100644
--- a/services/core/java/com/android/server/wm/WindowContainer.java
+++ b/services/core/java/com/android/server/wm/WindowContainer.java
@@ -767,11 +767,11 @@
*/
void setOrientation(int orientation, @Nullable IBinder freezeDisplayToken,
@Nullable ConfigurationContainer requestingContainer) {
- final boolean changed = mOrientation != orientation;
- mOrientation = orientation;
- if (!changed) {
+ if (mOrientation == orientation) {
return;
}
+
+ mOrientation = orientation;
final WindowContainer parent = getParent();
if (parent != null) {
onDescendantOrientationChanged(freezeDisplayToken, requestingContainer);
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 86faad0..db77a33 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -28,6 +28,7 @@
import static android.app.AppOpsManager.OP_SYSTEM_ALERT_WINDOW;
import static android.app.StatusBarManager.DISABLE_MASK;
import static android.app.admin.DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED;
+import static android.content.pm.PackageManager.FEATURE_PC;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static android.os.Process.SYSTEM_UID;
import static android.os.Process.myPid;
@@ -591,9 +592,6 @@
int mDockedStackCreateMode = SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT;
Rect mDockedStackCreateBounds;
- boolean mForceResizableTasks;
- boolean mSupportsPictureInPicture;
- boolean mSupportsFreeformWindowManagement;
boolean mIsPc;
/**
* Flag that indicates that desktop mode is forced for public secondary screens.
@@ -819,7 +817,7 @@
int mTransactionSequence;
final WindowAnimator mAnimator;
- final SurfaceAnimationRunner mSurfaceAnimationRunner;
+ SurfaceAnimationRunner mSurfaceAnimationRunner;
/**
* Keeps track of which animations got transferred to which animators. Entries will get cleaned
@@ -957,6 +955,9 @@
final ArrayList<AppFreezeListener> mAppFreezeListeners = new ArrayList<>();
+ @VisibleForTesting
+ final DeviceConfig.OnPropertiesChangedListener mPropertiesChangedListener;
+
interface AppFreezeListener {
void onAppFreezeTimeout();
}
@@ -1010,6 +1011,7 @@
mGlobalLock = atm.getGlobalLock();
mAtmService = atm;
mContext = context;
+ mIsPc = mContext.getPackageManager().hasSystemFeature(FEATURE_PC);
mAllowBootMessages = showBootMsgs;
mOnlyCore = onlyCore;
mLimitedAlphaCompositing = context.getResources().getBoolean(
@@ -1159,26 +1161,28 @@
mSystemGestureExcludedByPreQStickyImmersive =
DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_WINDOW_MANAGER,
KEY_SYSTEM_GESTURES_EXCLUDED_BY_PRE_Q_STICKY_IMMERSIVE, false);
- DeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_WINDOW_MANAGER,
- new HandlerExecutor(mH), properties -> {
- synchronized (mGlobalLock) {
- final int exclusionLimitDp = Math.max(MIN_GESTURE_EXCLUSION_LIMIT_DP,
- properties.getInt(KEY_SYSTEM_GESTURE_EXCLUSION_LIMIT_DP, 0));
- final boolean excludedByPreQSticky = DeviceConfig.getBoolean(
- DeviceConfig.NAMESPACE_WINDOW_MANAGER,
- KEY_SYSTEM_GESTURES_EXCLUDED_BY_PRE_Q_STICKY_IMMERSIVE, false);
- if (mSystemGestureExcludedByPreQStickyImmersive != excludedByPreQSticky
- || mSystemGestureExclusionLimitDp != exclusionLimitDp) {
- mSystemGestureExclusionLimitDp = exclusionLimitDp;
- mSystemGestureExcludedByPreQStickyImmersive = excludedByPreQSticky;
- mRoot.forAllDisplays(DisplayContent::updateSystemGestureExclusionLimit);
- }
- mSystemGestureExclusionLogDebounceTimeoutMillis =
- DeviceConfig.getInt(DeviceConfig.NAMESPACE_WINDOW_MANAGER,
- KEY_SYSTEM_GESTURE_EXCLUSION_LOG_DEBOUNCE_MILLIS, 0);
- }
- });
+ mPropertiesChangedListener = properties -> {
+ synchronized (mGlobalLock) {
+ final int exclusionLimitDp = Math.max(MIN_GESTURE_EXCLUSION_LIMIT_DP,
+ properties.getInt(KEY_SYSTEM_GESTURE_EXCLUSION_LIMIT_DP, 0));
+ final boolean excludedByPreQSticky = DeviceConfig.getBoolean(
+ DeviceConfig.NAMESPACE_WINDOW_MANAGER,
+ KEY_SYSTEM_GESTURES_EXCLUDED_BY_PRE_Q_STICKY_IMMERSIVE, false);
+ if (mSystemGestureExcludedByPreQStickyImmersive != excludedByPreQSticky
+ || mSystemGestureExclusionLimitDp != exclusionLimitDp) {
+ mSystemGestureExclusionLimitDp = exclusionLimitDp;
+ mSystemGestureExcludedByPreQStickyImmersive = excludedByPreQSticky;
+ mRoot.forAllDisplays(DisplayContent::updateSystemGestureExclusionLimit);
+ }
+
+ mSystemGestureExclusionLogDebounceTimeoutMillis =
+ DeviceConfig.getInt(DeviceConfig.NAMESPACE_WINDOW_MANAGER,
+ KEY_SYSTEM_GESTURE_EXCLUSION_LOG_DEBOUNCE_MILLIS, 0);
+ }
+ };
+ DeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_WINDOW_MANAGER,
+ new HandlerExecutor(mH), mPropertiesChangedListener);
LocalServices.addService(WindowManagerInternal.class, new LocalService());
}
@@ -4847,8 +4851,10 @@
case UPDATE_DOCKED_STACK_DIVIDER: {
synchronized (mGlobalLock) {
final DisplayContent displayContent = getDefaultDisplayContentLocked();
- displayContent.getDockedDividerController().reevaluateVisibility(false);
- displayContent.adjustForImeIfNeeded();
+ if (displayContent != null) {
+ displayContent.getDockedDividerController().reevaluateVisibility(false);
+ displayContent.adjustForImeIfNeeded();
+ }
}
break;
}
@@ -6495,31 +6501,14 @@
}
}
- public void setForceResizableTasks(boolean forceResizableTasks) {
- synchronized (mGlobalLock) {
- mForceResizableTasks = forceResizableTasks;
- }
- }
-
- public void setSupportsPictureInPicture(boolean supportsPictureInPicture) {
- synchronized (mGlobalLock) {
- mSupportsPictureInPicture = supportsPictureInPicture;
- }
- }
-
- public void setSupportsFreeformWindowManagement(boolean supportsFreeformWindowManagement) {
- synchronized (mGlobalLock) {
- mSupportsFreeformWindowManagement = supportsFreeformWindowManagement;
- }
- }
-
void setForceDesktopModeOnExternalDisplays(boolean forceDesktopModeOnExternalDisplays) {
synchronized (mGlobalLock) {
mForceDesktopModeOnExternalDisplays = forceDesktopModeOnExternalDisplays;
}
}
- public void setIsPc(boolean isPc) {
+ @VisibleForTesting
+ void setIsPc(boolean isPc) {
synchronized (mGlobalLock) {
mIsPc = isPc;
}
@@ -6546,7 +6535,7 @@
"registerPinnedStackListener()")) {
return;
}
- if (!mSupportsPictureInPicture) {
+ if (!mAtmService.mSupportsPictureInPicture) {
return;
}
synchronized (mGlobalLock) {
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityDisplayTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityDisplayTests.java
index 63b9198..6c78f6f 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityDisplayTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityDisplayTests.java
@@ -28,6 +28,7 @@
import static com.android.dx.mockito.inline.extended.ExtendedMockito.never;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.reset;
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.verify;
import static com.android.server.wm.ActivityStackSupervisor.ON_TOP;
@@ -140,7 +141,8 @@
public void testNotResumeHomeStackOnRemovingDisplay() {
// Create a display which supports system decoration and allows reparenting stacks to
// another display when the display is removed.
- final ActivityDisplay display = spy(createNewActivityDisplay());
+ final ActivityDisplay display = createNewActivityDisplay();
+ spyOn(display);
doReturn(false).when(display).shouldDestroyContentOnRemove();
doReturn(true).when(display).supportsSystemDecorations();
mRootActivityContainer.addChild(display, ActivityDisplay.POSITION_TOP);
@@ -304,14 +306,18 @@
ACTIVITY_TYPE_STANDARD, ON_TOP);
final ActivityStack stack4 = display.createStack(WINDOWING_MODE_FULLSCREEN,
ACTIVITY_TYPE_STANDARD, ON_TOP);
- final TaskRecord task1 = new TaskBuilder(mService.mStackSupervisor).setStack(
- stack1).setTaskId(1).build();
- final TaskRecord task2 = new TaskBuilder(mService.mStackSupervisor).setStack(
- stack2).setTaskId(2).build();
- final TaskRecord task3 = new TaskBuilder(mService.mStackSupervisor).setStack(
- stack3).setTaskId(3).build();
- final TaskRecord task4 = new TaskBuilder(mService.mStackSupervisor).setStack(
- stack4).setTaskId(4).build();
+ final TaskRecord task1 = new TaskBuilder(mService.mStackSupervisor)
+ .setStack(stack1)
+ .build();
+ final TaskRecord task2 = new TaskBuilder(mService.mStackSupervisor)
+ .setStack(stack2)
+ .build();
+ final TaskRecord task3 = new TaskBuilder(mService.mStackSupervisor)
+ .setStack(stack3)
+ .build();
+ final TaskRecord task4 = new TaskBuilder(mService.mStackSupervisor)
+ .setStack(stack4)
+ .build();
// Reordering stacks while removing stacks.
doAnswer(invocation -> {
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java
index 23bae88..977dd8e 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java
@@ -61,13 +61,13 @@
private ActivityMetricsLaunchObserver mLaunchObserver;
private ActivityMetricsLaunchObserverRegistry mLaunchObserverRegistry;
- private TestActivityStack mStack;
+ private ActivityStack mStack;
private TaskRecord mTask;
private ActivityRecord mActivityRecord;
private ActivityRecord mActivityRecordTrampoline;
@Before
- public void setUpAMLO() throws Exception {
+ public void setUpAMLO() {
mLaunchObserver = mock(ActivityMetricsLaunchObserver.class);
// ActivityStackSupervisor always creates its own instance of ActivityMetricsLogger.
@@ -78,15 +78,19 @@
// Sometimes we need an ActivityRecord for ActivityMetricsLogger to do anything useful.
// This seems to be the easiest way to create an ActivityRecord.
- mStack = mRootActivityContainer.getDefaultDisplay().createStack(
- WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
- mTask = new TaskBuilder(mSupervisor).setStack(mStack).build();
- mActivityRecord = new ActivityBuilder(mService).setTask(mTask).build();
+ mStack = new StackBuilder(mRootActivityContainer)
+ .setActivityType(ACTIVITY_TYPE_STANDARD)
+ .setWindowingMode(WINDOWING_MODE_FULLSCREEN)
+ .setOnTop(true)
+ .setCreateActivity(true)
+ .build();
+ mTask = mStack.topTask();
+ mActivityRecord = mTask.getTopActivity();
mActivityRecordTrampoline = new ActivityBuilder(mService).setTask(mTask).build();
}
@After
- public void tearDownAMLO() throws Exception {
+ public void tearDownAMLO() {
if (mLaunchObserverRegistry != null) { // Don't NPE if setUp failed.
mLaunchObserverRegistry.unregisterLaunchObserver(mLaunchObserver);
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
index 7b252cb..787ce28 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
@@ -16,6 +16,12 @@
package com.android.server.wm;
+import static android.content.pm.ActivityInfo.CONFIG_ORIENTATION;
+import static android.content.pm.ActivityInfo.CONFIG_SCREEN_LAYOUT;
+import static android.content.pm.ActivityInfo.RESIZE_MODE_UNRESIZEABLE;
+import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
+import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
+import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
import static android.os.Process.NOBODY_UID;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.Surface.ROTATION_0;
@@ -29,6 +35,7 @@
import static com.android.dx.mockito.inline.extended.ExtendedMockito.eq;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
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.dx.mockito.inline.extended.ExtendedMockito.when;
import static com.android.server.wm.ActivityRecord.FINISH_RESULT_CANCELLED;
@@ -71,6 +78,7 @@
import android.platform.test.annotations.Presubmit;
import android.util.MergedConfiguration;
import android.util.MutableBoolean;
+import android.view.DisplayInfo;
import android.view.IRemoteAnimationFinishedCallback;
import android.view.IRemoteAnimationRunner.Stub;
import android.view.RemoteAnimationAdapter;
@@ -79,7 +87,6 @@
import androidx.test.filters.MediumTest;
import com.android.internal.R;
-import com.android.server.wm.utils.WmDisplayCutout;
import org.junit.Before;
import org.junit.Test;
@@ -96,13 +103,13 @@
@MediumTest
@Presubmit
public class ActivityRecordTests extends ActivityTestsBase {
- private TestActivityStack mStack;
+ private ActivityStack mStack;
private TaskRecord mTask;
private ActivityRecord mActivity;
@Before
public void setUp() throws Exception {
- mStack = (TestActivityStack) new StackBuilder(mRootActivityContainer).build();
+ mStack = new StackBuilder(mRootActivityContainer).build();
mTask = mStack.getChildAt(0);
mActivity = mTask.getTopActivity();
@@ -113,13 +120,13 @@
@Test
public void testStackCleanupOnClearingTask() {
mActivity.setTask(null);
- assertEquals(mStack.onActivityRemovedFromStackInvocationCount(), 1);
+ verify(mStack, times(1)).onActivityRemovedFromStack(any());
}
@Test
public void testStackCleanupOnActivityRemoval() {
mTask.removeActivity(mActivity);
- assertEquals(mStack.onActivityRemovedFromStackInvocationCount(), 1);
+ verify(mStack, times(1)).onActivityRemovedFromStack(any());
}
@Test
@@ -134,7 +141,7 @@
final TaskRecord newTask = new TaskBuilder(mService.mStackSupervisor).setStack(mStack)
.build();
mActivity.reparent(newTask, 0, null /*reason*/);
- assertEquals(mStack.onActivityRemovedFromStackInvocationCount(), 0);
+ verify(mStack, times(0)).onActivityRemovedFromStack(any());
}
@Test
@@ -261,8 +268,8 @@
public void testNewParentConfigurationIncrementsSeq() {
final Configuration newConfig = new Configuration(
mTask.getRequestedOverrideConfiguration());
- newConfig.orientation = newConfig.orientation == Configuration.ORIENTATION_PORTRAIT
- ? Configuration.ORIENTATION_LANDSCAPE : Configuration.ORIENTATION_PORTRAIT;
+ newConfig.orientation = newConfig.orientation == ORIENTATION_PORTRAIT
+ ? ORIENTATION_LANDSCAPE : ORIENTATION_PORTRAIT;
final int prevSeq = mActivity.getMergedOverrideConfiguration().seq;
mTask.onRequestedOverrideConfigurationChanged(newConfig);
@@ -277,7 +284,7 @@
.getRequestedOverrideConfiguration();
final Configuration newConfig = new Configuration();
- newConfig.orientation = Configuration.ORIENTATION_PORTRAIT;
+ newConfig.orientation = ORIENTATION_PORTRAIT;
final int prevSeq = mActivity.getMergedOverrideConfiguration().seq;
mActivity.onRequestedOverrideConfigurationChanged(newConfig);
@@ -293,10 +300,11 @@
mActivity.setLastReportedConfiguration(new MergedConfiguration(new Configuration(),
mActivity.getConfiguration()));
- mActivity.info.configChanges &= ~ActivityInfo.CONFIG_ORIENTATION;
+ mActivity.info.configChanges &= ~CONFIG_ORIENTATION;
final Configuration newConfig = new Configuration(mTask.getConfiguration());
- newConfig.orientation = newConfig.orientation == Configuration.ORIENTATION_PORTRAIT
- ? Configuration.ORIENTATION_LANDSCAPE : Configuration.ORIENTATION_PORTRAIT;
+ newConfig.orientation = newConfig.orientation == ORIENTATION_PORTRAIT
+ ? ORIENTATION_LANDSCAPE
+ : ORIENTATION_PORTRAIT;
mTask.onRequestedOverrideConfigurationChanged(newConfig);
mActivity.mRelaunchReason = ActivityTaskManagerService.RELAUNCH_REASON_NONE;
@@ -315,13 +323,14 @@
mActivity.setLastReportedConfiguration(new MergedConfiguration(new Configuration(),
mActivity.getConfiguration()));
- mActivity.info.configChanges &= ~ActivityInfo.CONFIG_ORIENTATION;
+ mActivity.info.configChanges &= ~CONFIG_ORIENTATION;
final Configuration newConfig = new Configuration(mTask.getConfiguration());
- newConfig.orientation = newConfig.orientation == Configuration.ORIENTATION_PORTRAIT
- ? Configuration.ORIENTATION_LANDSCAPE : Configuration.ORIENTATION_PORTRAIT;
+ newConfig.orientation = newConfig.orientation == ORIENTATION_PORTRAIT
+ ? ORIENTATION_LANDSCAPE
+ : ORIENTATION_PORTRAIT;
mTask.onRequestedOverrideConfigurationChanged(newConfig);
- doReturn(true).when(mTask.getTask()).isDragResizing();
+ doReturn(true).when(mTask.mTask).isDragResizing();
mActivity.mRelaunchReason = ActivityTaskManagerService.RELAUNCH_REASON_NONE;
@@ -355,30 +364,39 @@
@Test
public void testSetRequestedOrientationUpdatesConfiguration() throws Exception {
+ mActivity = new ActivityBuilder(mService)
+ .setTask(mTask)
+ .setConfigChanges(CONFIG_ORIENTATION | CONFIG_SCREEN_LAYOUT)
+ .build();
mActivity.setState(ActivityStack.ActivityState.RESUMED, "Testing");
- mTask.onRequestedOverrideConfigurationChanged(mTask.getConfiguration());
mActivity.setLastReportedConfiguration(new MergedConfiguration(new Configuration(),
mActivity.getConfiguration()));
- mActivity.info.configChanges |= ActivityInfo.CONFIG_ORIENTATION;
final Configuration newConfig = new Configuration(mActivity.getConfiguration());
- newConfig.orientation = newConfig.orientation == Configuration.ORIENTATION_PORTRAIT
- ? Configuration.ORIENTATION_LANDSCAPE
- : Configuration.ORIENTATION_PORTRAIT;
+ final int shortSide = Math.min(newConfig.screenWidthDp, newConfig.screenHeightDp);
+ final int longSide = Math.max(newConfig.screenWidthDp, newConfig.screenHeightDp);
+ if (newConfig.orientation == ORIENTATION_PORTRAIT) {
+ newConfig.orientation = ORIENTATION_LANDSCAPE;
+ newConfig.screenWidthDp = longSide;
+ newConfig.screenHeightDp = shortSide;
+ } else {
+ newConfig.orientation = ORIENTATION_PORTRAIT;
+ newConfig.screenWidthDp = shortSide;
+ newConfig.screenHeightDp = longSide;
+ }
// Mimic the behavior that display doesn't handle app's requested orientation.
- doAnswer(invocation -> {
- mTask.onConfigurationChanged(newConfig);
- return null;
- }).when(mActivity.mAppWindowToken).setOrientation(anyInt(), any(), any());
+ final DisplayContent dc = mTask.mTask.getDisplayContent();
+ doReturn(false).when(dc).onDescendantOrientationChanged(any(), any());
+ doReturn(false).when(dc).handlesOrientationChangeFromDescendant();
final int requestedOrientation;
switch (newConfig.orientation) {
- case Configuration.ORIENTATION_LANDSCAPE:
- requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
+ case ORIENTATION_LANDSCAPE:
+ requestedOrientation = SCREEN_ORIENTATION_LANDSCAPE;
break;
- case Configuration.ORIENTATION_PORTRAIT:
+ case ORIENTATION_PORTRAIT:
requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
break;
default:
@@ -421,24 +439,33 @@
@Test
public void testPushConfigurationWhenLaunchTaskBehind() throws Exception {
+ mActivity = new ActivityBuilder(mService)
+ .setTask(mTask)
+ .setLaunchTaskBehind(true)
+ .setConfigChanges(CONFIG_ORIENTATION)
+ .build();
mActivity.setState(ActivityStack.ActivityState.STOPPED, "Testing");
- final TestActivityStack stack = (TestActivityStack) new StackBuilder(mRootActivityContainer)
- .build();
+ final ActivityStack stack = new StackBuilder(mRootActivityContainer).build();
try {
- stack.setIsTranslucent(false);
+ doReturn(false).when(stack).isStackTranslucent(any());
assertFalse(mStack.shouldBeVisible(null /* starting */));
- mTask.onRequestedOverrideConfigurationChanged(mTask.getConfiguration());
mActivity.setLastReportedConfiguration(new MergedConfiguration(new Configuration(),
mActivity.getConfiguration()));
- mActivity.mLaunchTaskBehind = true;
- mActivity.info.configChanges |= ActivityInfo.CONFIG_ORIENTATION;
final Configuration newConfig = new Configuration(mActivity.getConfiguration());
- newConfig.orientation = newConfig.orientation == Configuration.ORIENTATION_PORTRAIT
- ? Configuration.ORIENTATION_LANDSCAPE
- : Configuration.ORIENTATION_PORTRAIT;
+ final int shortSide = Math.min(newConfig.screenWidthDp, newConfig.screenHeightDp);
+ final int longSide = Math.max(newConfig.screenWidthDp, newConfig.screenHeightDp);
+ if (newConfig.orientation == ORIENTATION_PORTRAIT) {
+ newConfig.orientation = ORIENTATION_LANDSCAPE;
+ newConfig.screenWidthDp = longSide;
+ newConfig.screenHeightDp = shortSide;
+ } else {
+ newConfig.orientation = ORIENTATION_PORTRAIT;
+ newConfig.screenWidthDp = shortSide;
+ newConfig.screenHeightDp = longSide;
+ }
mTask.onConfigurationChanged(newConfig);
@@ -468,6 +495,7 @@
setupDisplayContentForCompatDisplayInsets();
final int decorHeight = 200; // e.g. The device has cutout.
final DisplayPolicy policy = setupDisplayAndParentSize(600, 800).getDisplayPolicy();
+ spyOn(policy);
doAnswer(invocationOnMock -> {
final int rotation = invocationOnMock.<Integer>getArgument(0);
final Rect insets = invocationOnMock.<Rect>getArgument(4);
@@ -482,7 +510,7 @@
doReturn(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED)
.when(mActivity.mAppWindowToken).getOrientationIgnoreVisibility();
- mActivity.info.resizeMode = ActivityInfo.RESIZE_MODE_UNRESIZEABLE;
+ mActivity.info.resizeMode = RESIZE_MODE_UNRESIZEABLE;
mActivity.info.minAspectRatio = mActivity.info.maxAspectRatio = 1;
ensureActivityConfiguration();
// The parent configuration doesn't change since the first resolved configuration, so the
@@ -506,19 +534,28 @@
@Test
public void testSizeCompatMode_FixedScreenConfigurationWhenMovingToDisplay() {
// Initialize different bounds on a new display.
- final ActivityDisplay newDisplay = addNewActivityDisplayAt(ActivityDisplay.POSITION_TOP);
- newDisplay.getWindowConfiguration().setAppBounds(new Rect(0, 0, 1000, 2000));
- newDisplay.getConfiguration().densityDpi = 300;
+ final Rect newDisplayBounds = new Rect(0, 0, 1000, 2000);
+ DisplayInfo info = new DisplayInfo();
+ mService.mContext.getDisplay().getDisplayInfo(info);
+ info.logicalWidth = newDisplayBounds.width();
+ info.logicalHeight = newDisplayBounds.height();
+ info.logicalDensityDpi = 300;
+
+ final ActivityDisplay newDisplay =
+ addNewActivityDisplayAt(info, ActivityDisplay.POSITION_TOP);
mTask.getConfiguration().densityDpi = 200;
- prepareFixedAspectRatioUnresizableActivity();
+ mActivity = new ActivityBuilder(mService)
+ .setTask(mTask)
+ .setResizeMode(RESIZE_MODE_UNRESIZEABLE)
+ .setMaxAspectRatio(1.5f)
+ .build();
final Rect originalBounds = new Rect(mActivity.getBounds());
final int originalDpi = mActivity.getConfiguration().densityDpi;
// Move the non-resizable activity to the new display.
mStack.reparent(newDisplay, true /* onTop */, false /* displayRemoved */);
- ensureActivityConfiguration();
assertEquals(originalBounds, mActivity.getBounds());
assertEquals(originalDpi, mActivity.getConfiguration().densityDpi);
@@ -531,9 +568,9 @@
when(mActivity.mAppWindowToken.getOrientationIgnoreVisibility()).thenReturn(
ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
mTask.getWindowConfiguration().setAppBounds(mStack.getDisplay().getBounds());
- mTask.getConfiguration().orientation = Configuration.ORIENTATION_PORTRAIT;
+ mTask.getConfiguration().orientation = ORIENTATION_PORTRAIT;
mActivity.info.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
- mActivity.info.resizeMode = ActivityInfo.RESIZE_MODE_UNRESIZEABLE;
+ mActivity.info.resizeMode = RESIZE_MODE_UNRESIZEABLE;
ensureActivityConfiguration();
final Rect originalBounds = new Rect(mActivity.getBounds());
@@ -579,7 +616,7 @@
mTask.getWindowConfiguration().setAppBounds(new Rect(0, 0, 600, 1200));
// Simulate the display changes orientation.
- doReturn(ActivityInfo.CONFIG_SCREEN_SIZE | ActivityInfo.CONFIG_ORIENTATION
+ doReturn(ActivityInfo.CONFIG_SCREEN_SIZE | CONFIG_ORIENTATION
| ActivityInfo.CONFIG_WINDOW_CONFIGURATION)
.when(display).getLastOverrideConfigurationChanges();
mActivity.onConfigurationChanged(mTask.getConfiguration());
@@ -754,24 +791,17 @@
/** Setup {@link #mActivity} as a size-compat-mode-able activity without fixed orientation. */
private void prepareFixedAspectRatioUnresizableActivity() {
setupDisplayContentForCompatDisplayInsets();
- when(mActivity.mAppWindowToken.getOrientationIgnoreVisibility()).thenReturn(
- ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
- mActivity.info.resizeMode = ActivityInfo.RESIZE_MODE_UNRESIZEABLE;
+ mActivity.info.resizeMode = RESIZE_MODE_UNRESIZEABLE;
mActivity.info.maxAspectRatio = 1.5f;
ensureActivityConfiguration();
}
private void setupDisplayContentForCompatDisplayInsets() {
final Rect displayBounds = mStack.getDisplay().getBounds();
- final DisplayContent displayContent = setupDisplayAndParentSize(
- displayBounds.width(), displayBounds.height());
- doReturn(mock(DisplayPolicy.class)).when(displayContent).getDisplayPolicy();
- doReturn(mock(WmDisplayCutout.class)).when(displayContent)
- .calculateDisplayCutoutForRotation(anyInt());
+ setupDisplayAndParentSize(displayBounds.width(), displayBounds.height());
}
private DisplayContent setupDisplayAndParentSize(int width, int height) {
- // The DisplayContent is already a mocked object.
final DisplayContent displayContent = mStack.getDisplay().mDisplayContent;
displayContent.mBaseDisplayWidth = width;
displayContent.mBaseDisplayHeight = height;
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java
index e5278d8..ff7b1fa 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java
@@ -29,7 +29,7 @@
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.spy;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
import static com.android.server.wm.ActivityStack.ActivityState.DESTROYING;
import static com.android.server.wm.ActivityStack.ActivityState.FINISHING;
@@ -44,6 +44,7 @@
import static com.android.server.wm.ActivityStack.STACK_VISIBILITY_VISIBLE_BEHIND_TRANSLUCENT;
import static com.android.server.wm.ActivityTaskManagerService.RELAUNCH_REASON_FREE_RESIZE;
import static com.android.server.wm.ActivityTaskManagerService.RELAUNCH_REASON_WINDOWING_MODE_RESIZE;
+import static com.android.server.wm.TaskRecord.REPARENT_MOVE_STACK_TO_FRONT;
import static com.google.common.truth.Truth.assertThat;
@@ -83,8 +84,9 @@
@Before
public void setUp() throws Exception {
mDefaultDisplay = mRootActivityContainer.getDefaultDisplay();
- mStack = spy(mDefaultDisplay.createStack(WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_STANDARD,
- true /* onTop */));
+ mStack = mDefaultDisplay.createStack(WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_STANDARD,
+ true /* onTop */);
+ spyOn(mStack);
mTask = new TaskBuilder(mSupervisor).setStack(mStack).build();
}
@@ -140,10 +142,8 @@
final ActivityStack destStack = mRootActivityContainer.getDefaultDisplay().createStack(
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
- final TaskRecord destTask = new TaskBuilder(mSupervisor).setStack(destStack).build();
-
- mTask.removeActivity(r);
- destTask.addActivityToTop(r);
+ mTask.reparent(destStack, true /*toTop*/, REPARENT_MOVE_STACK_TO_FRONT, false, false,
+ "testResumedActivityFromActivityReparenting");
assertNull(mStack.getResumedActivity());
assertEquals(r, destStack.getResumedActivity());
@@ -313,45 +313,50 @@
@Test
public void testShouldBeVisible_Fullscreen() {
- final TestActivityStack homeStack = createStackForShouldBeVisibleTest(mDefaultDisplay,
+ final ActivityStack homeStack = createStackForShouldBeVisibleTest(mDefaultDisplay,
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, true /* onTop */);
final ActivityStack pinnedStack = createStackForShouldBeVisibleTest(mDefaultDisplay,
WINDOWING_MODE_PINNED, ACTIVITY_TYPE_STANDARD, true /* onTop */);
+ // Add an activity to the pinned stack so it isn't considered empty for visibility check.
+ final ActivityRecord pinnedActivity = new ActivityBuilder(mService)
+ .setCreateTask(true)
+ .setStack(pinnedStack)
+ .build();
assertTrue(homeStack.shouldBeVisible(null /* starting */));
assertTrue(pinnedStack.shouldBeVisible(null /* starting */));
- final TestActivityStack fullscreenStack = createStackForShouldBeVisibleTest(mDefaultDisplay,
+ final ActivityStack fullscreenStack = createStackForShouldBeVisibleTest(mDefaultDisplay,
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
// Home stack shouldn't be visible behind an opaque fullscreen stack, but pinned stack
// should be visible since it is always on-top.
- fullscreenStack.setIsTranslucent(false);
+ doReturn(false).when(fullscreenStack).isStackTranslucent(any());
assertFalse(homeStack.shouldBeVisible(null /* starting */));
assertTrue(pinnedStack.shouldBeVisible(null /* starting */));
assertTrue(fullscreenStack.shouldBeVisible(null /* starting */));
// Home stack should be visible behind a translucent fullscreen stack.
- fullscreenStack.setIsTranslucent(true);
+ doReturn(true).when(fullscreenStack).isStackTranslucent(any());
assertTrue(homeStack.shouldBeVisible(null /* starting */));
assertTrue(pinnedStack.shouldBeVisible(null /* starting */));
}
@Test
public void testShouldBeVisible_SplitScreen() {
- final TestActivityStack homeStack = createStackForShouldBeVisibleTest(mDefaultDisplay,
+ final ActivityStack homeStack = createStackForShouldBeVisibleTest(mDefaultDisplay,
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, true /* onTop */);
// Home stack should always be fullscreen for this test.
- homeStack.setSupportsSplitScreen(false);
- final TestActivityStack splitScreenPrimary =
+ doReturn(false).when(homeStack).supportsSplitScreenWindowingMode();
+ final ActivityStack splitScreenPrimary =
createStackForShouldBeVisibleTest(mDefaultDisplay,
WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, ACTIVITY_TYPE_STANDARD, true /* onTop */);
- final TestActivityStack splitScreenSecondary =
+ final ActivityStack splitScreenSecondary =
createStackForShouldBeVisibleTest(mDefaultDisplay,
WINDOWING_MODE_SPLIT_SCREEN_SECONDARY, ACTIVITY_TYPE_STANDARD, true /* onTop */);
// Home stack shouldn't be visible if both halves of split-screen are opaque.
- splitScreenPrimary.setIsTranslucent(false);
- splitScreenSecondary.setIsTranslucent(false);
+ doReturn(false).when(splitScreenPrimary).isStackTranslucent(any());
+ doReturn(false).when(splitScreenSecondary).isStackTranslucent(any());
assertFalse(homeStack.shouldBeVisible(null /* starting */));
assertTrue(splitScreenPrimary.shouldBeVisible(null /* starting */));
assertTrue(splitScreenSecondary.shouldBeVisible(null /* starting */));
@@ -362,7 +367,7 @@
splitScreenSecondary.getVisibility(null /* starting */));
// Home stack should be visible if one of the halves of split-screen is translucent.
- splitScreenPrimary.setIsTranslucent(true);
+ doReturn(true).when(splitScreenPrimary).isStackTranslucent(any());
assertTrue(homeStack.shouldBeVisible(null /* starting */));
assertTrue(splitScreenPrimary.shouldBeVisible(null /* starting */));
assertTrue(splitScreenSecondary.shouldBeVisible(null /* starting */));
@@ -373,12 +378,12 @@
assertEquals(STACK_VISIBILITY_VISIBLE,
splitScreenSecondary.getVisibility(null /* starting */));
- final TestActivityStack splitScreenSecondary2 =
+ final ActivityStack splitScreenSecondary2 =
createStackForShouldBeVisibleTest(mDefaultDisplay,
WINDOWING_MODE_SPLIT_SCREEN_SECONDARY, ACTIVITY_TYPE_STANDARD, true /* onTop */);
// First split-screen secondary shouldn't be visible behind another opaque split-split
// secondary.
- splitScreenSecondary2.setIsTranslucent(false);
+ doReturn(false).when(splitScreenSecondary2).isStackTranslucent(any());
assertFalse(splitScreenSecondary.shouldBeVisible(null /* starting */));
assertTrue(splitScreenSecondary2.shouldBeVisible(null /* starting */));
assertEquals(STACK_VISIBILITY_INVISIBLE,
@@ -388,7 +393,7 @@
// First split-screen secondary should be visible behind another translucent split-screen
// secondary.
- splitScreenSecondary2.setIsTranslucent(true);
+ doReturn(true).when(splitScreenSecondary2).isStackTranslucent(any());
assertTrue(splitScreenSecondary.shouldBeVisible(null /* starting */));
assertTrue(splitScreenSecondary2.shouldBeVisible(null /* starting */));
assertEquals(STACK_VISIBILITY_VISIBLE_BEHIND_TRANSLUCENT,
@@ -396,11 +401,11 @@
assertEquals(STACK_VISIBILITY_VISIBLE,
splitScreenSecondary2.getVisibility(null /* starting */));
- final TestActivityStack assistantStack = createStackForShouldBeVisibleTest(mDefaultDisplay,
+ final ActivityStack assistantStack = createStackForShouldBeVisibleTest(mDefaultDisplay,
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_ASSISTANT, true /* onTop */);
// Split-screen stacks shouldn't be visible behind an opaque fullscreen stack.
- assistantStack.setIsTranslucent(false);
+ doReturn(false).when(assistantStack).isStackTranslucent(any());
assertTrue(assistantStack.shouldBeVisible(null /* starting */));
assertFalse(splitScreenPrimary.shouldBeVisible(null /* starting */));
assertFalse(splitScreenSecondary.shouldBeVisible(null /* starting */));
@@ -415,7 +420,7 @@
splitScreenSecondary2.getVisibility(null /* starting */));
// Split-screen stacks should be visible behind a translucent fullscreen stack.
- assistantStack.setIsTranslucent(true);
+ doReturn(true).when(assistantStack).isStackTranslucent(any());
assertTrue(assistantStack.shouldBeVisible(null /* starting */));
assertTrue(splitScreenPrimary.shouldBeVisible(null /* starting */));
assertTrue(splitScreenSecondary.shouldBeVisible(null /* starting */));
@@ -430,9 +435,9 @@
splitScreenSecondary2.getVisibility(null /* starting */));
// Assistant stack shouldn't be visible behind translucent split-screen stack
- assistantStack.setIsTranslucent(false);
- splitScreenPrimary.setIsTranslucent(true);
- splitScreenSecondary2.setIsTranslucent(true);
+ doReturn(false).when(assistantStack).isStackTranslucent(any());
+ doReturn(true).when(splitScreenPrimary).isStackTranslucent(any());
+ doReturn(true).when(splitScreenSecondary2).isStackTranslucent(any());
splitScreenSecondary2.moveToFront("testShouldBeVisible_SplitScreen");
splitScreenPrimary.moveToFront("testShouldBeVisible_SplitScreen");
assertFalse(assistantStack.shouldBeVisible(null /* starting */));
@@ -450,10 +455,10 @@
@Test
public void testGetVisibility_FullscreenBehindTranslucent() {
- final TestActivityStack bottomStack =
+ final ActivityStack bottomStack =
createStandardStackForVisibilityTest(WINDOWING_MODE_FULLSCREEN,
false /* translucent */);
- final TestActivityStack translucentStack =
+ final ActivityStack translucentStack =
createStandardStackForVisibilityTest(WINDOWING_MODE_FULLSCREEN,
true /* translucent */);
@@ -465,13 +470,13 @@
@Test
public void testGetVisibility_FullscreenBehindTranslucentAndOpaque() {
- final TestActivityStack bottomStack =
+ final ActivityStack bottomStack =
createStandardStackForVisibilityTest(WINDOWING_MODE_FULLSCREEN,
false /* translucent */);
- final TestActivityStack translucentStack =
+ final ActivityStack translucentStack =
createStandardStackForVisibilityTest(WINDOWING_MODE_FULLSCREEN,
true /* translucent */);
- final TestActivityStack opaqueStack =
+ final ActivityStack opaqueStack =
createStandardStackForVisibilityTest(WINDOWING_MODE_FULLSCREEN,
false /* translucent */);
@@ -483,13 +488,13 @@
@Test
public void testGetVisibility_FullscreenBehindOpaqueAndTranslucent() {
- final TestActivityStack bottomStack =
+ final ActivityStack bottomStack =
createStandardStackForVisibilityTest(WINDOWING_MODE_FULLSCREEN,
false /* translucent */);
- final TestActivityStack opaqueStack =
+ final ActivityStack opaqueStack =
createStandardStackForVisibilityTest(WINDOWING_MODE_FULLSCREEN,
false /* translucent */);
- final TestActivityStack translucentStack =
+ final ActivityStack translucentStack =
createStandardStackForVisibilityTest(WINDOWING_MODE_FULLSCREEN,
true /* translucent */);
@@ -502,10 +507,10 @@
@Test
public void testGetVisibility_FullscreenTranslucentBehindTranslucent() {
- final TestActivityStack bottomTranslucentStack =
+ final ActivityStack bottomTranslucentStack =
createStandardStackForVisibilityTest(WINDOWING_MODE_FULLSCREEN,
true /* translucent */);
- final TestActivityStack translucentStack =
+ final ActivityStack translucentStack =
createStandardStackForVisibilityTest(WINDOWING_MODE_FULLSCREEN,
true /* translucent */);
@@ -517,10 +522,10 @@
@Test
public void testGetVisibility_FullscreenTranslucentBehindOpaque() {
- final TestActivityStack bottomTranslucentStack =
+ final ActivityStack bottomTranslucentStack =
createStandardStackForVisibilityTest(WINDOWING_MODE_FULLSCREEN,
true /* translucent */);
- final TestActivityStack opaqueStack =
+ final ActivityStack opaqueStack =
createStandardStackForVisibilityTest(WINDOWING_MODE_FULLSCREEN,
false /* translucent */);
@@ -531,10 +536,10 @@
@Test
public void testGetVisibility_FullscreenBehindTranslucentAndPip() {
- final TestActivityStack bottomStack =
+ final ActivityStack bottomStack =
createStandardStackForVisibilityTest(WINDOWING_MODE_FULLSCREEN,
false /* translucent */);
- final TestActivityStack translucentStack =
+ final ActivityStack translucentStack =
createStandardStackForVisibilityTest(WINDOWING_MODE_FULLSCREEN,
true /* translucent */);
final ActivityStack pinnedStack = createStackForShouldBeVisibleTest(mDefaultDisplay,
@@ -544,22 +549,34 @@
bottomStack.getVisibility(null /* starting */));
assertEquals(STACK_VISIBILITY_VISIBLE,
translucentStack.getVisibility(null /* starting */));
+ // Add an activity to the pinned stack so it isn't considered empty for visibility check.
+ final ActivityRecord pinnedActivity = new ActivityBuilder(mService)
+ .setCreateTask(true)
+ .setStack(pinnedStack)
+ .build();
assertEquals(STACK_VISIBILITY_VISIBLE, pinnedStack.getVisibility(null /* starting */));
}
@Test
public void testShouldBeVisible_Finishing() {
- final TestActivityStack homeStack = createStackForShouldBeVisibleTest(mDefaultDisplay,
+ final ActivityStack homeStack = createStackForShouldBeVisibleTest(mDefaultDisplay,
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, true /* onTop */);
- final TestActivityStack translucentStack = createStackForShouldBeVisibleTest(
+ ActivityRecord topRunningHomeActivity = homeStack.topRunningActivityLocked();
+ if (topRunningHomeActivity == null) {
+ topRunningHomeActivity = new ActivityBuilder(mService)
+ .setStack(homeStack)
+ .setCreateTask(true)
+ .build();
+ }
+
+ final ActivityStack translucentStack = createStackForShouldBeVisibleTest(
mDefaultDisplay, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD,
true /* onTop */);
- translucentStack.setIsTranslucent(true);
+ doReturn(true).when(translucentStack).isStackTranslucent(any());
assertTrue(homeStack.shouldBeVisible(null /* starting */));
assertTrue(translucentStack.shouldBeVisible(null /* starting */));
- final ActivityRecord topRunningHomeActivity = homeStack.topRunningActivityLocked();
topRunningHomeActivity.finishing = true;
final ActivityRecord topRunningTranslucentActivity =
translucentStack.topRunningActivityLocked();
@@ -577,13 +594,13 @@
public void testMoveHomeStackBehindBottomMostVisibleStack_NoMoveHomeBehindFullscreen() {
mDefaultDisplay.removeChild(mStack);
- final TestActivityStack homeStack = createStackForShouldBeVisibleTest(mDefaultDisplay,
+ final ActivityStack homeStack = createStackForShouldBeVisibleTest(mDefaultDisplay,
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, true /* onTop */);
- final TestActivityStack fullscreenStack = createStackForShouldBeVisibleTest(mDefaultDisplay,
+ final ActivityStack fullscreenStack = createStackForShouldBeVisibleTest(mDefaultDisplay,
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
- homeStack.setIsTranslucent(false);
- fullscreenStack.setIsTranslucent(false);
+ doReturn(false).when(homeStack).isStackTranslucent(any());
+ doReturn(false).when(fullscreenStack).isStackTranslucent(any());
// Ensure that we don't move the home stack if it is already behind the top fullscreen stack
int homeStackIndex = mDefaultDisplay.getIndexOf(homeStack);
@@ -596,13 +613,13 @@
public void testMoveHomeStackBehindBottomMostVisibleStack_NoMoveHomeBehindTranslucent() {
mDefaultDisplay.removeChild(mStack);
- final TestActivityStack homeStack = createStackForShouldBeVisibleTest(mDefaultDisplay,
+ final ActivityStack homeStack = createStackForShouldBeVisibleTest(mDefaultDisplay,
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, true /* onTop */);
- final TestActivityStack fullscreenStack = createStackForShouldBeVisibleTest(mDefaultDisplay,
+ final ActivityStack fullscreenStack = createStackForShouldBeVisibleTest(mDefaultDisplay,
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
- homeStack.setIsTranslucent(false);
- fullscreenStack.setIsTranslucent(true);
+ doReturn(false).when(homeStack).isStackTranslucent(any());
+ doReturn(true).when(fullscreenStack).isStackTranslucent(any());
// Ensure that we don't move the home stack if it is already behind the top fullscreen stack
int homeStackIndex = mDefaultDisplay.getIndexOf(homeStack);
@@ -615,13 +632,13 @@
public void testMoveHomeStackBehindBottomMostVisibleStack_NoMoveHomeOnTop() {
mDefaultDisplay.removeChild(mStack);
- final TestActivityStack fullscreenStack = createStackForShouldBeVisibleTest(mDefaultDisplay,
+ final ActivityStack fullscreenStack = createStackForShouldBeVisibleTest(mDefaultDisplay,
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
- final TestActivityStack homeStack = createStackForShouldBeVisibleTest(mDefaultDisplay,
+ final ActivityStack homeStack = createStackForShouldBeVisibleTest(mDefaultDisplay,
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, true /* onTop */);
- homeStack.setIsTranslucent(false);
- fullscreenStack.setIsTranslucent(false);
+ doReturn(false).when(homeStack).isStackTranslucent(any());
+ doReturn(false).when(fullscreenStack).isStackTranslucent(any());
// Ensure we don't move the home stack if it is already on top
int homeStackIndex = mDefaultDisplay.getIndexOf(homeStack);
@@ -634,20 +651,20 @@
public void testMoveHomeStackBehindBottomMostVisibleStack_MoveHomeBehindFullscreen() {
mDefaultDisplay.removeChild(mStack);
- final TestActivityStack homeStack = createStackForShouldBeVisibleTest(mDefaultDisplay,
+ final ActivityStack homeStack = createStackForShouldBeVisibleTest(mDefaultDisplay,
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, true /* onTop */);
- final TestActivityStack fullscreenStack1 = createStackForShouldBeVisibleTest(
+ final ActivityStack fullscreenStack1 = createStackForShouldBeVisibleTest(
mDefaultDisplay, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD,
true /* onTop */);
- final TestActivityStack fullscreenStack2 = createStackForShouldBeVisibleTest(
+ final ActivityStack fullscreenStack2 = createStackForShouldBeVisibleTest(
mDefaultDisplay, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD,
true /* onTop */);
final ActivityStack pinnedStack = createStackForShouldBeVisibleTest(mDefaultDisplay,
WINDOWING_MODE_PINNED, ACTIVITY_TYPE_STANDARD, true /* onTop */);
- homeStack.setIsTranslucent(false);
- fullscreenStack1.setIsTranslucent(false);
- fullscreenStack2.setIsTranslucent(false);
+ doReturn(false).when(homeStack).isStackTranslucent(any());
+ doReturn(false).when(fullscreenStack1).isStackTranslucent(any());
+ doReturn(false).when(fullscreenStack2).isStackTranslucent(any());
// Ensure that we move the home stack behind the bottom most fullscreen stack, ignoring the
// pinned stack
@@ -661,18 +678,18 @@
testMoveHomeStackBehindBottomMostVisibleStack_MoveHomeBehindFullscreenAndTranslucent() {
mDefaultDisplay.removeChild(mStack);
- final TestActivityStack homeStack = createStackForShouldBeVisibleTest(mDefaultDisplay,
+ final ActivityStack homeStack = createStackForShouldBeVisibleTest(mDefaultDisplay,
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, true /* onTop */);
- final TestActivityStack fullscreenStack1 = createStackForShouldBeVisibleTest(
+ final ActivityStack fullscreenStack1 = createStackForShouldBeVisibleTest(
mDefaultDisplay, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD,
true /* onTop */);
- final TestActivityStack fullscreenStack2 = createStackForShouldBeVisibleTest(
+ final ActivityStack fullscreenStack2 = createStackForShouldBeVisibleTest(
mDefaultDisplay, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD,
true /* onTop */);
- homeStack.setIsTranslucent(false);
- fullscreenStack1.setIsTranslucent(false);
- fullscreenStack2.setIsTranslucent(true);
+ doReturn(false).when(homeStack).isStackTranslucent(any());
+ doReturn(false).when(fullscreenStack1).isStackTranslucent(any());
+ doReturn(true).when(fullscreenStack2).isStackTranslucent(any());
// Ensure that we move the home stack behind the bottom most non-translucent fullscreen
// stack
@@ -685,18 +702,18 @@
public void testMoveHomeStackBehindStack_BehindHomeStack() {
mDefaultDisplay.removeChild(mStack);
- final TestActivityStack fullscreenStack1 = createStackForShouldBeVisibleTest(
+ final ActivityStack fullscreenStack1 = createStackForShouldBeVisibleTest(
mDefaultDisplay, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD,
true /* onTop */);
- final TestActivityStack fullscreenStack2 = createStackForShouldBeVisibleTest(
+ final ActivityStack fullscreenStack2 = createStackForShouldBeVisibleTest(
mDefaultDisplay, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD,
true /* onTop */);
- final TestActivityStack homeStack = createStackForShouldBeVisibleTest(mDefaultDisplay,
+ final ActivityStack homeStack = createStackForShouldBeVisibleTest(mDefaultDisplay,
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, true /* onTop */);
- homeStack.setIsTranslucent(false);
- fullscreenStack1.setIsTranslucent(false);
- fullscreenStack2.setIsTranslucent(false);
+ doReturn(false).when(homeStack).isStackTranslucent(any());
+ doReturn(false).when(fullscreenStack1).isStackTranslucent(any());
+ doReturn(false).when(fullscreenStack2).isStackTranslucent(any());
// Ensure we don't move the home stack behind itself
int homeStackIndex = mDefaultDisplay.getIndexOf(homeStack);
@@ -708,19 +725,19 @@
public void testMoveHomeStackBehindStack() {
mDefaultDisplay.removeChild(mStack);
- final TestActivityStack fullscreenStack1 = createStackForShouldBeVisibleTest(
+ final ActivityStack fullscreenStack1 = createStackForShouldBeVisibleTest(
mDefaultDisplay, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD,
true /* onTop */);
- final TestActivityStack fullscreenStack2 = createStackForShouldBeVisibleTest(
+ final ActivityStack fullscreenStack2 = createStackForShouldBeVisibleTest(
mDefaultDisplay, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD,
true /* onTop */);
- final TestActivityStack fullscreenStack3 = createStackForShouldBeVisibleTest(
+ final ActivityStack fullscreenStack3 = createStackForShouldBeVisibleTest(
mDefaultDisplay, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD,
true /* onTop */);
- final TestActivityStack fullscreenStack4 = createStackForShouldBeVisibleTest(
+ final ActivityStack fullscreenStack4 = createStackForShouldBeVisibleTest(
mDefaultDisplay, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD,
true /* onTop */);
- final TestActivityStack homeStack = createStackForShouldBeVisibleTest(mDefaultDisplay,
+ final ActivityStack homeStack = createStackForShouldBeVisibleTest(mDefaultDisplay,
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, true /* onTop */);
mDefaultDisplay.moveStackBehindStack(homeStack, fullscreenStack1);
@@ -735,13 +752,13 @@
@Test
public void testSetAlwaysOnTop() {
- final TestActivityStack homeStack = createStackForShouldBeVisibleTest(mDefaultDisplay,
+ final ActivityStack homeStack = createStackForShouldBeVisibleTest(mDefaultDisplay,
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, true /* onTop */);
final ActivityStack pinnedStack = createStackForShouldBeVisibleTest(mDefaultDisplay,
WINDOWING_MODE_PINNED, ACTIVITY_TYPE_STANDARD, true /* onTop */);
assertEquals(pinnedStack, mDefaultDisplay.getStackAbove(homeStack));
- final TestActivityStack alwaysOnTopStack = createStackForShouldBeVisibleTest(
+ final ActivityStack alwaysOnTopStack = createStackForShouldBeVisibleTest(
mDefaultDisplay, WINDOWING_MODE_FREEFORM, ACTIVITY_TYPE_STANDARD,
true /* onTop */);
alwaysOnTopStack.setAlwaysOnTop(true);
@@ -749,13 +766,13 @@
// Ensure (non-pinned) always on top stack is put below pinned stack.
assertEquals(pinnedStack, mDefaultDisplay.getStackAbove(alwaysOnTopStack));
- final TestActivityStack nonAlwaysOnTopStack = createStackForShouldBeVisibleTest(
+ final ActivityStack nonAlwaysOnTopStack = createStackForShouldBeVisibleTest(
mDefaultDisplay, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD,
true /* onTop */);
// Ensure non always on top stack is put below always on top stacks.
assertEquals(alwaysOnTopStack, mDefaultDisplay.getStackAbove(nonAlwaysOnTopStack));
- final TestActivityStack alwaysOnTopStack2 = createStackForShouldBeVisibleTest(
+ final ActivityStack alwaysOnTopStack2 = createStackForShouldBeVisibleTest(
mDefaultDisplay, WINDOWING_MODE_FREEFORM, ACTIVITY_TYPE_STANDARD,
true /* onTop */);
alwaysOnTopStack2.setAlwaysOnTop(true);
@@ -780,18 +797,18 @@
@Test
public void testSplitScreenMoveToFront() {
- final TestActivityStack splitScreenPrimary = createStackForShouldBeVisibleTest(
+ final ActivityStack splitScreenPrimary = createStackForShouldBeVisibleTest(
mDefaultDisplay, WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, ACTIVITY_TYPE_STANDARD,
true /* onTop */);
- final TestActivityStack splitScreenSecondary = createStackForShouldBeVisibleTest(
+ final ActivityStack splitScreenSecondary = createStackForShouldBeVisibleTest(
mDefaultDisplay, WINDOWING_MODE_SPLIT_SCREEN_SECONDARY, ACTIVITY_TYPE_STANDARD,
true /* onTop */);
- final TestActivityStack assistantStack = createStackForShouldBeVisibleTest(mDefaultDisplay,
+ final ActivityStack assistantStack = createStackForShouldBeVisibleTest(mDefaultDisplay,
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_ASSISTANT, true /* onTop */);
- splitScreenPrimary.setIsTranslucent(false);
- splitScreenSecondary.setIsTranslucent(false);
- assistantStack.setIsTranslucent(false);
+ doReturn(false).when(splitScreenPrimary).isStackTranslucent(any());
+ doReturn(false).when(splitScreenSecondary).isStackTranslucent(any());
+ doReturn(false).when(assistantStack).isStackTranslucent(any());
assertFalse(splitScreenPrimary.shouldBeVisible(null /* starting */));
assertFalse(splitScreenSecondary.shouldBeVisible(null /* starting */));
@@ -804,18 +821,18 @@
assertFalse(assistantStack.shouldBeVisible(null /* starting */));
}
- private TestActivityStack createStandardStackForVisibilityTest(int windowingMode,
+ private ActivityStack createStandardStackForVisibilityTest(int windowingMode,
boolean translucent) {
- final TestActivityStack stack = createStackForShouldBeVisibleTest(mDefaultDisplay,
+ final ActivityStack stack = createStackForShouldBeVisibleTest(mDefaultDisplay,
windowingMode, ACTIVITY_TYPE_STANDARD, true /* onTop */);
- stack.setIsTranslucent(translucent);
+ doReturn(translucent).when(stack).isStackTranslucent(any());
return stack;
}
@SuppressWarnings("TypeParameterUnusedInFormals")
private <T extends ActivityStack> T createStackForShouldBeVisibleTest(
ActivityDisplay display, int windowingMode, int activityType, boolean onTop) {
- final T stack;
+ final ActivityStack stack;
if (activityType == ACTIVITY_TYPE_HOME) {
// Home stack and activity are created in ActivityTestsBase#setupActivityManagerService
stack = mDefaultDisplay.getStack(WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME);
@@ -825,11 +842,15 @@
mDefaultDisplay.positionChildAtBottom(stack);
}
} else {
- stack = display.createStack(windowingMode, activityType, onTop);
- final ActivityRecord r = new ActivityBuilder(mService).setUid(0).setStack(stack)
- .setCreateTask(true).build();
+ stack = new StackBuilder(mRootActivityContainer)
+ .setDisplay(display)
+ .setWindowingMode(windowingMode)
+ .setActivityType(activityType)
+ .setOnTop(onTop)
+ .setCreateActivity(true)
+ .build();
}
- return stack;
+ return (T) stack;
}
@Test
@@ -961,11 +982,16 @@
@Test
public void testAdjustFocusedStackToHomeWhenNoActivity() {
+ final ActivityStack homeStask = mDefaultDisplay.getHomeStack();
+ TaskRecord homeTask = homeStask.topTask();
+ if (homeTask == null) {
+ // Create home task if there isn't one.
+ homeTask = new TaskBuilder(mSupervisor).setStack(homeStask).build();
+ }
+
final ActivityRecord topActivity = new ActivityBuilder(mService).setTask(mTask).build();
mStack.moveToFront("testAdjustFocusedStack");
- final ActivityStack homeStask = mDefaultDisplay.getHomeStack();
- final TaskRecord homeTask = homeStask.topTask();
// Simulate that home activity has not been started or is force-stopped.
homeStask.removeTask(homeTask, "testAdjustFocusedStack", REMOVE_TASK_MODE_DESTROYING);
@@ -981,6 +1007,14 @@
final ActivityStack homeStack = createStackForShouldBeVisibleTest(mDefaultDisplay,
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, true /* onTop */);
+ ActivityRecord activity = homeStack.topRunningActivityLocked();
+ if (activity == null) {
+ activity = new ActivityBuilder(mService)
+ .setStack(homeStack)
+ .setCreateTask(true)
+ .build();
+ }
+
// Home stack should not be destroyed immediately.
final ActivityRecord activity1 = finishCurrentActivity(homeStack);
assertEquals(FINISHING, activity1.getState());
@@ -1068,7 +1102,7 @@
public void testStackOrderChangedOnPositionStack() {
StackOrderChangedListener listener = new StackOrderChangedListener();
try {
- final TestActivityStack fullscreenStack1 = createStackForShouldBeVisibleTest(
+ final ActivityStack fullscreenStack1 = createStackForShouldBeVisibleTest(
mDefaultDisplay, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD,
true /* onTop */);
mDefaultDisplay.registerStackOrderChangedListener(listener);
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 3d94467..40a029c 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
@@ -329,9 +329,6 @@
any(), any(), any(), anyInt(), anyInt(), anyInt(), any(),
anyBoolean(), anyBoolean(), 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(
@@ -482,7 +479,7 @@
@Test
public void testTaskModeViolation() {
final ActivityDisplay display = mService.mRootActivityContainer.getDefaultDisplay();
- ((TestActivityDisplay) display).removeAllTasks();
+ display.removeAllTasks();
assertNoTasks(display);
final ActivityStarter starter = prepareStarter(0);
@@ -676,18 +673,27 @@
doReturn(isCallingUidDeviceOwner).when(mService).isDeviceOwner(callingUid);
final ActivityOptions options = spy(ActivityOptions.makeBasic());
+ ActivityRecord[] outActivity = new ActivityRecord[1];
ActivityStarter starter = prepareStarter(FLAG_ACTIVITY_NEW_TASK)
.setCallingPackage("com.whatever.dude")
.setCaller(caller)
.setCallingUid(callingUid)
.setRealCallingUid(realCallingUid)
- .setActivityOptions(new SafeActivityOptions(options));
+ .setActivityOptions(new SafeActivityOptions(options))
+ .setOutActivity(outActivity);
final int result = starter.setReason("testBackgroundActivityStarts_" + name).execute();
assertEquals(ActivityStarter.getExternalResult(
shouldHaveAborted ? START_ABORTED : START_SUCCESS), result);
verify(options, times(shouldHaveAborted ? 1 : 0)).abort();
+
+ final ActivityRecord startedActivity = outActivity[0];
+ if (startedActivity != null && startedActivity.getTaskRecord() != null) {
+ // Remove the activity so it doesn't interfere with with subsequent activity launch
+ // tests from this method.
+ startedActivity.getTaskRecord().removeActivity(startedActivity);
+ }
}
/**
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java
index d8a9bb0..297aa7e 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java
@@ -45,8 +45,7 @@
/** Verify that activity is finished correctly upon request. */
@Test
public void testActivityFinish() {
- final TestActivityStack stack =
- (TestActivityStack) new StackBuilder(mRootActivityContainer).build();
+ final ActivityStack stack = new StackBuilder(mRootActivityContainer).build();
final ActivityRecord activity = stack.getChildAt(0).getTopActivity();
assertTrue("Activity must be finished", mService.finishActivity(activity.appToken,
0 /* resultCode */, null /* resultData */,
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 ab2da2b..2e7218d 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java
@@ -16,89 +16,55 @@
package com.android.server.wm;
-import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
-import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
-import static android.view.Display.DEFAULT_DISPLAY;
-import static android.view.DisplayAdjustments.DEFAULT_DISPLAY_ADJUSTMENTS;
+import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE;
+import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.any;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.anyBoolean;
-import static com.android.dx.mockito.inline.extended.ExtendedMockito.anyInt;
-import static com.android.dx.mockito.inline.extended.ExtendedMockito.anyString;
-import static com.android.dx.mockito.inline.extended.ExtendedMockito.doAnswer;
-import static com.android.dx.mockito.inline.extended.ExtendedMockito.doCallRealMethod;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
-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.reset;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
-import static com.android.server.wm.ActivityStack.REMOVE_TASK_MODE_DESTROYING;
-import static com.android.server.wm.ActivityStackSupervisor.ON_TOP;
-import android.app.ActivityManagerInternal;
import android.app.ActivityOptions;
-import android.app.AppOpsManager;
import android.app.IApplicationThread;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
-import android.content.pm.IPackageManager;
-import android.content.pm.PackageManagerInternal;
import android.content.res.Configuration;
import android.graphics.Rect;
-import android.hardware.display.DisplayManager;
-import android.hardware.display.DisplayManagerGlobal;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.PowerManager;
-import android.os.Process;
import android.os.UserHandle;
import android.service.voice.IVoiceInteractionSession;
import android.testing.DexmakerShareClassLoaderRule;
-import android.view.Display;
import android.view.DisplayInfo;
-import com.android.internal.app.IVoiceInteractor;
import com.android.server.AttributeCache;
-import com.android.server.ServiceThread;
-import com.android.server.am.ActivityManagerService;
-import com.android.server.am.PendingIntentController;
-import com.android.server.appop.AppOpsService;
-import com.android.server.firewall.IntentFirewall;
-import com.android.server.policy.PermissionPolicyInternal;
-import com.android.server.uri.UriGrantsManagerInternal;
-import com.android.server.wm.TaskRecord.TaskRecordFactory;
import com.android.server.wm.utils.MockTracker;
import org.junit.After;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Rule;
-import org.mockito.invocation.InvocationOnMock;
-
-import java.io.File;
-import java.util.List;
-import java.util.function.Consumer;
/**
* A base class to handle common operations in activity related unit tests.
*/
class ActivityTestsBase {
- private static int sNextDisplayId = DEFAULT_DISPLAY + 1;
@Rule
public final DexmakerShareClassLoaderRule mDexmakerShareClassLoaderRule =
new DexmakerShareClassLoaderRule();
+ @Rule
+ public final SystemServicesTestRule mSystemServicesTestRule = new SystemServicesTestRule();
+
final Context mContext = getInstrumentation().getTargetContext();
- final TestInjector mTestInjector = new TestInjector(mContext);
ActivityTaskManagerService mService;
RootActivityContainer mRootActivityContainer;
@@ -121,35 +87,24 @@
public void setUpBase() {
mMockTracker = new MockTracker();
- mTestInjector.setUp();
-
- mService = new TestActivityTaskManagerService(mContext);
+ mService = mSystemServicesTestRule.getActivityTaskManagerService();
mSupervisor = mService.mStackSupervisor;
mRootActivityContainer = mService.mRootActivityContainer;
}
@After
public void tearDownBase() {
- mTestInjector.tearDown();
- if (mService != null) {
- mService.setWindowManager(null);
- mService = null;
- }
- if (sMockWindowManagerService != null) {
- reset(sMockWindowManagerService);
- }
-
mMockTracker.close();
mMockTracker = null;
}
/** Creates a {@link TestActivityDisplay}. */
TestActivityDisplay createNewActivityDisplay() {
- return TestActivityDisplay.create(mSupervisor, sNextDisplayId++);
+ return TestActivityDisplay.create(mSupervisor);
}
TestActivityDisplay createNewActivityDisplay(DisplayInfo info) {
- return TestActivityDisplay.create(mSupervisor, sNextDisplayId++, info);
+ return TestActivityDisplay.create(mSupervisor, info);
}
/** Creates and adds a {@link TestActivityDisplay} to supervisor at the given position. */
@@ -166,25 +121,9 @@
return display;
}
- /**
- * Delegates task creation to {@link #TaskBuilder} to avoid the dependency of window hierarchy
- * when starting activity in unit tests.
- */
- void mockTaskRecordFactory(Consumer<TaskBuilder> taskBuilderSetup) {
- final TaskBuilder taskBuilder = new TaskBuilder(mSupervisor).setCreateStack(false);
- if (taskBuilderSetup != null) {
- taskBuilderSetup.accept(taskBuilder);
- }
- final TaskRecord task = taskBuilder.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 */);
- }
-
- void mockTaskRecordFactory() {
- mockTaskRecordFactory(null /* taskBuilderSetup */);
+ /** Sets the default minimum task size to 1 so that tests can use small task sizes */
+ public void removeGlobalMinSizeRestriction() {
+ mService.mRootActivityContainer.mDefaultMinSizeOfResizeableTaskDp = 1;
}
/**
@@ -204,6 +143,11 @@
private ActivityStack mStack;
private int mActivityFlags;
private int mLaunchMode;
+ private int mResizeMode = RESIZE_MODE_RESIZEABLE;
+ private float mMaxAspectRatio;
+ private int mScreenOrientation = SCREEN_ORIENTATION_UNSPECIFIED;
+ private boolean mLaunchTaskBehind;
+ private int mConfigChanges;
ActivityBuilder(ActivityTaskManagerService service) {
mService = service;
@@ -254,6 +198,31 @@
return this;
}
+ ActivityBuilder setResizeMode(int resizeMode) {
+ mResizeMode = resizeMode;
+ return this;
+ }
+
+ ActivityBuilder setMaxAspectRatio(float maxAspectRatio) {
+ mMaxAspectRatio = maxAspectRatio;
+ return this;
+ }
+
+ ActivityBuilder setScreenOrientation(int screenOrientation) {
+ mScreenOrientation = screenOrientation;
+ return this;
+ }
+
+ ActivityBuilder setLaunchTaskBehind(boolean launchTaskBehind) {
+ mLaunchTaskBehind = launchTaskBehind;
+ return this;
+ }
+
+ ActivityBuilder setConfigChanges(int configChanges) {
+ mConfigChanges = configChanges;
+ return this;
+ }
+
ActivityRecord build() {
if (mComponent == null) {
final int id = sCurrentActivityId++;
@@ -279,24 +248,31 @@
}
aInfo.flags |= mActivityFlags;
aInfo.launchMode = mLaunchMode;
+ aInfo.resizeMode = mResizeMode;
+ aInfo.maxAspectRatio = mMaxAspectRatio;
+ aInfo.screenOrientation = mScreenOrientation;
+ aInfo.configChanges |= mConfigChanges;
+
+ ActivityOptions options = null;
+ if (mLaunchTaskBehind) {
+ options = ActivityOptions.makeTaskLaunchBehind();
+ }
final ActivityRecord activity = new ActivityRecord(mService, null /* caller */,
0 /* launchedFromPid */, 0, null, intent, null,
aInfo /*aInfo*/, new Configuration(), null /* resultTo */, null /* resultWho */,
0 /* reqCode */, false /*componentSpecified*/, false /* rootVoiceInteraction */,
- mService.mStackSupervisor, null /* options */, null /* sourceRecord */);
+ mService.mStackSupervisor, options, null /* sourceRecord */);
spyOn(activity);
- activity.mAppWindowToken = mock(AppWindowToken.class);
- doCallRealMethod().when(activity.mAppWindowToken).getOrientationIgnoreVisibility();
- doCallRealMethod().when(activity.mAppWindowToken)
- .setOrientation(anyInt(), any(), any());
- doCallRealMethod().when(activity.mAppWindowToken).setOrientation(anyInt());
- doNothing().when(activity).removeWindowContainer();
- doReturn(mock(Configuration.class)).when(activity.mAppWindowToken)
- .getRequestedOverrideConfiguration();
-
if (mTaskRecord != null) {
- mTaskRecord.addActivityToTop(activity);
+ // fullscreen value is normally read from resources in ctor, so for testing we need
+ // to set it somewhere else since we can't mock resources.
+ activity.fullscreen = true;
+ activity.setTask(mTaskRecord);
+ activity.createAppWindowToken();
+ spyOn(activity.mAppWindowToken);
+ // Make visible by default...
+ activity.mAppWindowToken.setHidden(false);
}
final WindowProcessController wpc = new WindowProcessController(mService,
@@ -305,6 +281,9 @@
mock(WindowProcessListener.class));
wpc.setThread(mock(IApplicationThread.class));
activity.setProcess(wpc);
+
+ // Resume top activities to make sure all other signals in the system are connected.
+ mService.mRootActivityContainer.resumeFocusedStacksTopActivities();
return activity;
}
}
@@ -313,16 +292,13 @@
* Builder for creating new tasks.
*/
protected static class TaskBuilder {
- // Default package name
- static final String DEFAULT_PACKAGE = "com.bar";
-
private final ActivityStackSupervisor mSupervisor;
private ComponentName mComponent;
private String mPackage;
private int mFlags = 0;
// Task id 0 is reserved in ARC for the home app.
- private int mTaskId = 1;
+ private int mTaskId = SystemServicesTestRule.sNextTaskId++;
private int mUserId = 0;
private IVoiceInteractionSession mVoiceSession;
private boolean mCreateStack = true;
@@ -381,6 +357,7 @@
if (mStack == null && mCreateStack) {
mStack = mSupervisor.mRootActivityContainer.getDefaultDisplay().createStack(
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
+ spyOn(mStack);
}
final ActivityInfo aInfo = new ActivityInfo();
@@ -396,450 +373,22 @@
intent.setComponent(mComponent);
intent.setFlags(mFlags);
- final TestTaskRecord task = new TestTaskRecord(mSupervisor.mService, mTaskId, aInfo,
+ final TaskRecord task = new TaskRecord(mSupervisor.mService, mTaskId, aInfo,
intent /*intent*/, mVoiceSession, null /*_voiceInteractor*/);
+ spyOn(task);
task.userId = mUserId;
if (mStack != null) {
mStack.moveToFront("test");
mStack.addTask(task, true, "creating test task");
- task.setStack(mStack);
- task.setTask();
- mStack.getTaskStack().addChild(task.mTask, 0);
+ task.createTask(true, true);
+ spyOn(task.mTask);
}
task.touchActiveTime();
return task;
}
-
- private static class TestTaskRecord extends TaskRecord {
- TestTaskRecord(ActivityTaskManagerService service, int taskId, ActivityInfo info,
- Intent intent, IVoiceInteractionSession voiceSession,
- IVoiceInteractor voiceInteractor) {
- super(service, taskId, info, intent, voiceSession, voiceInteractor);
- }
-
- @Override
- void createTask(boolean onTop, boolean showForAllUsers) {
- setTask();
- }
-
- void setTask() {
- Task mockTask = mock(Task.class);
- mockTask.mTaskRecord = this;
- doCallRealMethod().when(mockTask).onDescendantOrientationChanged(any(), any());
- setTask(mock(Task.class));
- }
- }
- }
-
- protected class TestActivityTaskManagerService extends ActivityTaskManagerService {
- private PackageManagerInternal mPmInternal;
- private PermissionPolicyInternal mPermissionPolicyInternal;
-
- // ActivityStackSupervisor may be created more than once while setting up AMS and ATMS.
- // We keep the reference in order to prevent creating it twice.
- ActivityStackSupervisor mTestStackSupervisor;
-
- ActivityDisplay mDefaultDisplay;
- AppOpsService mAppOpsService;
-
- TestActivityTaskManagerService(Context context) {
- super(context);
- spyOn(this);
-
- mUgmInternal = mock(UriGrantsManagerInternal.class);
- mAppOpsService = mock(AppOpsService.class);
-
- // Make sure permission checks aren't overridden.
- doReturn(AppOpsManager.MODE_DEFAULT)
- .when(mAppOpsService).noteOperation(anyInt(), anyInt(), anyString());
-
- mSupportsMultiWindow = true;
- mSupportsMultiDisplay = true;
- mSupportsSplitScreenMultiWindow = true;
- mSupportsFreeformWindowManagement = true;
- mSupportsPictureInPicture = true;
-
- final TestActivityManagerService am =
- new TestActivityManagerService(mTestInjector, this);
-
- spyOn(getLifecycleManager());
- spyOn(getLockTaskController());
- spyOn(getTaskChangeNotificationController());
- doReturn(mock(IPackageManager.class)).when(this).getPackageManager();
- // allow background activity starts by default
- doReturn(true).when(this).isBackgroundActivityStartsEnabled();
- doNothing().when(this).updateCpuStats();
- }
-
- void setup(IntentFirewall intentFirewall, PendingIntentController intentController,
- ActivityManagerInternal amInternal, WindowManagerService wm, Looper looper) {
- mAmInternal = amInternal;
- initialize(intentFirewall, intentController, looper);
- initRootActivityContainerMocks(wm);
- setWindowManager(wm);
- createDefaultDisplay();
- }
-
- void initRootActivityContainerMocks(WindowManagerService wm) {
- spyOn(mRootActivityContainer);
- mRootActivityContainer.setWindowContainer(mock(RootWindowContainer.class));
- mRootActivityContainer.mWindowManager = wm;
- mRootActivityContainer.mDisplayManager =
- (DisplayManager) mContext.getSystemService(Context.DISPLAY_SERVICE);
- doNothing().when(mRootActivityContainer).setWindowManager(any());
- // Invoked during {@link ActivityStack} creation.
- doNothing().when(mRootActivityContainer).updateUIDsPresentOnDisplay();
- // Always keep things awake.
- doReturn(true).when(mRootActivityContainer).hasAwakeDisplay();
- // Called when moving activity to pinned stack.
- doNothing().when(mRootActivityContainer).ensureActivitiesVisible(any(), anyInt(),
- anyBoolean());
- }
-
- void createDefaultDisplay() {
- // Create a default display and put a home stack on it so that we'll always have
- // something focusable.
- mDefaultDisplay = TestActivityDisplay.create(mStackSupervisor, DEFAULT_DISPLAY);
- spyOn(mDefaultDisplay);
- mRootActivityContainer.addChild(mDefaultDisplay, ActivityDisplay.POSITION_TOP);
- mDefaultDisplay.createStack(WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, ON_TOP);
- final TaskRecord task = new TaskBuilder(mStackSupervisor)
- .setStack(mDefaultDisplay.getHomeStack()).build();
- new ActivityBuilder(this).setTask(task).build();
-
- doReturn(mDefaultDisplay).when(mRootActivityContainer).getDefaultDisplay();
- }
-
- @Override
- int handleIncomingUser(int callingPid, int callingUid, int userId, String name) {
- return userId;
- }
-
- @Override
- AppOpsService getAppOpsService() {
- return mAppOpsService;
- }
-
- @Override
- void updateCpuStats() {
- }
-
- @Override
- void updateBatteryStats(ActivityRecord component, boolean resumed) {
- }
-
- @Override
- void updateActivityUsageStats(ActivityRecord activity, int event) {
- }
-
- @Override
- protected ActivityStackSupervisor createStackSupervisor() {
- if (mTestStackSupervisor == null) {
- mTestStackSupervisor = new TestActivityStackSupervisor(this, mH.getLooper());
- }
- return mTestStackSupervisor;
- }
-
- @Override
- PackageManagerInternal getPackageManagerInternalLocked() {
- if (mPmInternal == null) {
- mPmInternal = mock(PackageManagerInternal.class);
- doReturn(false)
- .when(mPmInternal)
- .isPermissionsReviewRequired(anyString(), anyInt());
- }
- return mPmInternal;
- }
-
- @Override
- PermissionPolicyInternal getPermissionPolicyInternal() {
- if (mPermissionPolicyInternal == null) {
- mPermissionPolicyInternal = mock(PermissionPolicyInternal.class);
- doReturn(true).when(mPermissionPolicyInternal).checkStartActivity(any(), anyInt(),
- any());
- }
- return mPermissionPolicyInternal;
- }
- }
-
- private static class TestInjector extends ActivityManagerService.Injector {
- private ServiceThread mHandlerThread;
-
- TestInjector(Context context) {
- super(context);
- }
-
- @Override
- public AppOpsService getAppOpsService(File file, Handler handler) {
- return null;
- }
-
- @Override
- public Handler getUiHandler(ActivityManagerService service) {
- return mHandlerThread.getThreadHandler();
- }
-
- @Override
- public boolean isNetworkRestrictedForUid(int uid) {
- return false;
- }
-
- void setUp() {
- mHandlerThread = new ServiceThread("ActivityTestsThread",
- Process.THREAD_PRIORITY_DEFAULT, true /* allowIo */);
- mHandlerThread.start();
- }
-
- void tearDown() {
- // Make sure there are no running messages and then quit the thread so the next test
- // won't be affected.
- mHandlerThread.getThreadHandler().runWithScissors(mHandlerThread::quit,
- 0 /* timeout */);
- }
- }
-
- // TODO: Replace this with a mock object since we are no longer in AMS package.
- /**
- * An {@link ActivityManagerService} subclass which provides a test
- * {@link ActivityStackSupervisor}.
- */
- class TestActivityManagerService extends ActivityManagerService {
-
- TestActivityManagerService(TestInjector testInjector, TestActivityTaskManagerService atm) {
- super(testInjector, testInjector.mHandlerThread);
- spyOn(this);
-
- mWindowManager = prepareMockWindowManager();
- mUgmInternal = mock(UriGrantsManagerInternal.class);
-
- atm.setup(mIntentFirewall, mPendingIntentController, new LocalService(), mWindowManager,
- testInjector.mHandlerThread.getLooper());
-
- mActivityTaskManager = atm;
- mAtmInternal = atm.mInternal;
-
- doReturn(mock(IPackageManager.class)).when(this).getPackageManager();
- PackageManagerInternal mockPackageManager = mock(PackageManagerInternal.class);
- doReturn(mockPackageManager).when(this).getPackageManagerInternalLocked();
- doReturn(null).when(mockPackageManager).getDefaultHomeActivity(anyInt());
- doNothing().when(this).grantEphemeralAccessLocked(anyInt(), any(), anyInt(), anyInt());
- }
- }
-
- /**
- * An {@link ActivityStackSupervisor} which stubs out certain methods that depend on
- * setup not available in the test environment. Also specifies an injector for
- */
- protected class TestActivityStackSupervisor extends ActivityStackSupervisor {
- private KeyguardController mKeyguardController;
-
- TestActivityStackSupervisor(ActivityTaskManagerService service, Looper looper) {
- super(service, looper);
- spyOn(this);
- mWindowManager = prepareMockWindowManager();
- mKeyguardController = mock(KeyguardController.class);
-
- // Do not schedule idle that may touch methods outside the scope of the test.
- doNothing().when(this).scheduleIdleLocked();
- doNothing().when(this).scheduleIdleTimeoutLocked(any());
- // unit test version does not handle launch wake lock
- doNothing().when(this).acquireLaunchWakelock();
- doReturn(mKeyguardController).when(this).getKeyguardController();
-
- mLaunchingActivityWakeLock = mock(PowerManager.WakeLock.class);
-
- initialize();
- }
-
- @Override
- public KeyguardController getKeyguardController() {
- return mKeyguardController;
- }
-
- @Override
- void setWindowManager(WindowManagerService wm) {
- mWindowManager = wm;
- }
- }
-
- protected static class TestActivityDisplay extends ActivityDisplay {
- private final ActivityStackSupervisor mSupervisor;
-
- static TestActivityDisplay create(ActivityStackSupervisor supervisor, int displayId) {
- return create(supervisor, displayId, new DisplayInfo());
- }
-
- static TestActivityDisplay create(ActivityStackSupervisor supervisor, int displayId,
- DisplayInfo info) {
- if (displayId == DEFAULT_DISPLAY) {
- return new TestActivityDisplay(supervisor,
- supervisor.mRootActivityContainer.mDisplayManager.getDisplay(displayId));
- }
- final Display display = new Display(DisplayManagerGlobal.getInstance(), displayId,
- info, DEFAULT_DISPLAY_ADJUSTMENTS);
- return new TestActivityDisplay(supervisor, display);
- }
-
- TestActivityDisplay(ActivityStackSupervisor supervisor, Display display) {
- super(supervisor.mService.mRootActivityContainer, display);
- // Normally this comes from display-properties as exposed by WM. Without that, just
- // hard-code to FULLSCREEN for tests.
- setWindowingMode(WINDOWING_MODE_FULLSCREEN);
- mSupervisor = supervisor;
- }
-
- @SuppressWarnings("TypeParameterUnusedInFormals")
- @Override
- ActivityStack createStackUnchecked(int windowingMode, int activityType,
- int stackId, boolean onTop) {
- return new StackBuilder(mSupervisor.mRootActivityContainer).setDisplay(this)
- .setWindowingMode(windowingMode).setActivityType(activityType)
- .setStackId(stackId).setOnTop(onTop).setCreateActivity(false).build();
- }
-
- @Override
- protected DisplayContent createDisplayContent() {
- final DisplayContent displayContent = mock(DisplayContent.class);
- DockedStackDividerController divider = mock(DockedStackDividerController.class);
- doReturn(divider).when(displayContent).getDockedDividerController();
- return displayContent;
- }
-
- void removeAllTasks() {
- for (int i = 0; i < getChildCount(); i++) {
- final ActivityStack stack = getChildAt(i);
- for (TaskRecord task : (List<TaskRecord>) stack.getAllTasks()) {
- stack.removeTask(task, "removeAllTasks", REMOVE_TASK_MODE_DESTROYING);
- }
- }
- }
- }
-
- private static WindowManagerService sMockWindowManagerService;
-
- private static WindowManagerService prepareMockWindowManager() {
- if (sMockWindowManagerService == null) {
- sMockWindowManagerService = mock(WindowManagerService.class);
- }
-
- sMockWindowManagerService.mRoot = mock(RootWindowContainer.class);
-
- doAnswer((InvocationOnMock invocationOnMock) -> {
- final Runnable runnable = invocationOnMock.<Runnable>getArgument(0);
- if (runnable != null) {
- runnable.run();
- }
- return null;
- }).when(sMockWindowManagerService).inSurfaceTransaction(any());
-
- return sMockWindowManagerService;
- }
-
- /**
- * Overridden {@link ActivityStack} that tracks test metrics, such as the number of times a
- * method is called. Note that its functionality depends on the implementations of the
- * construction arguments.
- */
- protected static class TestActivityStack
- extends ActivityStack {
- private int mOnActivityRemovedFromStackCount = 0;
-
- static final int IS_TRANSLUCENT_UNSET = 0;
- static final int IS_TRANSLUCENT_FALSE = 1;
- static final int IS_TRANSLUCENT_TRUE = 2;
- private int mIsTranslucent = IS_TRANSLUCENT_UNSET;
-
- static final int SUPPORTS_SPLIT_SCREEN_UNSET = 0;
- static final int SUPPORTS_SPLIT_SCREEN_FALSE = 1;
- static final int SUPPORTS_SPLIT_SCREEN_TRUE = 2;
- private int mSupportsSplitScreen = SUPPORTS_SPLIT_SCREEN_UNSET;
-
- TestActivityStack(ActivityDisplay display, int stackId, ActivityStackSupervisor supervisor,
- int windowingMode, int activityType, boolean onTop, boolean createActivity) {
- super(display, stackId, supervisor, windowingMode, activityType, onTop);
- if (createActivity) {
- new ActivityBuilder(mService).setCreateTask(true).setStack(this).build();
- if (onTop) {
- // We move the task to front again in order to regain focus after activity
- // added to the stack. Or {@link ActivityDisplay#mPreferredTopFocusableStack}
- // could be other stacks (e.g. home stack).
- moveToFront("createActivityStack");
- } else {
- moveToBack("createActivityStack", null);
- }
- }
- }
-
- @Override
- void onActivityRemovedFromStack(ActivityRecord r) {
- mOnActivityRemovedFromStackCount++;
- super.onActivityRemovedFromStack(r);
- }
-
- // Returns the number of times {@link #onActivityRemovedFromStack} has been called
- int onActivityRemovedFromStackInvocationCount() {
- return mOnActivityRemovedFromStackCount;
- }
-
- @Override
- protected void createTaskStack(int displayId, boolean onTop, Rect outBounds) {
- mTaskStack = mock(TaskStack.class);
-
- // Primary pinned stacks require a non-empty out bounds to be set or else all tasks
- // will be moved to the full screen stack.
- if (getWindowingMode() == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
- outBounds.set(0, 0, 100, 100);
- }
- }
-
- @Override
- TaskStack getTaskStack() {
- return mTaskStack;
- }
-
- void setIsTranslucent(boolean isTranslucent) {
- mIsTranslucent = isTranslucent ? IS_TRANSLUCENT_TRUE : IS_TRANSLUCENT_FALSE;
- }
-
- @Override
- boolean isStackTranslucent(ActivityRecord starting) {
- switch (mIsTranslucent) {
- case IS_TRANSLUCENT_TRUE:
- return true;
- case IS_TRANSLUCENT_FALSE:
- return false;
- case IS_TRANSLUCENT_UNSET:
- default:
- return super.isStackTranslucent(starting);
- }
- }
-
- void setSupportsSplitScreen(boolean supportsSplitScreen) {
- mSupportsSplitScreen = supportsSplitScreen
- ? SUPPORTS_SPLIT_SCREEN_TRUE : SUPPORTS_SPLIT_SCREEN_FALSE;
- }
-
- @Override
- public boolean supportsSplitScreenWindowingMode() {
- switch (mSupportsSplitScreen) {
- case SUPPORTS_SPLIT_SCREEN_TRUE:
- return true;
- case SUPPORTS_SPLIT_SCREEN_FALSE:
- return false;
- case SUPPORTS_SPLIT_SCREEN_UNSET:
- default:
- return super.supportsSplitScreenWindowingMode();
- }
- }
-
- @Override
- void startActivityLocked(ActivityRecord r, ActivityRecord focusedTopActivity,
- boolean newTask, boolean keepCurTransition,
- ActivityOptions options) {
- }
}
static class StackBuilder {
@@ -886,27 +435,45 @@
return this;
}
- @SuppressWarnings("TypeParameterUnusedInFormals")
ActivityStack build() {
final int stackId = mStackId >= 0 ? mStackId : mDisplay.getNextStackId();
+ final ActivityStack stack;
+ final ActivityStackSupervisor supervisor = mRootActivityContainer.mStackSupervisor;
if (mWindowingMode == WINDOWING_MODE_PINNED) {
- return new ActivityStack(mDisplay, stackId, mRootActivityContainer.mStackSupervisor,
+ stack = new ActivityStack(mDisplay, stackId, supervisor,
mWindowingMode, ACTIVITY_TYPE_STANDARD, mOnTop) {
@Override
Rect getDefaultPictureInPictureBounds(float aspectRatio) {
return new Rect(50, 50, 100, 100);
}
-
- @Override
- void createTaskStack(int displayId, boolean onTop, Rect outBounds) {
- mTaskStack = mock(TaskStack.class);
- }
};
} else {
- return new TestActivityStack(mDisplay, stackId,
- mRootActivityContainer.mStackSupervisor, mWindowingMode,
- mActivityType, mOnTop, mCreateActivity);
+ stack = new ActivityStack(mDisplay, stackId, supervisor,
+ mWindowingMode, mActivityType, mOnTop);
+
+ if (mCreateActivity) {
+ new ActivityBuilder(supervisor.mService)
+ .setCreateTask(true)
+ .setStack(stack)
+ .build();
+ if (mOnTop) {
+ // We move the task to front again in order to regain focus after activity
+ // added to the stack.
+ // Or {@link ActivityDisplay#mPreferredTopFocusableStack} could be other
+ // stacks (e.g. home stack).
+ stack.moveToFront("createActivityStack");
+ } else {
+ stack.moveToBack("createActivityStack", null);
+ }
+ }
}
+
+ spyOn(stack);
+ spyOn(stack.mTaskStack);
+ doNothing().when(stack).startActivityLocked(
+ any(), any(), anyBoolean(), anyBoolean(), any());
+
+ return stack;
}
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java b/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java
index d1dc382..c162b6a 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java
@@ -30,12 +30,14 @@
import static com.android.dx.mockito.inline.extended.ExtendedMockito.anyBoolean;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
import android.graphics.Rect;
import android.os.IBinder;
@@ -195,6 +197,7 @@
@Test
public void testCancelRemoteAnimationWhenFreeze() {
final DisplayContent dc = createNewDisplay(Display.STATE_ON);
+ doReturn(false).when(dc).onDescendantOrientationChanged(any(), any());
final WindowState exitingAppWindow = createWindow(null /* parent */, TYPE_BASE_APPLICATION,
dc, "exiting app");
final AppWindowToken exitingAppToken = exitingAppWindow.mAppToken;
diff --git a/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java b/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java
index d9566a3..db2895b 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java
@@ -36,7 +36,7 @@
import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
-import static com.android.dx.mockito.inline.extended.ExtendedMockito.spy;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_AFTER_ANIM;
import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_BEFORE_ANIM;
import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_NONE;
@@ -152,10 +152,6 @@
@Test
@FlakyTest(bugId = 131005232)
public void testLandscapeSeascapeRotationByApp() {
- // Some plumbing to get the service ready for rotation updates.
- mWm.mDisplayReady = true;
- mWm.mDisplayEnabled = true;
-
final WindowManager.LayoutParams attrs = new WindowManager.LayoutParams(
TYPE_BASE_APPLICATION);
attrs.setTitle("AppWindow");
@@ -185,25 +181,21 @@
@Test
public void testLandscapeSeascapeRotationByPolicy() {
- // Some plumbing to get the service ready for rotation updates.
- mWm.mDisplayReady = true;
- mWm.mDisplayEnabled = true;
-
- final DisplayRotation spiedRotation = spy(mDisplayContent.getDisplayRotation());
- mDisplayContent.setDisplayRotation(spiedRotation);
+ final DisplayRotation displayRotation = mDisplayContent.getDisplayRotation();
+ spyOn(displayRotation);
final WindowManager.LayoutParams attrs = new WindowManager.LayoutParams(
TYPE_BASE_APPLICATION);
- attrs.setTitle("AppWindow");
+ attrs.setTitle("RotationByPolicy");
final WindowTestUtils.TestWindowState appWindow = createWindowState(attrs, mToken);
mToken.addWindow(appWindow);
// Set initial orientation and update.
- performRotation(spiedRotation, Surface.ROTATION_90);
+ performRotation(displayRotation, Surface.ROTATION_90);
appWindow.mResizeReported = false;
// Update the rotation to perform 180 degree rotation and check that resize was reported.
- performRotation(spiedRotation, Surface.ROTATION_270);
+ performRotation(displayRotation, Surface.ROTATION_270);
assertTrue(appWindow.mResizeReported);
appWindow.removeImmediately();
@@ -211,14 +203,7 @@
private void performRotation(DisplayRotation spiedRotation, int rotationToReport) {
doReturn(rotationToReport).when(spiedRotation).rotationForOrientation(anyInt(), anyInt());
- int oldRotation = mDisplayContent.getRotation();
mWm.updateRotation(false, false);
- // Must manually apply here since ATM doesn't know about the display during this test
- // (meaning it can't perform the normal sendNewConfiguration flow).
- mDisplayContent.applyRotationLocked(oldRotation, mDisplayContent.getRotation());
- // Prevent the next rotation from being deferred by animation.
- mWm.mAnimator.setScreenRotationAnimationLocked(mDisplayContent.getDisplayId(), null);
- mWm.mRoot.performSurfacePlacement(false /* recoveringMemory */);
}
@Test
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
index 388658d..6289768 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
@@ -83,7 +83,6 @@
import androidx.test.filters.SmallTest;
-import com.android.dx.mockito.inline.extended.ExtendedMockito;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto;
import com.android.server.wm.utils.WmDisplayCutout;
@@ -653,25 +652,27 @@
@Test
public void testOnDescendantOrientationRequestChanged() {
final DisplayContent dc = createNewDisplay();
- mWm.mAtmService.mRootActivityContainer = mock(RootActivityContainer.class);
+ dc.getDisplayRotation().setFixedToUserRotation(
+ DisplayRotation.FIXED_TO_USER_ROTATION_DISABLED);
final int newOrientation = dc.getLastOrientation() == SCREEN_ORIENTATION_LANDSCAPE
? SCREEN_ORIENTATION_PORTRAIT
: SCREEN_ORIENTATION_LANDSCAPE;
- final WindowState window = createWindow(null /* parent */, TYPE_BASE_APPLICATION, dc, "w");
- window.getTask().mTaskRecord = mock(TaskRecord.class, ExtendedMockito.RETURNS_DEEP_STUBS);
- window.mAppToken.setOrientation(newOrientation);
+ final ActivityStack stack =
+ new ActivityTestsBase.StackBuilder(mWm.mAtmService.mRootActivityContainer)
+ .setDisplay(dc.mAcitvityDisplay).build();
+ final ActivityRecord activity = stack.topTask().getTopActivity();
- ActivityRecord activityRecord = mock(ActivityRecord.class);
-
- assertTrue("Display should rotate to handle orientation request by default.",
- dc.onDescendantOrientationChanged(window.mToken.token, activityRecord));
+ activity.setRequestedOrientation(newOrientation);
final ArgumentCaptor<Configuration> captor = ArgumentCaptor.forClass(Configuration.class);
verify(dc.mAcitvityDisplay).updateDisplayOverrideConfigurationLocked(captor.capture(),
- same(activityRecord), anyBoolean(), same(null));
+ same(activity), anyBoolean(), same(null));
final Configuration newDisplayConfig = captor.getValue();
- assertEquals(Configuration.ORIENTATION_PORTRAIT, newDisplayConfig.orientation);
+ final int expectedOrientation = newOrientation == SCREEN_ORIENTATION_PORTRAIT
+ ? Configuration.ORIENTATION_PORTRAIT
+ : Configuration.ORIENTATION_LANDSCAPE;
+ assertEquals(expectedOrientation, newDisplayConfig.orientation);
}
@Test
@@ -679,22 +680,20 @@
final DisplayContent dc = createNewDisplay();
dc.getDisplayRotation().setFixedToUserRotation(
DisplayRotation.FIXED_TO_USER_ROTATION_ENABLED);
- mWm.mAtmService.mRootActivityContainer = mock(RootActivityContainer.class);
final int newOrientation = dc.getLastOrientation() == SCREEN_ORIENTATION_LANDSCAPE
? SCREEN_ORIENTATION_PORTRAIT
: SCREEN_ORIENTATION_LANDSCAPE;
- final WindowState window = createWindow(null /* parent */, TYPE_BASE_APPLICATION, dc, "w");
- window.getTask().mTaskRecord = mock(TaskRecord.class, ExtendedMockito.RETURNS_DEEP_STUBS);
- window.mAppToken.setOrientation(newOrientation);
+ final ActivityStack stack =
+ new ActivityTestsBase.StackBuilder(mWm.mAtmService.mRootActivityContainer)
+ .setDisplay(dc.mAcitvityDisplay).build();
+ final ActivityRecord activity = stack.topTask().getTopActivity();
- ActivityRecord activityRecord = mock(ActivityRecord.class);
+ activity.setRequestedOrientation(newOrientation);
- assertFalse("Display shouldn't rotate to handle orientation request if fixed to"
- + " user rotation.",
- dc.onDescendantOrientationChanged(window.mToken.token, activityRecord));
verify(dc.mAcitvityDisplay, never()).updateDisplayOverrideConfigurationLocked(any(),
- eq(activityRecord), anyBoolean(), same(null));
+ eq(activity), anyBoolean(), same(null));
+ assertEquals(dc.getDisplayRotation().getUserRotation(), dc.getRotation());
}
@Test
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayWindowSettingsTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayWindowSettingsTests.java
index bfede51..f6f8811 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayWindowSettingsTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayWindowSettingsTests.java
@@ -95,7 +95,7 @@
public void setUp() throws Exception {
deleteRecursively(TEST_FOLDER);
- mWm.setSupportsFreeformWindowManagement(false);
+ mWm.mAtmService.mSupportsFreeformWindowManagement = false;
mWm.setIsPc(false);
mWm.setForceDesktopModeOnExternalDisplays(false);
@@ -134,7 +134,7 @@
@Test
public void testPrimaryDisplayDefaultToFullscreen_HasFreeformSupport_NonPc_NoDesktopMode() {
- mWm.setSupportsFreeformWindowManagement(true);
+ mWm.mAtmService.mSupportsFreeformWindowManagement = true;
mTarget.applySettingsToDisplayLocked(mPrimaryDisplay);
@@ -144,7 +144,7 @@
@Test
public void testPrimaryDisplayDefaultToFullscreen_HasFreeformSupport_NonPc_HasDesktopMode() {
- mWm.setSupportsFreeformWindowManagement(true);
+ mWm.mAtmService.mSupportsFreeformWindowManagement = true;
mWm.setForceDesktopModeOnExternalDisplays(true);
mTarget.applySettingsToDisplayLocked(mPrimaryDisplay);
@@ -155,7 +155,7 @@
@Test
public void testPrimaryDisplayDefaultToFreeform_HasFreeformSupport_IsPc() {
- mWm.setSupportsFreeformWindowManagement(true);
+ mWm.mAtmService.mSupportsFreeformWindowManagement = true;
mWm.setIsPc(true);
mTarget.applySettingsToDisplayLocked(mPrimaryDisplay);
@@ -168,7 +168,7 @@
public void testPrimaryDisplayUpdateToFreeform_HasFreeformSupport_IsPc() {
mTarget.applySettingsToDisplayLocked(mPrimaryDisplay);
- mWm.setSupportsFreeformWindowManagement(true);
+ mWm.mAtmService.mSupportsFreeformWindowManagement = true;
mWm.setIsPc(true);
mTarget.updateSettingsForDisplay(mPrimaryDisplay);
@@ -187,7 +187,7 @@
@Test
public void testSecondaryDisplayDefaultToFreeform_HasFreeformSupport_NonPc_NoDesktopMode() {
- mWm.setSupportsFreeformWindowManagement(true);
+ mWm.mAtmService.mSupportsFreeformWindowManagement = true;
mTarget.applySettingsToDisplayLocked(mSecondaryDisplay);
@@ -197,7 +197,7 @@
@Test
public void testSecondaryDisplayDefaultToFreeform_HasFreeformSupport_NonPc_HasDesktopMode() {
- mWm.setSupportsFreeformWindowManagement(true);
+ mWm.mAtmService.mSupportsFreeformWindowManagement = true;
mWm.setForceDesktopModeOnExternalDisplays(true);
mTarget.applySettingsToDisplayLocked(mSecondaryDisplay);
@@ -208,7 +208,7 @@
@Test
public void testSecondaryDisplayDefaultToFreeform_HasFreeformSupport_IsPc() {
- mWm.setSupportsFreeformWindowManagement(true);
+ mWm.mAtmService.mSupportsFreeformWindowManagement = true;
mWm.setIsPc(true);
mTarget.applySettingsToDisplayLocked(mSecondaryDisplay);
diff --git a/services/tests/wmtests/src/com/android/server/wm/LaunchParamsControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/LaunchParamsControllerTests.java
index b28ae40..be2ee29 100644
--- a/services/tests/wmtests/src/com/android/server/wm/LaunchParamsControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/LaunchParamsControllerTests.java
@@ -331,7 +331,9 @@
mController.layoutTask(task, null /* windowLayout */);
- assertEquals(expected, task.getBounds());
+ // TaskRecord will make adjustments to requested bounds. We only need to guarantee that the
+ // reuqested bounds are expected.
+ assertEquals(expected, task.getRequestedOverrideBounds());
}
/**
diff --git a/services/tests/wmtests/src/com/android/server/wm/LaunchParamsPersisterTests.java b/services/tests/wmtests/src/com/android/server/wm/LaunchParamsPersisterTests.java
index e4d3770..49d778f 100644
--- a/services/tests/wmtests/src/com/android/server/wm/LaunchParamsPersisterTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/LaunchParamsPersisterTests.java
@@ -104,6 +104,7 @@
mDisplayUniqueId = "test:" + Integer.toString(sNextUniqueId++);
final DisplayInfo info = new DisplayInfo();
+ mService.mContext.getDisplay().getDisplayInfo(info);
info.uniqueId = mDisplayUniqueId;
mTestDisplay = createNewActivityDisplay(info);
mRootActivityContainer.addChild(mTestDisplay, ActivityDisplay.POSITION_TOP);
diff --git a/services/tests/wmtests/src/com/android/server/wm/PinnedStackControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/PinnedStackControllerTest.java
index 63d9fb9..efd468f 100644
--- a/services/tests/wmtests/src/com/android/server/wm/PinnedStackControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/PinnedStackControllerTest.java
@@ -61,7 +61,7 @@
@Test
public void setShelfHeight_shelfVisibilityChangedTriggered() throws RemoteException {
- mWm.mSupportsPictureInPicture = true;
+ mWm.mAtmService.mSupportsPictureInPicture = true;
mWm.registerPinnedStackListener(DEFAULT_DISPLAY, mIPinnedStackListener);
verify(mIPinnedStackListener).onImeVisibilityChanged(false, 0);
diff --git a/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java b/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java
index b7a85d7..fb4e330 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java
@@ -32,7 +32,7 @@
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
-import static com.android.dx.mockito.inline.extended.ExtendedMockito.spy;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth.assertWithMessage;
@@ -53,14 +53,12 @@
import android.app.ActivityTaskManager;
import android.app.WindowConfiguration;
import android.content.ComponentName;
-import android.content.Context;
import android.content.pm.PackageManager;
import android.content.pm.ParceledListSlice;
import android.content.pm.UserInfo;
import android.content.res.Configuration;
import android.graphics.Rect;
import android.os.Bundle;
-import android.os.Looper;
import android.os.RemoteException;
import android.os.SystemClock;
import android.platform.test.annotations.Presubmit;
@@ -93,11 +91,8 @@
private static final int TEST_QUIET_USER_ID = 20;
private static final UserInfo DEFAULT_USER_INFO = new UserInfo();
private static final UserInfo QUIET_USER_INFO = new UserInfo();
- private static int sLastTaskId = 1;
- private static int sLastStackId = 1;
private static final int INVALID_STACK_ID = 999;
- private TestActivityTaskManagerService mTestService;
private ActivityDisplay mDisplay;
private ActivityDisplay mOtherDisplay;
private ActivityDisplay mSingleTaskDisplay;
@@ -115,13 +110,29 @@
@Before
public void setUp() throws Exception {
mTaskPersister = new TestTaskPersister(mContext.getFilesDir());
- mTestService = new MyTestActivityTaskManagerService(mContext);
- mRecentTasks = (TestRecentTasks) mTestService.getRecentTasks();
+
+ // Set testing displays
+ mDisplay = mRootActivityContainer.getActivityDisplay(DEFAULT_DISPLAY);
+ mOtherDisplay = createNewActivityDisplay();
+ mSingleTaskDisplay = createNewActivityDisplay();
+ mSingleTaskDisplay.setDisplayToSingleTaskInstance();
+ mRootActivityContainer.addChild(mOtherDisplay, ActivityDisplay.POSITION_TOP);
+ mRootActivityContainer.addChild(mDisplay, ActivityDisplay.POSITION_TOP);
+ mRootActivityContainer.addChild(mSingleTaskDisplay, ActivityDisplay.POSITION_TOP);
+
+ // Set the recent tasks we should use for testing in this class.
+ mRecentTasks = new TestRecentTasks(mService, mTaskPersister);
+ spyOn(mRecentTasks);
+ mService.setRecentTasks(mRecentTasks);
mRecentTasks.loadParametersFromResources(mContext.getResources());
- mRunningTasks = (TestRunningTasks) mTestService.mStackSupervisor.mRunningTasks;
- mHomeStack = mTestService.mRootActivityContainer.getDefaultDisplay().getOrCreateStack(
+
+ // Set the running tasks we should use for testing in this class.
+ mRunningTasks = new TestRunningTasks();
+ mService.mStackSupervisor.setRunningTasks(mRunningTasks);
+
+ mHomeStack = mDisplay.getOrCreateStack(
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, true /* onTop */);
- mStack = mTestService.mRootActivityContainer.getDefaultDisplay().createStack(
+ mStack = mDisplay.createStack(
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
mCallbacksRecorder = new CallbacksRecorder();
mRecentTasks.registerCallback(mCallbacksRecorder);
@@ -723,7 +734,7 @@
ActivityStack stack = mTasks.get(2).getStack();
stack.moveToFront("", mTasks.get(2));
- doReturn(stack).when(mTestService.mRootActivityContainer).getTopDisplayFocusedStack();
+ doReturn(stack).when(mService.mRootActivityContainer).getTopDisplayFocusedStack();
// Simulate the reset from the timeout
mRecentTasks.resetFreezeTaskListReorderingOnTimeout();
@@ -742,10 +753,9 @@
public void testBackStackTasks_expectNoTrim() {
mRecentTasks.setParameters(-1 /* min */, 1 /* max */, -1 /* ms */);
- final MyTestActivityStackSupervisor supervisor =
- (MyTestActivityStackSupervisor) mTestService.mStackSupervisor;
final ActivityStack homeStack = mDisplay.getHomeStack();
- final ActivityStack aboveHomeStack = new MyTestActivityStack(mDisplay, supervisor);
+ final ActivityStack aboveHomeStack = mDisplay.createStack(
+ WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
// Add a number of tasks (beyond the max) but ensure that nothing is trimmed because all
// the tasks belong in stacks above the home stack
@@ -761,11 +771,11 @@
public void testBehindHomeStackTasks_expectTaskTrimmed() {
mRecentTasks.setParameters(-1 /* min */, 1 /* max */, -1 /* ms */);
- final MyTestActivityStackSupervisor supervisor =
- (MyTestActivityStackSupervisor) mTestService.mStackSupervisor;
- final ActivityStack behindHomeStack = new MyTestActivityStack(mDisplay, supervisor);
+ final ActivityStack behindHomeStack = mDisplay.createStack(
+ WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
final ActivityStack homeStack = mDisplay.getHomeStack();
- final ActivityStack aboveHomeStack = new MyTestActivityStack(mDisplay, supervisor);
+ final ActivityStack aboveHomeStack = mDisplay.createStack(
+ WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
// Add a number of tasks (beyond the max) but ensure that only the task in the stack behind
// the home stack is trimmed once a new task is added
@@ -783,10 +793,9 @@
public void testOtherDisplayTasks_expectNoTrim() {
mRecentTasks.setParameters(-1 /* min */, 1 /* max */, -1 /* ms */);
- final MyTestActivityStackSupervisor supervisor =
- (MyTestActivityStackSupervisor) mTestService.mStackSupervisor;
final ActivityStack homeStack = mDisplay.getHomeStack();
- final ActivityStack otherDisplayStack = new MyTestActivityStack(mOtherDisplay, supervisor);
+ final ActivityStack otherDisplayStack = mOtherDisplay.createStack(
+ WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
// Add a number of tasks (beyond the max) on each display, ensure that the tasks are not
// removed
@@ -887,16 +896,16 @@
mStack.remove();
// The following APIs should not restore task from recents to the active list.
- assertNotRestoreTask(() -> mTestService.setFocusedTask(taskId));
- assertNotRestoreTask(() -> mTestService.startSystemLockTaskMode(taskId));
- assertNotRestoreTask(() -> mTestService.cancelTaskWindowTransition(taskId));
+ assertNotRestoreTask(() -> mService.setFocusedTask(taskId));
+ assertNotRestoreTask(() -> mService.startSystemLockTaskMode(taskId));
+ assertNotRestoreTask(() -> mService.cancelTaskWindowTransition(taskId));
assertNotRestoreTask(
- () -> mTestService.resizeTask(taskId, null /* bounds */, 0 /* resizeMode */));
+ () -> mService.resizeTask(taskId, null /* bounds */, 0 /* resizeMode */));
assertNotRestoreTask(
- () -> mTestService.setTaskWindowingMode(taskId, WINDOWING_MODE_FULLSCREEN,
+ () -> mService.setTaskWindowingMode(taskId, WINDOWING_MODE_FULLSCREEN,
false/* toTop */));
assertNotRestoreTask(
- () -> mTestService.setTaskWindowingModeSplitScreenPrimary(taskId,
+ () -> mService.setTaskWindowingModeSplitScreenPrimary(taskId,
SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT,
false /* toTop */, false /* animate */, null /* initialBounds */,
true /* showRecents */));
@@ -910,7 +919,7 @@
mRecentTasks.remove(task);
TaskChangeNotificationController controller =
- mTestService.getTaskChangeNotificationController();
+ mService.getTaskChangeNotificationController();
verify(controller, times(2)).notifyTaskListUpdated();
}
@@ -923,7 +932,7 @@
// 2 calls - Once for add and once for remove
TaskChangeNotificationController controller =
- mTestService.getTaskChangeNotificationController();
+ mService.getTaskChangeNotificationController();
verify(controller, times(2)).notifyTaskListUpdated();
}
@@ -938,7 +947,7 @@
// 4 calls - Twice for add and twice for remove
TaskChangeNotificationController controller =
- mTestService.getTaskChangeNotificationController();
+ mService.getTaskChangeNotificationController();
verify(controller, times(4)).notifyTaskListUpdated();
}
@@ -980,7 +989,7 @@
@Test
public void testNotRecentsComponent_denyApiAccess() throws Exception {
- doReturn(PackageManager.PERMISSION_DENIED).when(mTestService)
+ doReturn(PackageManager.PERMISSION_DENIED).when(mService)
.checkGetTasksPermission(anyString(), anyInt(), anyInt());
// Expect the following methods to fail due to recents component not being set
mRecentTasks.setIsCallerRecentsOverride(TestRecentTasks.DENY_THROW_SECURITY_EXCEPTION);
@@ -992,7 +1001,7 @@
@Test
public void testRecentsComponent_allowApiAccessWithoutPermissions() {
- doReturn(PackageManager.PERMISSION_DENIED).when(mTestService)
+ doReturn(PackageManager.PERMISSION_DENIED).when(mService)
.checkGetTasksPermission(anyString(), anyInt(), anyInt());
// Set the recents component and ensure that the following calls do not fail
@@ -1002,62 +1011,62 @@
}
private void doTestRecentTasksApis(boolean expectCallable) {
- assertSecurityException(expectCallable, () -> mTestService.removeStack(INVALID_STACK_ID));
+ assertSecurityException(expectCallable, () -> mService.removeStack(INVALID_STACK_ID));
assertSecurityException(expectCallable,
- () -> mTestService.removeStacksInWindowingModes(
+ () -> mService.removeStacksInWindowingModes(
new int[]{WINDOWING_MODE_UNDEFINED}));
assertSecurityException(expectCallable,
- () -> mTestService.removeStacksWithActivityTypes(
+ () -> mService.removeStacksWithActivityTypes(
new int[]{ACTIVITY_TYPE_UNDEFINED}));
- assertSecurityException(expectCallable, () -> mTestService.removeTask(0));
+ assertSecurityException(expectCallable, () -> mService.removeTask(0));
assertSecurityException(expectCallable,
- () -> mTestService.setTaskWindowingMode(0, WINDOWING_MODE_UNDEFINED, true));
+ () -> mService.setTaskWindowingMode(0, WINDOWING_MODE_UNDEFINED, true));
assertSecurityException(expectCallable,
- () -> mTestService.moveTaskToStack(0, INVALID_STACK_ID, true));
+ () -> mService.moveTaskToStack(0, INVALID_STACK_ID, true));
assertSecurityException(expectCallable,
- () -> mTestService.setTaskWindowingModeSplitScreenPrimary(0,
+ () -> mService.setTaskWindowingModeSplitScreenPrimary(0,
SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT, true, true, new Rect(), true));
- assertSecurityException(expectCallable, () -> mTestService.dismissSplitScreenMode(true));
- assertSecurityException(expectCallable, () -> mTestService.dismissPip(true, 0));
+ assertSecurityException(expectCallable, () -> mService.dismissSplitScreenMode(true));
+ assertSecurityException(expectCallable, () -> mService.dismissPip(true, 0));
assertSecurityException(expectCallable,
- () -> mTestService.moveTopActivityToPinnedStack(INVALID_STACK_ID, new Rect()));
+ () -> mService.moveTopActivityToPinnedStack(INVALID_STACK_ID, new Rect()));
assertSecurityException(expectCallable,
- () -> mTestService.resizeStack(INVALID_STACK_ID, new Rect(), true, true, true, 0));
+ () -> mService.resizeStack(INVALID_STACK_ID, new Rect(), true, true, true, 0));
assertSecurityException(expectCallable,
- () -> mTestService.resizeDockedStack(new Rect(), new Rect(), new Rect(), new Rect(),
+ () -> mService.resizeDockedStack(new Rect(), new Rect(), new Rect(), new Rect(),
new Rect()));
assertSecurityException(expectCallable,
- () -> mTestService.resizePinnedStack(new Rect(), new Rect()));
- assertSecurityException(expectCallable, () -> mTestService.getAllStackInfos());
+ () -> mService.resizePinnedStack(new Rect(), new Rect()));
+ assertSecurityException(expectCallable, () -> mService.getAllStackInfos());
assertSecurityException(expectCallable,
- () -> mTestService.getStackInfo(WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_UNDEFINED));
+ () -> mService.getStackInfo(WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_UNDEFINED));
assertSecurityException(expectCallable, () -> {
try {
- mTestService.getFocusedStackInfo();
+ mService.getFocusedStackInfo();
} catch (RemoteException e) {
// Ignore
}
});
assertSecurityException(expectCallable,
- () -> mTestService.moveTasksToFullscreenStack(INVALID_STACK_ID, true));
+ () -> mService.moveTasksToFullscreenStack(INVALID_STACK_ID, true));
assertSecurityException(expectCallable,
- () -> mTestService.startActivityFromRecents(0, new Bundle()));
- assertSecurityException(expectCallable, () -> mTestService.getTaskSnapshot(0, true));
- assertSecurityException(expectCallable, () -> mTestService.registerTaskStackListener(null));
+ () -> mService.startActivityFromRecents(0, new Bundle()));
+ assertSecurityException(expectCallable, () -> mService.getTaskSnapshot(0, true));
+ assertSecurityException(expectCallable, () -> mService.registerTaskStackListener(null));
assertSecurityException(expectCallable,
- () -> mTestService.unregisterTaskStackListener(null));
- assertSecurityException(expectCallable, () -> mTestService.getTaskDescription(0));
- assertSecurityException(expectCallable, () -> mTestService.cancelTaskWindowTransition(0));
- assertSecurityException(expectCallable, () -> mTestService.startRecentsActivity(null, null,
+ () -> mService.unregisterTaskStackListener(null));
+ assertSecurityException(expectCallable, () -> mService.getTaskDescription(0));
+ assertSecurityException(expectCallable, () -> mService.cancelTaskWindowTransition(0));
+ assertSecurityException(expectCallable, () -> mService.startRecentsActivity(null, null,
null));
- assertSecurityException(expectCallable, () -> mTestService.cancelRecentsAnimation(true));
- assertSecurityException(expectCallable, () -> mTestService.stopAppSwitches());
- assertSecurityException(expectCallable, () -> mTestService.resumeAppSwitches());
+ assertSecurityException(expectCallable, () -> mService.cancelRecentsAnimation(true));
+ assertSecurityException(expectCallable, () -> mService.stopAppSwitches());
+ assertSecurityException(expectCallable, () -> mService.resumeAppSwitches());
}
private void testGetTasksApis(boolean expectCallable) {
- mTestService.getRecentTasks(MAX_VALUE, 0, TEST_USER_0_ID);
- mTestService.getTasks(MAX_VALUE);
+ mService.getRecentTasks(MAX_VALUE, 0, TEST_USER_0_ID);
+ mService.getTasks(MAX_VALUE);
if (expectCallable) {
assertTrue(mRecentTasks.mLastAllowed);
assertTrue(mRunningTasks.mLastAllowed);
@@ -1072,10 +1081,9 @@
}
private TaskBuilder createTaskBuilder(String packageName, String className) {
- return new TaskBuilder(mTestService.mStackSupervisor)
+ return new TaskBuilder(mService.mStackSupervisor)
.setComponent(new ComponentName(packageName, className))
.setStack(mStack)
- .setTaskId(sLastTaskId++)
.setUserId(TEST_USER_0_ID);
}
@@ -1140,68 +1148,6 @@
}
}
- private class MyTestActivityTaskManagerService extends TestActivityTaskManagerService {
- MyTestActivityTaskManagerService(Context context) {
- super(context);
- }
-
- @Override
- protected RecentTasks createRecentTasks() {
- return spy(new TestRecentTasks(this, mTaskPersister));
- }
-
- @Override
- protected ActivityStackSupervisor createStackSupervisor() {
- if (mTestStackSupervisor == null) {
- mTestStackSupervisor = new MyTestActivityStackSupervisor(this, mH.getLooper());
- }
- return mTestStackSupervisor;
- }
-
- @Override
- void createDefaultDisplay() {
- super.createDefaultDisplay();
- mDisplay = mRootActivityContainer.getActivityDisplay(DEFAULT_DISPLAY);
- mOtherDisplay = TestActivityDisplay.create(mTestStackSupervisor, DEFAULT_DISPLAY + 1);
- mSingleTaskDisplay = TestActivityDisplay.create(mTestStackSupervisor,
- DEFAULT_DISPLAY + 2);
- mSingleTaskDisplay.setDisplayToSingleTaskInstance();
- mRootActivityContainer.addChild(mOtherDisplay, ActivityDisplay.POSITION_TOP);
- mRootActivityContainer.addChild(mDisplay, ActivityDisplay.POSITION_TOP);
- mRootActivityContainer.addChild(mSingleTaskDisplay, ActivityDisplay.POSITION_TOP);
- }
- }
-
- private class MyTestActivityStackSupervisor extends TestActivityStackSupervisor {
- MyTestActivityStackSupervisor(ActivityTaskManagerService service, Looper looper) {
- super(service, looper);
- }
-
- @Override
- RunningTasks createRunningTasks() {
- mRunningTasks = new TestRunningTasks();
- return mRunningTasks;
- }
- }
-
- private static class MyTestActivityStack extends TestActivityStack {
- private ActivityDisplay mDisplay = null;
-
- MyTestActivityStack(ActivityDisplay display, ActivityStackSupervisor supervisor) {
- super(display, sLastStackId++, supervisor, WINDOWING_MODE_FULLSCREEN,
- ACTIVITY_TYPE_STANDARD, true /* onTop */, false /* createActivity */);
- mDisplay = display;
- }
-
- @Override
- ActivityDisplay getDisplay() {
- if (mDisplay != null) {
- return mDisplay;
- }
- return super.getDisplay();
- }
- }
-
private static class CallbacksRecorder implements Callbacks {
public final ArrayList<TaskRecord> mAdded = new ArrayList<>();
public final ArrayList<TaskRecord> mTrimmed = new ArrayList<>();
diff --git a/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java
index f5a1d75..ce5a211 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java
@@ -30,6 +30,7 @@
import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.verifyNoMoreInteractions;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.when;
+import static com.android.server.wm.ActivityStackSupervisor.ON_TOP;
import static com.android.server.wm.RecentsAnimationController.REORDER_KEEP_IN_PLACE;
import static com.android.server.wm.RecentsAnimationController.REORDER_MOVE_TO_ORIGINAL_POSITION;
@@ -132,8 +133,14 @@
@Test
public void testIncludedApps_expectTargetAndVisible() {
mWm.setRecentsAnimationController(mController);
- final AppWindowToken homeAppWindow = createAppWindowToken(mDisplayContent,
- WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME);
+ final ActivityStack homStack = mDisplayContent.mAcitvityDisplay.getOrCreateStack(
+ WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, ON_TOP);
+ final AppWindowToken homeAppWindow =
+ new ActivityTestsBase.ActivityBuilder(mWm.mAtmService)
+ .setStack(homStack)
+ .setCreateTask(true)
+ .build()
+ .mAppWindowToken;
final AppWindowToken appWindow = createAppWindowToken(mDisplayContent,
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
final AppWindowToken hiddenAppWindow = createAppWindowToken(mDisplayContent,
diff --git a/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationTest.java b/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationTest.java
index 0e119e3..e2074f5 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationTest.java
@@ -74,8 +74,9 @@
@Before
public void setUp() throws Exception {
mRecentsAnimationController = mock(RecentsAnimationController.class);
- doReturn(mRecentsAnimationController).when(
- mService.mWindowManager).getRecentsAnimationController();
+ mService.mWindowManager.setRecentsAnimationController(mRecentsAnimationController);
+ doNothing().when(mService.mWindowManager).initializeRecentsAnimation(
+ anyInt(), any(), any(), anyInt(), any());
doReturn(true).when(mService.mWindowManager).canStartRecentsAnimation();
final RecentTasks recentTasks = mService.getRecentTasks();
@@ -115,8 +116,18 @@
@Test
public void testPreloadRecentsActivity() {
- // Ensure that the fake recent component can be resolved by the recents intent.
- mockTaskRecordFactory(builder -> builder.setComponent(mRecentsComponent));
+ final ActivityDisplay defaultDisplay = mRootActivityContainer.getDefaultDisplay();
+ final ActivityStack homeStack =
+ defaultDisplay.getStack(WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME);
+ defaultDisplay.positionChildAtTop(homeStack, false /* includingParents */);
+ ActivityRecord topRunningHomeActivity = homeStack.topRunningActivityLocked();
+ if (topRunningHomeActivity == null) {
+ topRunningHomeActivity = new ActivityBuilder(mService)
+ .setStack(homeStack)
+ .setCreateTask(true)
+ .build();
+ }
+
ActivityInfo aInfo = new ActivityInfo();
aInfo.applicationInfo = new ApplicationInfo();
aInfo.applicationInfo.uid = 10001;
@@ -204,6 +215,13 @@
ActivityStack homeStack = display.getHomeStack();
// Assume the home activity support recents.
ActivityRecord targetActivity = homeStack.getTopActivity();
+ if (targetActivity == null) {
+ targetActivity = new ActivityBuilder(mService)
+ .setCreateTask(true)
+ .setStack(homeStack)
+ .build();
+ }
+
// Put another home activity in home stack.
ActivityRecord anotherHomeActivity = new ActivityBuilder(mService)
.setComponent(new ComponentName(mContext.getPackageName(), "Home2"))
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 d4f24f9..539a79c 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java
@@ -97,7 +97,7 @@
*/
@Test
public void testRestoringInvalidTask() {
- ((TestActivityDisplay) mRootActivityContainer.getDefaultDisplay()).removeAllTasks();
+ mRootActivityContainer.getDefaultDisplay().removeAllTasks();
TaskRecord task = mRootActivityContainer.anyTaskForId(0 /*taskId*/,
MATCH_TASK_IN_STACKS_OR_RECENT_TASKS_AND_RESTORE, null, false /* onTop */);
assertNull(task);
@@ -304,21 +304,23 @@
*/
@Test
public void testResizeDockedStackForSplitScreenPrimary() {
- final Rect taskSize = new Rect(0, 0, 600, 600);
+ final Rect taskSize = new Rect(0, 0, 1000, 1000);
final Rect stackSize = new Rect(0, 0, 300, 300);
// Create primary split-screen stack with a task.
- final ActivityStack primaryStack = mRootActivityContainer.getDefaultDisplay()
- .createStack(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, ACTIVITY_TYPE_STANDARD,
- true /* onTop */);
- final TaskRecord task = new TaskBuilder(mSupervisor).setStack(primaryStack).build();
+ final ActivityStack primaryStack = new StackBuilder(mRootActivityContainer)
+ .setActivityType(ACTIVITY_TYPE_STANDARD)
+ .setWindowingMode(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY)
+ .setOnTop(true)
+ .build();
+ final TaskRecord task = primaryStack.topTask();
// Resize dock stack.
mService.resizeDockedStack(stackSize, taskSize, null, null, null);
// Verify dock stack & its task bounds if is equal as resized result.
- assertEquals(primaryStack.getBounds(), stackSize);
- assertEquals(task.getBounds(), taskSize);
+ assertEquals(stackSize, primaryStack.getBounds());
+ assertEquals(taskSize, task.getBounds());
}
/**
@@ -328,8 +330,9 @@
public void testFindTaskToMoveToFrontWhenRecentsOnTop() {
// Create stack/task on default display.
final ActivityDisplay display = mRootActivityContainer.getDefaultDisplay();
- final TestActivityStack targetStack = (TestActivityStack) new StackBuilder(
- mRootActivityContainer).setOnTop(false).build();
+ final ActivityStack targetStack = new StackBuilder(mRootActivityContainer)
+ .setOnTop(false)
+ .build();
final TaskRecord targetTask = targetStack.getChildAt(0);
// Create Recents on top of the display.
@@ -505,12 +508,10 @@
mockResolveSecondaryHomeActivity();
// Create secondary displays.
- final TestActivityDisplay secondDisplay = spy(createNewActivityDisplay());
+ final TestActivityDisplay secondDisplay = createNewActivityDisplay();
mRootActivityContainer.addChild(secondDisplay, POSITION_TOP);
doReturn(true).when(secondDisplay).supportsSystemDecorations();
- // Create mock tasks and other necessary mocks.
- mockTaskRecordFactory();
doReturn(true).when(mRootActivityContainer)
.ensureVisibilityAndConfig(any(), anyInt(), anyBoolean(), anyBoolean());
doReturn(true).when(mRootActivityContainer).canStartHomeOnDisplay(
@@ -621,7 +622,6 @@
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();
diff --git a/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java b/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java
index f51ce13..db105dd 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java
@@ -96,7 +96,7 @@
mWm.getDefaultDisplayContentLocked().getWindowingMode());
mWm.mIsPc = true;
- mWm.mSupportsFreeformWindowManagement = true;
+ mWm.mAtmService.mSupportsFreeformWindowManagement = true;
mWm.mRoot.onSettingsRetrieved();
diff --git a/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java b/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java
index df7c9a4..c42098e 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java
@@ -16,6 +16,9 @@
package com.android.server.wm;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+import static android.os.Process.THREAD_PRIORITY_DEFAULT;
import static android.testing.DexmakerShareClassLoaderRule.runWithDexmakerShareClassLoader;
import static android.view.Display.DEFAULT_DISPLAY;
@@ -25,61 +28,89 @@
import static com.android.dx.mockito.inline.extended.ExtendedMockito.anyBoolean;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.anyInt;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.anyString;
-import static com.android.dx.mockito.inline.extended.ExtendedMockito.doAnswer;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.eq;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.nullable;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.spy;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
import android.app.ActivityManagerInternal;
import android.app.AppOpsManager;
+import android.app.usage.UsageStatsManagerInternal;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.Context;
import android.content.IntentFilter;
+import android.content.pm.IPackageManager;
+import android.content.pm.PackageManagerInternal;
import android.database.ContentObserver;
+import android.hardware.display.DisplayManager;
import android.hardware.display.DisplayManagerInternal;
import android.net.Uri;
import android.os.Handler;
+import android.os.Looper;
+import android.os.PowerManager;
import android.os.PowerManagerInternal;
import android.os.PowerSaveState;
import android.os.UserHandle;
-import android.view.Display;
+import android.provider.DeviceConfig;
import android.view.InputChannel;
+import android.view.Surface;
+import android.view.SurfaceControl;
import com.android.dx.mockito.inline.extended.StaticMockitoSession;
import com.android.server.LocalServices;
import com.android.server.LockGuard;
+import com.android.server.ServiceThread;
import com.android.server.Watchdog;
+import com.android.server.am.ActivityManagerService;
+import com.android.server.appop.AppOpsService;
+import com.android.server.display.color.ColorDisplayService;
import com.android.server.input.InputManagerService;
+import com.android.server.policy.PermissionPolicyInternal;
import com.android.server.policy.WindowManagerPolicy;
+import com.android.server.statusbar.StatusBarManagerInternal;
+import com.android.server.uri.UriGrantsManagerInternal;
import com.android.server.wm.utils.MockTracker;
import org.junit.rules.TestRule;
import org.junit.runner.Description;
import org.junit.runners.model.Statement;
-import org.mockito.invocation.InvocationOnMock;
import org.mockito.quality.Strictness;
+import java.io.File;
import java.util.concurrent.atomic.AtomicBoolean;
/**
- * JUnit test rule to create a mock {@link WindowManagerService} instance for tests.
+ * JUnit test rule to correctly setting up system services like {@link WindowManagerService}
+ * and {@link ActivityTaskManagerService} for tests.
*/
public class SystemServicesTestRule implements TestRule {
private static final String TAG = SystemServicesTestRule.class.getSimpleName();
+ static int sNextDisplayId = DEFAULT_DISPLAY + 100;
+ static int sNextTaskId = 100;
+
private final AtomicBoolean mCurrentMessagesProcessed = new AtomicBoolean(false);
+ private Context mContext;
private MockTracker mMockTracker;
private StaticMockitoSession mMockitoSession;
- private WindowManagerService mWindowManagerService;
- private TestWindowManagerPolicy mWindowManagerPolicy;
+ ServiceThread mHandlerThread;
+ private ActivityManagerService mAmService;
+ private ActivityTaskManagerService mAtmService;
+ private WindowManagerService mWmService;
+ private TestWindowManagerPolicy mWMPolicy;
+ private InputManagerService mImService;
+ /**
+ * Spied {@link SurfaceControl.Transaction} class than can be used to verify calls.
+ */
+ SurfaceControl.Transaction mTransaction;
/** {@link MockTracker} to track mocks created by {@link SystemServicesTestRule}. */
private static class Tracker extends MockTracker {
@@ -103,92 +134,183 @@
}
private void setUp() {
- mMockTracker = new Tracker();
+ try {
+ mMockTracker = new Tracker();
- mMockitoSession = mockitoSession()
- .spyStatic(LocalServices.class)
- .mockStatic(LockGuard.class)
- .mockStatic(Watchdog.class)
- .strictness(Strictness.LENIENT)
- .startMocking();
+ mMockitoSession = mockitoSession()
+ .spyStatic(LocalServices.class)
+ .mockStatic(LockGuard.class)
+ .mockStatic(Watchdog.class)
+ .strictness(Strictness.LENIENT)
+ .startMocking();
+
+ setUpSystemCore();
+ setUpLocalServices();
+ setUpActivityTaskManagerService();
+ setUpWindowManagerService();
+ } finally {
+ mMockTracker.stopTracking();
+ }
+ }
+
+ private void setUpSystemCore() {
+ mHandlerThread = new ServiceThread(
+ "WmTestsThread", THREAD_PRIORITY_DEFAULT, true /* allowIo */);
+ mHandlerThread.start();
doReturn(mock(Watchdog.class)).when(Watchdog::getInstance);
- final Context context = getInstrumentation().getTargetContext();
- spyOn(context);
+ mContext = getInstrumentation().getTargetContext();
+ spyOn(mContext);
- doReturn(null).when(context)
+ doReturn(null).when(mContext)
.registerReceiver(nullable(BroadcastReceiver.class), any(IntentFilter.class));
- doReturn(null).when(context)
+ doReturn(null).when(mContext)
.registerReceiverAsUser(any(BroadcastReceiver.class), any(UserHandle.class),
any(IntentFilter.class), nullable(String.class), nullable(Handler.class));
- final ContentResolver contentResolver = context.getContentResolver();
+ final ContentResolver contentResolver = mContext.getContentResolver();
spyOn(contentResolver);
doNothing().when(contentResolver)
.registerContentObserver(any(Uri.class), anyBoolean(), any(ContentObserver.class),
anyInt());
+ }
- final AppOpsManager appOpsManager = mock(AppOpsManager.class);
- doReturn(appOpsManager).when(context)
- .getSystemService(eq(Context.APP_OPS_SERVICE));
+ private void setUpLocalServices() {
+ // Tear down any local services just in case.
+ tearDownLocalServices();
+ // UriGrantsManagerInternal
+ final UriGrantsManagerInternal ugmi = mock(UriGrantsManagerInternal.class);
+ LocalServices.addService(UriGrantsManagerInternal.class, ugmi);
+
+ // AppOpsManager
+ final AppOpsManager aom = mock(AppOpsManager.class);
+ doReturn(aom).when(mContext).getSystemService(eq(Context.APP_OPS_SERVICE));
+
+ // DisplayManagerInternal
final DisplayManagerInternal dmi = mock(DisplayManagerInternal.class);
doReturn(dmi).when(() -> LocalServices.getService(eq(DisplayManagerInternal.class)));
+ // ColorDisplayServiceInternal
+ final ColorDisplayService.ColorDisplayServiceInternal cds =
+ mock(ColorDisplayService.ColorDisplayServiceInternal.class);
+ doReturn(cds).when(() -> LocalServices.getService(
+ eq(ColorDisplayService.ColorDisplayServiceInternal.class)));
+
+ final UsageStatsManagerInternal usmi = mock(UsageStatsManagerInternal.class);
+ LocalServices.addService(UsageStatsManagerInternal.class, usmi);
+
+ // PackageManagerInternal
+ final PackageManagerInternal packageManagerInternal = mock(PackageManagerInternal.class);
+ LocalServices.addService(PackageManagerInternal.class, packageManagerInternal);
+ doReturn(false).when(packageManagerInternal).isPermissionsReviewRequired(
+ anyString(), anyInt());
+ doReturn(null).when(packageManagerInternal).getDefaultHomeActivity(anyInt());
+
+ // PowerManagerInternal
final PowerManagerInternal pmi = mock(PowerManagerInternal.class);
final PowerSaveState state = new PowerSaveState.Builder().build();
doReturn(state).when(pmi).getLowPowerState(anyInt());
doReturn(pmi).when(() -> LocalServices.getService(eq(PowerManagerInternal.class)));
- final ActivityManagerInternal ami = mock(ActivityManagerInternal.class);
- doReturn(ami).when(() -> LocalServices.getService(eq(ActivityManagerInternal.class)));
+ // PermissionPolicyInternal
+ final PermissionPolicyInternal ppi = mock(PermissionPolicyInternal.class);
+ LocalServices.addService(PermissionPolicyInternal.class, ppi);
+ doReturn(true).when(ppi).checkStartActivity(any(), anyInt(), any());
- final ActivityTaskManagerInternal atmi = mock(ActivityTaskManagerInternal.class);
- doAnswer((InvocationOnMock invocationOnMock) -> {
- final Runnable runnable = invocationOnMock.getArgument(0);
- if (runnable != null) {
- runnable.run();
- }
- return null;
- }).when(atmi).notifyKeyguardFlagsChanged(nullable(Runnable.class), anyInt());
- doReturn(atmi).when(() -> LocalServices.getService(eq(ActivityTaskManagerInternal.class)));
-
- final InputManagerService ims = mock(InputManagerService.class);
+ // InputManagerService
+ mImService = mock(InputManagerService.class);
// InputChannel is final and can't be mocked.
final InputChannel[] input = InputChannel.openInputChannelPair(TAG_WM);
if (input != null && input.length > 1) {
- doReturn(input[1]).when(ims).monitorInput(anyString(), anyInt());
+ doReturn(input[1]).when(mImService).monitorInput(anyString(), anyInt());
}
- final ActivityTaskManagerService atms = mock(ActivityTaskManagerService.class);
- final TaskChangeNotificationController taskChangeNotificationController = mock(
- TaskChangeNotificationController.class);
- doReturn(taskChangeNotificationController).when(atms).getTaskChangeNotificationController();
- final WindowManagerGlobalLock wmLock = new WindowManagerGlobalLock();
- doReturn(wmLock).when(atms).getGlobalLock();
+ // StatusBarManagerInternal
+ final StatusBarManagerInternal sbmi = mock(StatusBarManagerInternal.class);
+ doReturn(sbmi).when(() -> LocalServices.getService(eq(StatusBarManagerInternal.class)));
+ }
- mWindowManagerPolicy = new TestWindowManagerPolicy(this::getWindowManagerService);
- mWindowManagerService = WindowManagerService.main(
- context, ims, false, false, mWindowManagerPolicy, atms, StubTransaction::new);
+ private void setUpActivityTaskManagerService() {
+ // ActivityManagerService
+ mAmService = new ActivityManagerService(
+ new AMTestInjector(mContext, mHandlerThread), mHandlerThread);
+ spyOn(mAmService);
+ doReturn(mock(IPackageManager.class)).when(mAmService).getPackageManager();
+ doNothing().when(mAmService).grantEphemeralAccessLocked(
+ anyInt(), any(), anyInt(), anyInt());
- mWindowManagerService.onInitReady();
+ // ActivityManagerInternal
+ final ActivityManagerInternal amInternal = mAmService.mInternal;
+ spyOn(amInternal);
+ doNothing().when(amInternal).trimApplications();
+ doNothing().when(amInternal).updateCpuStats();
+ doNothing().when(amInternal).updateOomAdj();
+ doNothing().when(amInternal).updateBatteryStats(any(), anyInt(), anyInt(), anyBoolean());
+ doNothing().when(amInternal).updateActivityUsageStats(
+ any(), anyInt(), anyInt(), any(), any());
+ doNothing().when(amInternal).startProcess(
+ any(), any(), anyBoolean(), anyBoolean(), any(), any());
+ doNothing().when(amInternal).updateOomLevelsForDisplay(anyInt());
+ LocalServices.addService(ActivityManagerInternal.class, amInternal);
- final Display display = mWindowManagerService.mDisplayManager.getDisplay(DEFAULT_DISPLAY);
- // Display creation is driven by the ActivityManagerService via
- // ActivityStackSupervisor. We emulate those steps here.
- DisplayContent displayContent = mWindowManagerService.mRoot
- .createDisplayContent(display, mock(ActivityDisplay.class));
- displayContent.reconfigureDisplayLocked();
+ mAtmService = new TestActivityTaskManagerService(mContext, mAmService);
+ LocalServices.addService(ActivityTaskManagerInternal.class, mAtmService.getAtmInternal());
+ }
- mMockTracker.stopTracking();
+ private void setUpWindowManagerService() {
+ mWMPolicy = new TestWindowManagerPolicy(this::getWindowManagerService);
+ mWmService = WindowManagerService.main(
+ mContext, mImService, false, false, mWMPolicy, mAtmService, StubTransaction::new);
+ spyOn(mWmService);
+
+ // Setup factory classes to prevent calls to native code.
+ mTransaction = spy(StubTransaction.class);
+ // Return a spied Transaction class than can be used to verify calls.
+ mWmService.mTransactionFactory = () -> mTransaction;
+ // Return a SurfaceControl.Builder class that creates mocked SurfaceControl instances.
+ mWmService.mSurfaceBuilderFactory = (unused) -> new MockSurfaceControlBuilder();
+ // Return mocked Surface instances.
+ mWmService.mSurfaceFactory = () -> mock(Surface.class);
+ mWmService.mSurfaceAnimationRunner = new SurfaceAnimationRunner(
+ null, null, mTransaction, mWmService.mPowerManagerInternal);
+
+ mWmService.onInitReady();
+ mAmService.setWindowManager(mWmService);
+ mWmService.mDisplayEnabled = true;
+ mWmService.mDisplayReady = true;
+ // Set configuration for default display
+ mWmService.getDefaultDisplayContentLocked().reconfigureDisplayLocked();
+
+ // Mock root, some default display, and home stack.
+ spyOn(mWmService.mRoot);
+ final ActivityDisplay display = mAtmService.mRootActivityContainer.getDefaultDisplay();
+ spyOn(display);
+ spyOn(display.mDisplayContent);
+ final ActivityStack homeStack = display.getStack(
+ WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME);
+ spyOn(homeStack);
+ spyOn(homeStack.mTaskStack);
}
private void tearDown() {
waitUntilWindowManagerHandlersIdle();
- removeLocalServices();
- mWindowManagerService = null;
- mWindowManagerPolicy = null;
+ // Unregister display listener from root to avoid issues with subsequent tests.
+ mContext.getSystemService(DisplayManager.class)
+ .unregisterDisplayListener(mAtmService.mRootActivityContainer);
+ // ProptertiesChangesListener is registered in the constructor of WindowManagerService to
+ // a static object, so we need to clean it up in tearDown(), even though we didn't set up
+ // in tests.
+ DeviceConfig.removeOnPropertiesChangedListener(mWmService.mPropertiesChangedListener);
+ mWmService = null;
+ mWMPolicy = null;
+
+ tearDownLocalServices();
+ tearDownSystemCore();
+ }
+
+ private void tearDownSystemCore() {
if (mMockitoSession != null) {
mMockitoSession.finishMocking();
mMockitoSession = null;
@@ -198,15 +320,36 @@
mMockTracker.close();
mMockTracker = null;
}
+
+ if (mHandlerThread != null) {
+ // Make sure there are no running messages and then quit the thread so the next test
+ // won't be affected.
+ mHandlerThread.getThreadHandler().runWithScissors(mHandlerThread::quit,
+ 0 /* timeout */);
+ }
}
- private static void removeLocalServices() {
+ private static void tearDownLocalServices() {
+ LocalServices.removeServiceForTest(DisplayManagerInternal.class);
+ LocalServices.removeServiceForTest(PowerManagerInternal.class);
+ LocalServices.removeServiceForTest(ActivityManagerInternal.class);
+ LocalServices.removeServiceForTest(ActivityTaskManagerInternal.class);
LocalServices.removeServiceForTest(WindowManagerInternal.class);
LocalServices.removeServiceForTest(WindowManagerPolicy.class);
+ LocalServices.removeServiceForTest(PackageManagerInternal.class);
+ LocalServices.removeServiceForTest(UriGrantsManagerInternal.class);
+ LocalServices.removeServiceForTest(PermissionPolicyInternal.class);
+ LocalServices.removeServiceForTest(ColorDisplayService.ColorDisplayServiceInternal.class);
+ LocalServices.removeServiceForTest(UsageStatsManagerInternal.class);
+ LocalServices.removeServiceForTest(StatusBarManagerInternal.class);
}
WindowManagerService getWindowManagerService() {
- return mWindowManagerService;
+ return mWmService;
+ }
+
+ ActivityTaskManagerService getActivityTaskManagerService() {
+ return mAtmService;
}
void cleanupWindowManagerHandlers() {
@@ -229,6 +372,7 @@
waitHandlerIdle(wm.mH);
waitHandlerIdle(wm.mAnimationHandler);
waitHandlerIdle(SurfaceAnimationThread.getHandler());
+ waitHandlerIdle(mHandlerThread.getThreadHandler());
}
private void waitHandlerIdle(Handler handler) {
@@ -251,4 +395,121 @@
}
}
}
+
+ protected class TestActivityTaskManagerService extends ActivityTaskManagerService {
+ // ActivityStackSupervisor may be created more than once while setting up AMS and ATMS.
+ // We keep the reference in order to prevent creating it twice.
+ ActivityStackSupervisor mTestStackSupervisor;
+
+ TestActivityTaskManagerService(Context context, ActivityManagerService ams) {
+ super(context);
+ spyOn(this);
+
+ mSupportsMultiWindow = true;
+ mSupportsMultiDisplay = true;
+ mSupportsSplitScreenMultiWindow = true;
+ mSupportsFreeformWindowManagement = true;
+ mSupportsPictureInPicture = true;
+
+ doReturn(mock(IPackageManager.class)).when(this).getPackageManager();
+ // allow background activity starts by default
+ doReturn(true).when(this).isBackgroundActivityStartsEnabled();
+ doNothing().when(this).updateCpuStats();
+
+ // AppOpsService
+ final AppOpsService aos = mock(AppOpsService.class);
+ doReturn(aos).when(this).getAppOpsService();
+ // Make sure permission checks aren't overridden.
+ doReturn(AppOpsManager.MODE_DEFAULT)
+ .when(aos).noteOperation(anyInt(), anyInt(), anyString());
+
+ setUsageStatsManager(LocalServices.getService(UsageStatsManagerInternal.class));
+ ams.mActivityTaskManager = this;
+ ams.mAtmInternal = mInternal;
+ onActivityManagerInternalAdded();
+ initialize(
+ ams.mIntentFirewall, ams.mPendingIntentController, mHandlerThread.getLooper());
+ spyOn(getLifecycleManager());
+ spyOn(getLockTaskController());
+ spyOn(getTaskChangeNotificationController());
+ initRootActivityContainerMocks();
+ }
+
+ void initRootActivityContainerMocks() {
+ spyOn(mRootActivityContainer);
+ // Invoked during {@link ActivityStack} creation.
+ doNothing().when(mRootActivityContainer).updateUIDsPresentOnDisplay();
+ // Always keep things awake.
+ doReturn(true).when(mRootActivityContainer).hasAwakeDisplay();
+ // Called when moving activity to pinned stack.
+ doNothing().when(mRootActivityContainer).ensureActivitiesVisible(any(), anyInt(),
+ anyBoolean());
+ }
+
+ @Override
+ int handleIncomingUser(int callingPid, int callingUid, int userId, String name) {
+ return userId;
+ }
+
+ @Override
+ protected ActivityStackSupervisor createStackSupervisor() {
+ if (mTestStackSupervisor == null) {
+ mTestStackSupervisor = new TestActivityStackSupervisor(this, mH.getLooper());
+ }
+ return mTestStackSupervisor;
+ }
+ }
+
+ /**
+ * An {@link ActivityStackSupervisor} which stubs out certain methods that depend on
+ * setup not available in the test environment. Also specifies an injector for
+ */
+ protected class TestActivityStackSupervisor extends ActivityStackSupervisor {
+
+ TestActivityStackSupervisor(ActivityTaskManagerService service, Looper looper) {
+ super(service, looper);
+ spyOn(this);
+
+ // Do not schedule idle that may touch methods outside the scope of the test.
+ doNothing().when(this).scheduleIdleLocked();
+ doNothing().when(this).scheduleIdleTimeoutLocked(any());
+ // unit test version does not handle launch wake lock
+ doNothing().when(this).acquireLaunchWakelock();
+ doReturn(mock(KeyguardController.class)).when(this).getKeyguardController();
+
+ mLaunchingActivityWakeLock = mock(PowerManager.WakeLock.class);
+
+ initialize();
+ }
+ }
+
+ // TODO: Can we just mock this?
+ private static class AMTestInjector extends ActivityManagerService.Injector {
+ private ServiceThread mHandlerThread;
+
+ AMTestInjector(Context context, ServiceThread handlerThread) {
+ super(context);
+ mHandlerThread = handlerThread;
+ }
+
+ @Override
+ public Context getContext() {
+ return getInstrumentation().getTargetContext();
+ }
+
+ @Override
+ public AppOpsService getAppOpsService(File file, Handler handler) {
+ return null;
+ }
+
+ @Override
+ public Handler getUiHandler(ActivityManagerService service) {
+ return mHandlerThread.getThreadHandler();
+ }
+
+ @Override
+ public boolean isNetworkRestrictedForUid(int uid) {
+ return false;
+ }
+ }
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java
index 2cebebf..bcff704 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java
@@ -1277,17 +1277,18 @@
}
private ActivityRecord createSourceActivity(TestActivityDisplay display) {
- final TestActivityStack stack = display.createStack(display.getWindowingMode(),
+ final ActivityStack stack = display.createStack(display.getWindowingMode(),
ACTIVITY_TYPE_STANDARD, true);
return new ActivityBuilder(mService).setStack(stack).setCreateTask(true).build();
}
private void addFreeformTaskTo(TestActivityDisplay display, Rect bounds) {
- final TestActivityStack stack = display.createStack(display.getWindowingMode(),
+ final ActivityStack stack = display.createStack(display.getWindowingMode(),
ACTIVITY_TYPE_STANDARD, true);
stack.setWindowingMode(WINDOWING_MODE_FREEFORM);
final TaskRecord task = new TaskBuilder(mSupervisor).setStack(stack).build();
- task.setBounds(bounds);
+ // Just work around the unnecessary adjustments for bounds.
+ task.getWindowConfiguration().setBounds(bounds);
}
private void assertEquivalentWindowingMode(int expected, int actual, int parentWindowingMode) {
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java
index a0302f6..c83401b 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java
@@ -28,14 +28,19 @@
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
import static android.util.DisplayMetrics.DENSITY_DEFAULT;
import static android.view.Surface.ROTATION_0;
+import static android.view.Surface.ROTATION_90;
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.eq;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
+import static com.android.server.policy.WindowManagerPolicy.USER_ROTATION_FREE;
+import static com.android.server.wm.DisplayRotation.FIXED_TO_USER_ROTATION_ENABLED;
import static com.android.server.wm.WindowContainer.POSITION_TOP;
+import static com.google.common.truth.Truth.assertThat;
+
import static org.hamcrest.Matchers.not;
import static org.hamcrest.Matchers.sameInstance;
import static org.junit.Assert.assertEquals;
@@ -64,6 +69,7 @@
import android.util.Xml;
import android.view.DisplayInfo;
+import androidx.test.filters.FlakyTest;
import androidx.test.filters.MediumTest;
import com.android.internal.app.IVoiceInteractor;
@@ -102,6 +108,7 @@
public void setUp() throws Exception {
TaskRecord.setTaskRecordFactory(null);
mParentBounds = new Rect(10 /*left*/, 30 /*top*/, 80 /*right*/, 60 /*bottom*/);
+ removeGlobalMinSizeRestriction();
}
@Test
@@ -165,6 +172,7 @@
/** Ensures that bounds on freeform stacks are not clipped. */
@Test
+ @FlakyTest(bugId = 137879065)
public void testAppBounds_FreeFormBounds() {
final Rect freeFormBounds = new Rect(mParentBounds);
freeFormBounds.offset(10, 10);
@@ -174,6 +182,7 @@
/** Ensures that fully contained bounds are not clipped. */
@Test
+ @FlakyTest(bugId = 137879065)
public void testAppBounds_ContainedBounds() {
final Rect insetBounds = new Rect(mParentBounds);
insetBounds.inset(5, 5, 5, 5);
@@ -182,6 +191,7 @@
}
@Test
+ @FlakyTest(bugId = 137879065)
public void testFitWithinBounds() {
final Rect parentBounds = new Rect(10, 10, 200, 200);
ActivityDisplay display = mService.mRootActivityContainer.getDefaultDisplay();
@@ -221,6 +231,7 @@
/** Tests that the task bounds adjust properly to changes between FULLSCREEN and FREEFORM */
@Test
+ @FlakyTest(bugId = 137879065)
public void testBoundsOnModeChangeFreeformToFullscreen() {
ActivityDisplay display = mService.mRootActivityContainer.getDefaultDisplay();
ActivityStack stack = new StackBuilder(mRootActivityContainer).setDisplay(display)
@@ -248,18 +259,6 @@
}
/**
- * This is a temporary hack to trigger an onConfigurationChange at the task level after an
- * orientation is requested. Normally this is done by the onDescendentOrientationChanged call
- * up the WM hierarchy, but since the WM hierarchy is mocked out, it doesn't happen here.
- * TODO: remove this when we either get a WM hierarchy or when hierarchies are merged.
- */
- private void setActivityRequestedOrientation(ActivityRecord activity, int orientation) {
- activity.setRequestedOrientation(orientation);
- ConfigurationContainer taskRecord = activity.getParent();
- taskRecord.onConfigurationChanged(taskRecord.getParent().getConfiguration());
- }
-
- /**
* Tests that a task with forced orientation has orientation-consistent bounds within the
* parent.
*/
@@ -268,49 +267,48 @@
final Rect fullScreenBounds = new Rect(0, 0, 1920, 1080);
final Rect fullScreenBoundsPort = new Rect(0, 0, 1080, 1920);
DisplayInfo info = new DisplayInfo();
+ mService.mContext.getDisplay().getDisplayInfo(info);
info.logicalWidth = fullScreenBounds.width();
info.logicalHeight = fullScreenBounds.height();
ActivityDisplay display = addNewActivityDisplayAt(info, POSITION_TOP);
assertTrue(mRootActivityContainer.getActivityDisplay(display.mDisplayId) != null);
- // Override display orientation. Normally this is available via DisplayContent, but DC
- // is mocked-out.
- display.getRequestedOverrideConfiguration().orientation =
- Configuration.ORIENTATION_LANDSCAPE;
- display.onRequestedOverrideConfigurationChanged(
- display.getRequestedOverrideConfiguration());
+ // Fix the display orientation to landscape which is the natural rotation (0) for the test
+ // display.
+ final DisplayRotation dr = display.mDisplayContent.getDisplayRotation();
+ dr.setFixedToUserRotation(FIXED_TO_USER_ROTATION_ENABLED);
+ dr.setUserRotation(USER_ROTATION_FREE, ROTATION_0);
+
ActivityStack stack = new StackBuilder(mRootActivityContainer)
.setWindowingMode(WINDOWING_MODE_FULLSCREEN).setDisplay(display).build();
TaskRecord task = stack.getChildAt(0);
ActivityRecord root = task.getTopActivity();
- assertEquals(root, task.getTopActivity());
assertEquals(fullScreenBounds, task.getBounds());
// Setting app to fixed portrait fits within parent
- setActivityRequestedOrientation(root, SCREEN_ORIENTATION_PORTRAIT);
+ root.setRequestedOrientation(SCREEN_ORIENTATION_PORTRAIT);
assertEquals(root, task.getRootActivity());
assertEquals(SCREEN_ORIENTATION_PORTRAIT, task.getRootActivity().getOrientation());
- assertTrue(task.getBounds().width() < task.getBounds().height());
+ assertThat(task.getBounds().width()).isLessThan(task.getBounds().height());
assertEquals(fullScreenBounds.height(), task.getBounds().height());
// Top activity gets used
ActivityRecord top = new ActivityBuilder(mService).setTask(task).setStack(stack).build();
assertEquals(top, task.getTopActivity());
- setActivityRequestedOrientation(top, SCREEN_ORIENTATION_LANDSCAPE);
- assertTrue(task.getBounds().width() > task.getBounds().height());
+ top.setRequestedOrientation(SCREEN_ORIENTATION_LANDSCAPE);
+ assertThat(task.getBounds().width()).isGreaterThan(task.getBounds().height());
assertEquals(task.getBounds().width(), fullScreenBounds.width());
// Setting app to unspecified restores
- setActivityRequestedOrientation(top, SCREEN_ORIENTATION_UNSPECIFIED);
+ top.setRequestedOrientation(SCREEN_ORIENTATION_UNSPECIFIED);
assertEquals(fullScreenBounds, task.getBounds());
// Setting app to fixed landscape and changing display
- setActivityRequestedOrientation(top, SCREEN_ORIENTATION_LANDSCAPE);
- // simulate display orientation changing (normally done via DisplayContent)
- display.getRequestedOverrideConfiguration().orientation =
- Configuration.ORIENTATION_PORTRAIT;
- display.setBounds(fullScreenBoundsPort);
- assertTrue(task.getBounds().width() > task.getBounds().height());
+ top.setRequestedOrientation(SCREEN_ORIENTATION_LANDSCAPE);
+ // Fix the display orientation to portrait which is 90 degrees for the test display.
+ dr.setUserRotation(USER_ROTATION_FREE, ROTATION_90);
+
+ assertThat(task.getBounds().width()).isGreaterThan(task.getBounds().height());
assertEquals(fullScreenBoundsPort.width(), task.getBounds().width());
// in FREEFORM, no constraint
@@ -323,7 +321,7 @@
// FULLSCREEN letterboxes bounds
stack.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
- assertTrue(task.getBounds().width() > task.getBounds().height());
+ assertThat(task.getBounds().width()).isGreaterThan(task.getBounds().height());
assertEquals(fullScreenBoundsPort.width(), task.getBounds().width());
// FREEFORM restores bounds as before
@@ -335,6 +333,7 @@
public void testIgnoresForcedOrientationWhenParentHandles() {
final Rect fullScreenBounds = new Rect(0, 0, 1920, 1080);
DisplayInfo info = new DisplayInfo();
+ mService.mContext.getDisplay().getDisplayInfo(info);
info.logicalWidth = fullScreenBounds.width();
info.logicalHeight = fullScreenBounds.height();
ActivityDisplay display = addNewActivityDisplayAt(info, POSITION_TOP);
@@ -355,7 +354,7 @@
// Setting app to fixed portrait fits within parent, but TaskRecord shouldn't adjust the
// bounds because its parent says it will handle it at a later time.
- setActivityRequestedOrientation(root, SCREEN_ORIENTATION_PORTRAIT);
+ root.setRequestedOrientation(SCREEN_ORIENTATION_PORTRAIT);
assertEquals(root, task.getRootActivity());
assertEquals(SCREEN_ORIENTATION_PORTRAIT, task.getRootActivity().getOrientation());
assertEquals(fullScreenBounds, task.getBounds());
@@ -646,7 +645,7 @@
final ActivityRecord activity0 = task0.getChildAt(0);
final TaskRecord task1 = getTestTask();
- final ActivityRecord activity1 = task0.getChildAt(0);
+ final ActivityRecord activity1 = task1.getChildAt(0);
assertEquals(task0.taskId,
ActivityRecord.getTaskForActivityLocked(activity0.appToken, false /* onlyRoot */));
diff --git a/services/tests/wmtests/src/com/android/server/wm/TestActivityDisplay.java b/services/tests/wmtests/src/com/android/server/wm/TestActivityDisplay.java
new file mode 100644
index 0000000..c143969
--- /dev/null
+++ b/services/tests/wmtests/src/com/android/server/wm/TestActivityDisplay.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wm;
+
+import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+import static android.view.Display.DEFAULT_DISPLAY;
+import static android.view.DisplayAdjustments.DEFAULT_DISPLAY_ADJUSTMENTS;
+
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.anyBoolean;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.doAnswer;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
+
+import android.hardware.display.DisplayManagerGlobal;
+import android.view.Display;
+import android.view.DisplayInfo;
+
+class TestActivityDisplay extends ActivityDisplay {
+ private final ActivityStackSupervisor mSupervisor;
+
+ static TestActivityDisplay create(ActivityStackSupervisor supervisor) {
+ return create(supervisor, SystemServicesTestRule.sNextDisplayId++);
+ }
+
+ static TestActivityDisplay create(ActivityStackSupervisor supervisor, DisplayInfo info) {
+ return create(supervisor, SystemServicesTestRule.sNextDisplayId++, info);
+ }
+
+ static TestActivityDisplay create(ActivityStackSupervisor supervisor, int displayId) {
+ final DisplayInfo info = new DisplayInfo();
+ supervisor.mService.mContext.getDisplay().getDisplayInfo(info);
+ return create(supervisor, displayId, info);
+ }
+
+ static TestActivityDisplay create(ActivityStackSupervisor supervisor, int displayId,
+ DisplayInfo info) {
+ if (displayId == DEFAULT_DISPLAY) {
+ synchronized (supervisor.mService.mGlobalLock) {
+ return new TestActivityDisplay(supervisor,
+ supervisor.mRootActivityContainer.mDisplayManager.getDisplay(displayId));
+ }
+ }
+ final Display display = new Display(DisplayManagerGlobal.getInstance(), displayId,
+ info, DEFAULT_DISPLAY_ADJUSTMENTS);
+
+ synchronized (supervisor.mService.mGlobalLock) {
+ return new TestActivityDisplay(supervisor, display);
+ }
+ }
+
+ private TestActivityDisplay(ActivityStackSupervisor supervisor, Display display) {
+ super(supervisor.mService.mRootActivityContainer, display);
+ // Normally this comes from display-properties as exposed by WM. Without that, just
+ // hard-code to FULLSCREEN for tests.
+ setWindowingMode(WINDOWING_MODE_FULLSCREEN);
+ mSupervisor = supervisor;
+ spyOn(this);
+ spyOn(mDisplayContent);
+ doAnswer(invocation -> {
+ // Bypass all the rotation animation and display freezing stuff for testing and just
+ // set the rotation we want for the display
+ final DisplayContent dc = mDisplayContent;
+ final int oldRotation = dc.getRotation();
+ final int rotation = dc.getDisplayRotation().rotationForOrientation(
+ dc.getLastOrientation(), oldRotation);
+ if (oldRotation == rotation) {
+ return false;
+ }
+ dc.setLayoutNeeded();
+ dc.setRotation(rotation);
+ return true;
+ }).when(mDisplayContent).updateRotationUnchecked(anyBoolean());
+ }
+
+ @SuppressWarnings("TypeParameterUnusedInFormals")
+ @Override
+ ActivityStack createStackUnchecked(int windowingMode, int activityType,
+ int stackId, boolean onTop) {
+ return new ActivityTestsBase.StackBuilder(mSupervisor.mRootActivityContainer)
+ .setDisplay(this)
+ .setWindowingMode(windowingMode)
+ .setActivityType(activityType)
+ .setStackId(stackId)
+ .setOnTop(onTop)
+ .setCreateActivity(false)
+ .build();
+ }
+}
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java
index acfc2ea..921f105 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java
@@ -27,6 +27,7 @@
import static com.android.dx.mockito.inline.extended.ExtendedMockito.eq;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.never;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.reset;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spy;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.times;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
@@ -113,6 +114,7 @@
@Test
public void testAddChildSetsSurfacePosition() {
+ reset(mTransaction);
try (MockSurfaceBuildingContainer top = new MockSurfaceBuildingContainer(mWm)) {
WindowContainer child = new WindowContainer(mWm);
child.setBounds(1, 1, 10, 10);
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowFrameTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowFrameTests.java
index 06bcdf8..60cefe8 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowFrameTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowFrameTests.java
@@ -57,6 +57,7 @@
private final IWindow mIWindow = new TestIWindow();
private final Rect mEmptyRect = new Rect();
+ private DisplayContent mTestDisplayContent;
static class FrameTestWindowState extends WindowState {
boolean mDockedResizingForTest = false;
@@ -77,6 +78,9 @@
@Before
public void setUp() throws Exception {
mStubStack = mock(TaskStack.class);
+ DisplayInfo testDisplayInfo = new DisplayInfo(mDisplayInfo);
+ testDisplayInfo.displayCutout = null;
+ mTestDisplayContent = createNewDisplay(testDisplayInfo);
}
// Do not use this function directly in the tests below. Instead, use more explicit function
@@ -100,6 +104,10 @@
assertRect(w.getStableInsets(), left, top, right, bottom);
}
+ private void assertFrame(WindowState w, Rect frame) {
+ assertEquals(w.getFrameLw(), frame);
+ }
+
private void assertFrame(WindowState w, int left, int top, int right, int bottom) {
assertRect(w.getFrameLw(), left, top, right, bottom);
}
@@ -380,9 +388,10 @@
}
@Test
+ @FlakyTest(bugId = 137879065)
public void testLayoutLetterboxedWindow() {
// First verify task behavior in multi-window mode.
- final DisplayInfo displayInfo = mWm.getDefaultDisplayContentLocked().getDisplayInfo();
+ final DisplayInfo displayInfo = mTestDisplayContent.getDisplayInfo();
final int logicalWidth = displayInfo.logicalWidth;
final int logicalHeight = displayInfo.logicalHeight;
@@ -413,13 +422,14 @@
final Rect cf = new Rect(xInset, 0, logicalWidth - xInset, logicalHeight);
Configuration config = new Configuration(w.mAppToken.getRequestedOverrideConfiguration());
config.windowConfiguration.setBounds(cf);
+ config.windowConfiguration.setAppBounds(cf);
w.mAppToken.onRequestedOverrideConfigurationChanged(config);
pf.set(0, 0, logicalWidth, logicalHeight);
task.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
task.setBounds(null);
windowFrames.setFrames(pf, pf, pf, cf, cf, pf, cf, mEmptyRect);
w.computeFrameLw();
- assertFrame(w, cf.left, cf.top, cf.right, cf.bottom);
+ assertFrame(w, cf);
assertContentFrame(w, cf);
assertContentInset(w, 0, 0, 0, 0);
}
@@ -483,7 +493,7 @@
w.mAttrs.gravity = Gravity.LEFT | Gravity.TOP;
task.setWindowingMode(WINDOWING_MODE_FREEFORM);
- DisplayContent dc = mWm.getDefaultDisplayContentLocked();
+ DisplayContent dc = mTestDisplayContent;
dc.mInputMethodTarget = w;
WindowState mockIme = mock(WindowState.class);
Mockito.doReturn(true).when(mockIme).isVisibleNow();
@@ -537,7 +547,7 @@
attrs.width = width;
attrs.height = height;
- AppWindowToken token = createAppWindowToken(mWm.getDefaultDisplayContentLocked(),
+ AppWindowToken token = createAppWindowToken(mTestDisplayContent,
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
FrameTestWindowState ws = new FrameTestWindowState(mWm, mIWindow, token, attrs);
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
index 36698ea..763d086 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
@@ -517,13 +517,19 @@
@Test
public void testGetTransformationMatrix() {
+ final int PARENT_WINDOW_OFFSET = 1;
+ final int DISPLAY_IN_PARENT_WINDOW_OFFSET = 2;
+ final int WINDOW_OFFSET = 3;
+ final float OFFSET_SUM =
+ PARENT_WINDOW_OFFSET + DISPLAY_IN_PARENT_WINDOW_OFFSET + WINDOW_OFFSET;
+
synchronized (mWm.mGlobalLock) {
final WindowState win0 = createWindow(null, TYPE_APPLICATION, "win0");
- win0.getFrameLw().offsetTo(1, 0);
final DisplayContent dc = createNewDisplay();
+ win0.getFrameLw().offsetTo(PARENT_WINDOW_OFFSET, 0);
dc.reparentDisplayContent(win0, win0.getSurfaceControl());
- dc.updateLocation(win0, 2, 0);
+ dc.updateLocation(win0, DISPLAY_IN_PARENT_WINDOW_OFFSET, 0);
final float[] values = new float[9];
final Matrix matrix = new Matrix();
@@ -531,12 +537,12 @@
final WindowState win1 = createWindow(null, TYPE_APPLICATION, dc, "win1");
win1.mHasSurface = true;
win1.mSurfaceControl = mock(SurfaceControl.class);
- win1.getFrameLw().offsetTo(3, 0);
+ win1.getFrameLw().offsetTo(WINDOW_OFFSET, 0);
win1.updateSurfacePosition(t);
win1.getTransformationMatrix(values, matrix);
matrix.getValues(values);
- assertEquals(6f, values[Matrix.MTRANS_X], 0f);
+ assertEquals(OFFSET_SUM, values[Matrix.MTRANS_X], 0f);
assertEquals(0f, values[Matrix.MTRANS_Y], 0f);
}
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
index dc461d1..0732066 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
@@ -20,8 +20,6 @@
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.os.Process.SYSTEM_UID;
-import static android.view.Display.DEFAULT_DISPLAY;
-import static android.view.DisplayAdjustments.DEFAULT_DISPLAY_ADJUSTMENTS;
import static android.view.View.VISIBLE;
import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW;
import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
@@ -38,20 +36,18 @@
import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
-import static com.android.dx.mockito.inline.extended.ExtendedMockito.spy;
+import static com.android.server.wm.ActivityDisplay.POSITION_TOP;
import static org.mockito.Mockito.mock;
import android.content.Context;
import android.content.res.Configuration;
-import android.hardware.display.DisplayManagerGlobal;
import android.testing.DexmakerShareClassLoaderRule;
import android.util.Log;
import android.view.Display;
import android.view.DisplayInfo;
import android.view.IWindow;
-import android.view.Surface;
import android.view.SurfaceControl.Transaction;
import android.view.WindowManager;
@@ -79,10 +75,6 @@
WindowManagerService mWm;
private final IWindow mIWindow = new TestIWindow();
private Session mMockSession;
- // The default display is removed in {@link #setUp} and then we iterate over all displays to
- // make sure we don't collide with any existing display. If we run into no other display, the
- // added display should be treated as default. This cannot be the default display
- private static int sNextDisplayId = DEFAULT_DISPLAY + 1;
static int sNextStackId = 1000;
/** Non-default display. */
@@ -134,27 +126,16 @@
// in the set up are clear. This can be removed when b/37850063 is fixed.
try {
mMockSession = mock(Session.class);
- mTransaction = spy(StubTransaction.class);
final Context context = getInstrumentation().getTargetContext();
mWm = mSystemServicesTestRule.getWindowManagerService();
-
- // Setup factory classes to prevent calls to native code.
-
- // Return a spied Transaction class than can be used to verify calls.
- mWm.mTransactionFactory = () -> mTransaction;
- // Return a SurfaceControl.Builder class that creates mocked SurfaceControl instances.
- mWm.mSurfaceBuilderFactory = (unused) -> new MockSurfaceControlBuilder();
- // Return mocked Surface instances.
- mWm.mSurfaceFactory = () -> mock(Surface.class);
+ mTransaction = mSystemServicesTestRule.mTransaction;
beforeCreateDisplay();
context.getDisplay().getDisplayInfo(mDisplayInfo);
mDisplayContent = createNewDisplay();
- mWm.mDisplayEnabled = true;
- mWm.mDisplayReady = true;
// Set-up some common windows.
mCommonWindows = new HashSet<>();
@@ -211,12 +192,6 @@
nonCommonWindows.pollLast().removeImmediately();
}
- for (int i = mWm.mRoot.mChildren.size() - 1; i >= 0; --i) {
- final DisplayContent displayContent = mWm.mRoot.mChildren.get(i);
- if (!displayContent.isDefaultDisplay) {
- displayContent.removeImmediately();
- }
- }
// Remove app transition & window freeze timeout callbacks to prevent unnecessary
// actions after test.
mWm.getDefaultDisplayContentLocked().mAppTransition
@@ -408,13 +383,11 @@
}
/** Creates a {@link DisplayContent} and adds it to the system. */
- DisplayContent createNewDisplay(DisplayInfo displayInfo) {
- final int displayId = sNextDisplayId++;
- final Display display = new Display(DisplayManagerGlobal.getInstance(), displayId,
- displayInfo, DEFAULT_DISPLAY_ADJUSTMENTS);
- synchronized (mWm.mGlobalLock) {
- return new DisplayContent(display, mWm, mock(ActivityDisplay.class));
- }
+ DisplayContent createNewDisplay(DisplayInfo info) {
+ final ActivityDisplay display =
+ TestActivityDisplay.create(mWm.mAtmService.mStackSupervisor, info);
+ mWm.mAtmService.mRootActivityContainer.addChild(display, POSITION_TOP);
+ return display.mDisplayContent;
}
/**
@@ -428,17 +401,7 @@
DisplayInfo displayInfo = new DisplayInfo();
displayInfo.copyFrom(mDisplayInfo);
displayInfo.state = displayState;
- final int displayId = sNextDisplayId++;
- final Display display = new Display(DisplayManagerGlobal.getInstance(), displayId,
- displayInfo, DEFAULT_DISPLAY_ADJUSTMENTS);
- synchronized (mWm.mGlobalLock) {
- // Display creation is driven by DisplayWindowController via ActivityStackSupervisor.
- // We skip those steps here.
- final ActivityDisplay mockAd = mock(ActivityDisplay.class);
- final DisplayContent displayContent = mWm.mRoot.createDisplayContent(display, mockAd);
- displayContent.reconfigureDisplayLocked();
- return displayContent;
- }
+ return createNewDisplay(displayInfo);
}
/** Creates a {@link com.android.server.wm.WindowTestUtils.TestWindowState} */