diff options
34 files changed, 691 insertions, 558 deletions
diff --git a/api/test-current.txt b/api/test-current.txt index 2e6c40ac34aa..8647ed397c49 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -75,9 +75,11 @@ package android.app { method public int describeContents(); method public int getActivityType(); method public android.graphics.Rect getAppBounds(); + method public android.graphics.Rect getBounds(); method public int getWindowingMode(); method public void setActivityType(int); method public void setAppBounds(android.graphics.Rect); + method public void setBounds(android.graphics.Rect); method public void setTo(android.app.WindowConfiguration); method public void setWindowingMode(int); method public void writeToParcel(android.os.Parcel, int); diff --git a/core/java/android/app/WindowConfiguration.java b/core/java/android/app/WindowConfiguration.java index 2c1fad1cf140..80399ae65c58 100644 --- a/core/java/android/app/WindowConfiguration.java +++ b/core/java/android/app/WindowConfiguration.java @@ -40,6 +40,13 @@ import android.view.DisplayInfo; */ @TestApi public class WindowConfiguration implements Parcelable, Comparable<WindowConfiguration> { + /** + * bounds that can differ from app bounds, which may include things such as insets. + * + * TODO: Investigate combining with {@link mAppBounds}. Can the latter be a product of the + * former? + */ + private Rect mBounds = new Rect(); /** * {@link android.graphics.Rect} defining app bounds. The dimensions override usages of @@ -117,22 +124,26 @@ public class WindowConfiguration implements Parcelable, Comparable<WindowConfigu }) public @interface ActivityType {} + /** Bit that indicates that the {@link #mBounds} changed. + * @hide */ + public static final int WINDOW_CONFIG_BOUNDS = 1 << 0; /** Bit that indicates that the {@link #mAppBounds} changed. * @hide */ - public static final int WINDOW_CONFIG_APP_BOUNDS = 1 << 0; + public static final int WINDOW_CONFIG_APP_BOUNDS = 1 << 1; /** Bit that indicates that the {@link #mWindowingMode} changed. * @hide */ - public static final int WINDOW_CONFIG_WINDOWING_MODE = 1 << 1; + public static final int WINDOW_CONFIG_WINDOWING_MODE = 1 << 2; /** Bit that indicates that the {@link #mActivityType} changed. * @hide */ - public static final int WINDOW_CONFIG_ACTIVITY_TYPE = 1 << 2; + public static final int WINDOW_CONFIG_ACTIVITY_TYPE = 1 << 3; /** @hide */ @IntDef(flag = true, value = { + WINDOW_CONFIG_BOUNDS, WINDOW_CONFIG_APP_BOUNDS, WINDOW_CONFIG_WINDOWING_MODE, - WINDOW_CONFIG_ACTIVITY_TYPE, + WINDOW_CONFIG_ACTIVITY_TYPE }) public @interface WindowConfig {} @@ -151,12 +162,14 @@ public class WindowConfiguration implements Parcelable, Comparable<WindowConfigu @Override public void writeToParcel(Parcel dest, int flags) { + dest.writeParcelable(mBounds, flags); dest.writeParcelable(mAppBounds, flags); dest.writeInt(mWindowingMode); dest.writeInt(mActivityType); } private void readFromParcel(Parcel source) { + mBounds = source.readParcelable(Rect.class.getClassLoader()); mAppBounds = source.readParcelable(Rect.class.getClassLoader()); mWindowingMode = source.readInt(); mActivityType = source.readInt(); @@ -181,6 +194,19 @@ public class WindowConfiguration implements Parcelable, Comparable<WindowConfigu }; /** + * Sets the bounds to the provided {@link Rect}. + * @param rect the new bounds value. + */ + public void setBounds(Rect rect) { + if (rect == null) { + mBounds.setEmpty(); + return; + } + + mBounds.set(rect); + } + + /** * Set {@link #mAppBounds} to the input Rect. * @param rect The rect value to set {@link #mAppBounds} to. * @see #getAppBounds() @@ -212,6 +238,11 @@ public class WindowConfiguration implements Parcelable, Comparable<WindowConfigu return mAppBounds; } + /** @see #setBounds(Rect) */ + public Rect getBounds() { + return mBounds; + } + public void setWindowingMode(@WindowingMode int windowingMode) { mWindowingMode = windowingMode; } @@ -244,6 +275,7 @@ public class WindowConfiguration implements Parcelable, Comparable<WindowConfigu } public void setTo(WindowConfiguration other) { + setBounds(other.mBounds); setAppBounds(other.mAppBounds); setWindowingMode(other.mWindowingMode); setActivityType(other.mActivityType); @@ -258,6 +290,7 @@ public class WindowConfiguration implements Parcelable, Comparable<WindowConfigu /** @hide */ public void setToDefaults() { setAppBounds(null); + setBounds(null); setWindowingMode(WINDOWING_MODE_UNDEFINED); setActivityType(ACTIVITY_TYPE_UNDEFINED); } @@ -272,6 +305,11 @@ public class WindowConfiguration implements Parcelable, Comparable<WindowConfigu */ public @WindowConfig int updateFrom(@NonNull WindowConfiguration delta) { int changed = 0; + // Only allow override if bounds is not empty + if (!delta.mBounds.isEmpty() && !delta.mBounds.equals(mBounds)) { + changed |= WINDOW_CONFIG_BOUNDS; + setBounds(delta.mBounds); + } if (delta.mAppBounds != null && !delta.mAppBounds.equals(mAppBounds)) { changed |= WINDOW_CONFIG_APP_BOUNDS; setAppBounds(delta.mAppBounds); @@ -303,6 +341,10 @@ public class WindowConfiguration implements Parcelable, Comparable<WindowConfigu public @WindowConfig long diff(WindowConfiguration other, boolean compareUndefined) { long changes = 0; + if (!mBounds.equals(other.mBounds)) { + changes |= WINDOW_CONFIG_BOUNDS; + } + // Make sure that one of the values is not null and that they are not equal. if ((compareUndefined || other.mAppBounds != null) && mAppBounds != other.mAppBounds @@ -340,6 +382,16 @@ public class WindowConfiguration implements Parcelable, Comparable<WindowConfigu n = mAppBounds.bottom - that.mAppBounds.bottom; if (n != 0) return n; } + + n = mBounds.left - that.mBounds.left; + if (n != 0) return n; + n = mBounds.top - that.mBounds.top; + if (n != 0) return n; + n = mBounds.right - that.mBounds.right; + if (n != 0) return n; + n = mBounds.bottom - that.mBounds.bottom; + if (n != 0) return n; + n = mWindowingMode - that.mWindowingMode; if (n != 0) return n; n = mActivityType - that.mActivityType; @@ -367,6 +419,8 @@ public class WindowConfiguration implements Parcelable, Comparable<WindowConfigu if (mAppBounds != null) { result = 31 * result + mAppBounds.hashCode(); } + result = 31 * result + mBounds.hashCode(); + result = 31 * result + mWindowingMode; result = 31 * result + mActivityType; return result; @@ -375,7 +429,8 @@ public class WindowConfiguration implements Parcelable, Comparable<WindowConfigu /** @hide */ @Override public String toString() { - return "{mAppBounds=" + mAppBounds + return "{ mBounds=" + mBounds + + " mAppBounds=" + mAppBounds + " mWindowingMode=" + windowingModeToString(mWindowingMode) + " mActivityType=" + activityTypeToString(mActivityType) + "}"; } diff --git a/services/core/java/com/android/server/am/ActivityDisplay.java b/services/core/java/com/android/server/am/ActivityDisplay.java index 2289f8572b93..3dbee42f2e79 100644 --- a/services/core/java/com/android/server/am/ActivityDisplay.java +++ b/services/core/java/com/android/server/am/ActivityDisplay.java @@ -42,6 +42,8 @@ import android.annotation.Nullable; import android.app.ActivityManagerInternal; import android.app.ActivityOptions; import android.app.WindowConfiguration; +import android.graphics.Point; +import android.graphics.Rect; import android.util.IntArray; import android.util.Slog; import android.util.proto.ProtoOutputStream; @@ -89,6 +91,9 @@ class ActivityDisplay extends ConfigurationContainer<ActivityStack> { private ActivityStack mPinnedStack = null; private ActivityStack mSplitScreenPrimaryStack = null; + // Used in updating the display size + private Point mTmpDisplaySize = new Point(); + ActivityDisplay(ActivityStackSupervisor supervisor, int displayId) { mSupervisor = supervisor; mDisplayId = displayId; @@ -97,6 +102,13 @@ class ActivityDisplay extends ConfigurationContainer<ActivityStack> { throw new IllegalStateException("Display does not exist displayId=" + displayId); } mDisplay = display; + + updateBounds(); + } + + void updateBounds() { + mDisplay.getSize(mTmpDisplaySize); + setBounds(0, 0, mTmpDisplaySize.x, mTmpDisplaySize.y); } void addChild(ActivityStack stack, int position) { diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index aa8a36627ef1..083d30628c83 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -8098,7 +8098,7 @@ public class ActivityManagerService extends IActivityManager.Stub return false; } // An activity is consider to be in multi-window mode if its task isn't fullscreen. - return !r.getTask().mFullscreen; + return r.inMultiWindowMode(); } } finally { Binder.restoreCallingIdentity(origId); @@ -10117,8 +10117,8 @@ public class ActivityManagerService extends IActivityManager.Stub } else { // Task isn't in window manager yet since it isn't associated with a stack. // Return the persist value from activity manager - if (task.mBounds != null) { - rect.set(task.mBounds); + if (!task.matchParentBounds()) { + rect.set(task.getBounds()); } else if (task.mLastNonFullscreenBounds != null) { rect.set(task.mLastNonFullscreenBounds); } diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java index a2c46f14ed3a..11590d6ca83b 100644 --- a/services/core/java/com/android/server/am/ActivityRecord.java +++ b/services/core/java/com/android/server/am/ActivityRecord.java @@ -165,7 +165,6 @@ import android.view.IApplicationToken; import android.view.WindowManager.LayoutParams; import com.android.internal.R; -import com.android.internal.annotations.VisibleForTesting; import com.android.internal.app.ResolverActivity; import com.android.internal.content.ReferrerIntent; import com.android.internal.util.XmlUtils; @@ -343,12 +342,6 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo // on the window. int mRotationAnimationHint = -1; - // The bounds of this activity. Mainly used for aspect-ratio compatibility. - // TODO(b/36505427): Every level on ConfigurationContainer now has bounds information, which - // directly affects the configuration. We should probably move this into that class and have it - // handle calculating override configuration from the bounds. - private final Rect mBounds = new Rect(); - private boolean mShowWhenLocked; private boolean mTurnScreenOn; @@ -414,8 +407,8 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo if (!getOverrideConfiguration().equals(EMPTY)) { pw.println(prefix + "OverrideConfiguration=" + getOverrideConfiguration()); } - if (!mBounds.isEmpty()) { - pw.println(prefix + "mBounds=" + mBounds); + if (!matchParentBounds()) { + pw.println(prefix + "bounds=" + getBounds()); } if (resultTo != null || resultWho != null) { pw.print(prefix); pw.print("resultTo="); pw.print(resultTo); @@ -648,7 +641,7 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo } // An activity is considered to be in multi-window mode if its task isn't fullscreen. - final boolean inMultiWindowMode = !task.mFullscreen; + final boolean inMultiWindowMode = task.inMultiWindowMode(); if (inMultiWindowMode != mLastReportedMultiWindowMode) { mLastReportedMultiWindowMode = inMultiWindowMode; scheduleMultiWindowModeChanged(getConfiguration()); @@ -966,14 +959,14 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo (info.flags & FLAG_SHOW_FOR_ALL_USERS) != 0, info.configChanges, task.voiceSession != null, mLaunchTaskBehind, isAlwaysFocusable(), appInfo.targetSdkVersion, mRotationAnimationHint, - ActivityManagerService.getInputDispatchingTimeoutLocked(this) * 1000000L, mBounds); + ActivityManagerService.getInputDispatchingTimeoutLocked(this) * 1000000L); task.addActivityToTop(this); // When an activity is started directly into a split-screen fullscreen stack, we need to // update the initial multi-window modes so that the callbacks are scheduled correctly when // the user leaves that mode. - mLastReportedMultiWindowMode = !task.mFullscreen; + mLastReportedMultiWindowMode = inMultiWindowMode(); mLastReportedPictureInPictureMode = inPinnedWindowingMode(); } @@ -2172,33 +2165,25 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo mLastReportedConfiguration.setConfiguration(global, override); } - @Override - public void onOverrideConfigurationChanged(Configuration newConfig) { - final Configuration currentConfig = getOverrideConfiguration(); - if (currentConfig.equals(newConfig)) { - return; - } - super.onOverrideConfigurationChanged(newConfig); - if (mWindowContainerController == null) { - return; - } - mWindowContainerController.onOverrideConfigurationChanged(newConfig, mBounds); - } - // TODO(b/36505427): Consider moving this method and similar ones to ConfigurationContainer. private void updateOverrideConfiguration() { mTmpConfig.unset(); computeBounds(mTmpBounds); - if (mTmpBounds.equals(mBounds)) { + + if (mTmpBounds.equals(getOverrideBounds())) { return; } - mBounds.set(mTmpBounds); + setBounds(mTmpBounds); + + final Rect updatedBounds = getOverrideBounds(); + // Bounds changed...update configuration to match. - if (!mBounds.isEmpty()) { - task.computeOverrideConfiguration(mTmpConfig, mBounds, null /* insetBounds */, + if (!matchParentBounds()) { + task.computeOverrideConfiguration(mTmpConfig, updatedBounds, null /* insetBounds */, false /* overrideWidth */, false /* overrideHeight */); } + onOverrideConfigurationChanged(mTmpConfig); } @@ -2225,7 +2210,7 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo outBounds.setEmpty(); final float maxAspectRatio = info.maxAspectRatio; final ActivityStack stack = getStack(); - if (task == null || stack == null || !task.mFullscreen || maxAspectRatio == 0 + if (task == null || stack == null || task.inMultiWindowMode() || maxAspectRatio == 0 || isInVrUiMode(getConfiguration())) { // We don't set override configuration if that activity task isn't fullscreen. I.e. the // activity is in multi-window mode. Or, there isn't a max aspect ratio specified for @@ -2256,11 +2241,11 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo if (containingAppWidth <= maxActivityWidth && containingAppHeight <= maxActivityHeight) { // The display matches or is less than the activity aspect ratio, so nothing else to do. // Return the existing bounds. If this method is running for the first time, - // {@link mBounds} will be empty (representing no override). If the method has run - // before, then effect of {@link mBounds} will already have been applied to the + // {@link #getOverrideBounds()} will be empty (representing no override). If the method has run + // before, then effect of {@link #getOverrideBounds()} will already have been applied to the // value returned from {@link getConfiguration}. Refer to // {@link TaskRecord#computeOverrideConfiguration}. - outBounds.set(mBounds); + outBounds.set(getOverrideBounds()); return; } @@ -2272,12 +2257,6 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo outBounds.offsetTo(left, 0 /* top */); } - /** Get bounds of the activity. */ - @VisibleForTesting - Rect getBounds() { - return new Rect(mBounds); - } - /** * Make sure the given activity matches the current configuration. Returns false if the activity * had to be destroyed. Returns true if the configuration is the same, or the activity will diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java index 6985d6e36ac1..481699833e41 100644 --- a/services/core/java/com/android/server/am/ActivityStack.java +++ b/services/core/java/com/android/server/am/ActivityStack.java @@ -156,7 +156,6 @@ import java.util.Set; */ class ActivityStack<T extends StackWindowController> extends ConfigurationContainer implements StackWindowListener { - private static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityStack" : TAG_AM; private static final String TAG_ADD_REMOVE = TAG + POSTFIX_ADD_REMOVE; private static final String TAG_APP = TAG + POSTFIX_APP; @@ -322,11 +321,6 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai */ boolean mForceHidden = false; - // Whether or not this stack covers the entire screen; by default stacks are fullscreen - boolean mFullscreen = true; - // Current bounds of the stack or null if fullscreen. - Rect mBounds = null; - private boolean mUpdateBoundsDeferred; private boolean mUpdateBoundsDeferredCalled; private final Rect mDeferredBounds = new Rect(); @@ -342,8 +336,6 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai /** The attached Display's unique identifier, or -1 if detached */ int mDisplayId; - /** Temp variables used during override configuration update. */ - private final SparseArray<Configuration> mTmpConfigs = new SparseArray<>(); private final SparseArray<Rect> mTmpBounds = new SparseArray<>(); private final SparseArray<Rect> mTmpInsetBounds = new SparseArray<>(); private final Rect mTmpRect2 = new Rect(); @@ -574,7 +566,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai } } - if (!Objects.equals(mBounds, mTmpRect2)) { + if (!Objects.equals(getOverrideBounds(), mTmpRect2)) { resize(mTmpRect2, null /* tempTaskBounds */, null /* tempTaskInsetBounds */); } } finally { @@ -641,9 +633,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai */ private void postAddToDisplay(ActivityDisplay activityDisplay, Rect bounds, boolean onTop) { mDisplayId = activityDisplay.mDisplayId; - mBounds = bounds != null ? new Rect(bounds) : null; - mFullscreen = mBounds == null; - + setBounds(bounds); onParentChanged(); activityDisplay.addChild(this, onTop ? POSITION_TOP : POSITION_BOTTOM); @@ -651,7 +641,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai // If we created a docked stack we want to resize it so it resizes all other stacks // in the system. mStackSupervisor.resizeDockedStackLocked( - mBounds, null, null, null, null, PRESERVE_WINDOWS); + getOverrideBounds(), null, null, null, null, PRESERVE_WINDOWS); } } @@ -766,8 +756,9 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai return false; } - void setBounds(Rect bounds) { - mBounds = mFullscreen ? null : new Rect(bounds); + @Override + public int setBounds(Rect bounds) { + return super.setBounds(!inMultiWindowMode() ? null : bounds); } ActivityRecord topRunningActivityLocked() { @@ -2495,7 +2486,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai // apps, maybeUpdateTransitToWallpaper() will fail to identify this as a // TRANSIT_WALLPAPER_OPEN animation, and run some funny animation. final boolean lastActivityTranslucent = lastStack != null - && (!lastStack.mFullscreen + && (lastStack.inMultiWindowMode() || (lastStack.mLastPausedActivity != null && !lastStack.mLastPausedActivity.fullscreen)); @@ -2739,8 +2730,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai position = getAdjustedPositionForTask(task, position, null /* starting */); mTaskHistory.remove(task); mTaskHistory.add(position, task); - mWindowContainerController.positionChildAt(task.getWindowContainerController(), position, - task.mBounds, task.getOverrideConfiguration()); + mWindowContainerController.positionChildAt(task.getWindowContainerController(), position); updateTaskMovement(task, true); } @@ -4602,8 +4592,6 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai // TODO: Can only be called from special methods in ActivityStackSupervisor. // Need to consolidate those calls points into this resize method so anyone can call directly. void resize(Rect bounds, Rect tempTaskBounds, Rect tempTaskInsetBounds) { - bounds = TaskRecord.validateBounds(bounds); - if (!updateBoundsAllowed(bounds, tempTaskBounds, tempTaskInsetBounds)) { return; } @@ -4613,7 +4601,6 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai final Rect insetBounds = tempTaskInsetBounds != null ? tempTaskInsetBounds : taskBounds; mTmpBounds.clear(); - mTmpConfigs.clear(); mTmpInsetBounds.clear(); for (int i = mTaskHistory.size() - 1; i >= 0; i--) { @@ -4624,7 +4611,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai // For freeform stack we don't adjust the size of the tasks to match that // of the stack, but we do try to make sure the tasks are still contained // with the bounds of the stack. - mTmpRect2.set(task.mBounds); + mTmpRect2.set(task.getOverrideBounds()); fitWithinBounds(mTmpRect2, bounds); task.updateOverrideConfiguration(mTmpRect2); } else { @@ -4632,15 +4619,13 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai } } - mTmpConfigs.put(task.taskId, task.getOverrideConfiguration()); - mTmpBounds.put(task.taskId, task.mBounds); + mTmpBounds.put(task.taskId, task.getOverrideBounds()); if (tempTaskInsetBounds != null) { mTmpInsetBounds.put(task.taskId, tempTaskInsetBounds); } } - mFullscreen = mWindowContainerController.resize(bounds, mTmpConfigs, mTmpBounds, - mTmpInsetBounds); + mWindowContainerController.resize(bounds, mTmpBounds, mTmpInsetBounds); setBounds(bounds); } @@ -4655,7 +4640,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai * @param stackBounds Bounds within which the other bounds should remain. */ private static void fitWithinBounds(Rect bounds, Rect stackBounds) { - if (stackBounds == null || stackBounds.contains(bounds)) { + if (stackBounds == null || stackBounds.isEmpty() || stackBounds.contains(bounds)) { return; } @@ -4873,8 +4858,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai pw.println(""); } pw.println(prefix + "Task id #" + task.taskId); - pw.println(prefix + "mFullscreen=" + task.mFullscreen); - pw.println(prefix + "mBounds=" + task.mBounds); + pw.println(prefix + "mBounds=" + task.getOverrideBounds()); pw.println(prefix + "mMinWidth=" + task.mMinWidth); pw.println(prefix + "mMinHeight=" + task.mMinHeight); pw.println(prefix + "mLastNonFullscreenBounds=" + task.mLastNonFullscreenBounds); @@ -4981,7 +4965,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai if (isOnHomeDisplay() && mode != REMOVE_TASK_MODE_MOVING_TO_TOP && mStackSupervisor.isFocusedStack(this)) { String myReason = reason + " leftTaskHistoryEmpty"; - if (mFullscreen || !adjustFocusToNextFocusableStack(myReason)) { + if (!inMultiWindowMode() || !adjustFocusToNextFocusableStack(myReason)) { mStackSupervisor.moveHomeStackToFront(myReason); } } @@ -5011,8 +4995,8 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai final boolean isLockscreenShown = mService.mStackSupervisor.getKeyguardController() .isKeyguardShowing(mDisplayId != INVALID_DISPLAY ? mDisplayId : DEFAULT_DISPLAY); if (!mStackSupervisor.getLaunchingBoundsController().layoutTask(task, info.windowLayout) - && mBounds != null && task.isResizeable() && !isLockscreenShown) { - task.updateOverrideConfiguration(mBounds); + && !matchParentBounds() && task.isResizeable() && !isLockscreenShown) { + task.updateOverrideConfiguration(getOverrideBounds()); } task.createWindowContainer(toTop, (info.flags & FLAG_SHOW_FOR_ALL_USERS) != 0); return task; @@ -5174,10 +5158,13 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai mResumedActivity.writeIdentifierToProto(proto, RESUMED_ACTIVITY); } proto.write(DISPLAY_ID, mDisplayId); - if (mBounds != null) { - mBounds.writeToProto(proto, BOUNDS); + if (!matchParentBounds()) { + final Rect bounds = getOverrideBounds(); + bounds.writeToProto(proto, BOUNDS); } - proto.write(FULLSCREEN, mFullscreen); + + // TODO: Remove, no longer needed with windowingMode. + proto.write(FULLSCREEN, matchParentBounds()); proto.end(token); } } diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java index ddde4bc4957c..5525cdb380b7 100644 --- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java +++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java @@ -2118,7 +2118,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D } if (task.isResizeable() && canUseActivityOptionsLaunchBounds(options)) { - final Rect bounds = TaskRecord.validateBounds(options.getLaunchBounds()); + final Rect bounds = options.getLaunchBounds(); task.updateOverrideConfiguration(bounds); ActivityStack stack = getLaunchStack(null, options, task, ON_TOP); @@ -2626,7 +2626,8 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D // TODO: Checking for isAttached might not be needed as if the user passes in null // dockedBounds then they want the docked stack to be dismissed. - if (stack.mFullscreen || (dockedBounds == null && !stack.isAttached())) { + if (stack.getWindowingMode() == WINDOWING_MODE_FULLSCREEN + || (dockedBounds == null && !stack.isAttached())) { // The dock stack either was dismissed or went fullscreen, which is kinda the same. // In this case we make all other static stacks fullscreen and move all // docked stack tasks to the fullscreen stack. @@ -3058,7 +3059,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D // Resize the pinned stack to match the current size of the task the activity we are // going to be moving is currently contained in. We do this to have the right starting // animation bounds for the pinned stack to the desired bounds the caller wants. - resizeStackLocked(stack, task.mBounds, null /* tempTaskBounds */, + resizeStackLocked(stack, task.getOverrideBounds(), null /* tempTaskBounds */, null /* tempTaskInsetBounds */, !PRESERVE_WINDOWS, true /* allowResizeInDockedMode */, !DEFER_RESUME); @@ -3782,9 +3783,8 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D pw.println(" Stack #" + stack.mStackId + ": type=" + activityTypeToString(stack.getActivityType()) + " mode=" + windowingModeToString(stack.getWindowingMode())); - pw.println(" mFullscreen=" + stack.mFullscreen); pw.println(" isSleeping=" + stack.shouldSleepActivities()); - pw.println(" mBounds=" + stack.mBounds); + pw.println(" mBounds=" + stack.getOverrideBounds()); printed |= stack.dumpActivitiesLocked(fd, pw, dumpAll, dumpClient, dumpPackage, needSep); @@ -4054,6 +4054,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D private void handleDisplayChanged(int displayId) { synchronized (mService) { ActivityDisplay activityDisplay = mActivityDisplays.get(displayId); + // TODO: The following code block should be moved into {@link ActivityDisplay}. if (activityDisplay != null) { // The window policy is responsible for stopping activities on the default display if (displayId != Display.DEFAULT_DISPLAY) { @@ -4067,7 +4068,8 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D activityDisplay.mOffToken = null; } } - // TODO: Update the bounds. + + activityDisplay.updateBounds(); } mWindowManager.onDisplayChanged(displayId); } @@ -4289,7 +4291,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D return; } - scheduleUpdatePictureInPictureModeIfNeeded(task, stack.mBounds); + scheduleUpdatePictureInPictureModeIfNeeded(task, stack.getOverrideBounds()); } void scheduleUpdatePictureInPictureModeIfNeeded(TaskRecord task, Rect targetStackBounds) { diff --git a/services/core/java/com/android/server/am/LaunchingActivityPositioner.java b/services/core/java/com/android/server/am/LaunchingActivityPositioner.java index d5f9cf3ad4d5..793884d08c08 100644 --- a/services/core/java/com/android/server/am/LaunchingActivityPositioner.java +++ b/services/core/java/com/android/server/am/LaunchingActivityPositioner.java @@ -47,10 +47,10 @@ public class LaunchingActivityPositioner implements LaunchingBoundsPositioner { return RESULT_SKIP; } - final Rect bounds = TaskRecord.validateBounds(options.getLaunchBounds()); + final Rect bounds = options.getLaunchBounds(); // Bounds weren't valid. - if (bounds == null) { + if (bounds == null || bounds.isEmpty()) { return RESULT_SKIP; } diff --git a/services/core/java/com/android/server/am/LaunchingTaskPositioner.java b/services/core/java/com/android/server/am/LaunchingTaskPositioner.java index c958fcac6938..d89568e27506 100644 --- a/services/core/java/com/android/server/am/LaunchingTaskPositioner.java +++ b/services/core/java/com/android/server/am/LaunchingTaskPositioner.java @@ -88,7 +88,7 @@ class LaunchingTaskPositioner implements LaunchingBoundsController.LaunchingBoun final ArrayList<TaskRecord> tasks = task.getStack().getAllTasks(); - updateAvailableRect(task, mAvailableRect); + mAvailableRect.set(task.getParent().getBounds()); if (layout == null) { positionCenter(tasks, mAvailableRect, getFreeformWidth(mAvailableRect), @@ -123,17 +123,6 @@ class LaunchingTaskPositioner implements LaunchingBoundsController.LaunchingBoun return RESULT_CONTINUE; } - private void updateAvailableRect(TaskRecord task, Rect availableRect) { - final Rect stackBounds = task.getStack().mBounds; - - if (stackBounds != null) { - availableRect.set(stackBounds); - } else { - task.getStack().getDisplay().mDisplay.getSize(mDisplaySize); - availableRect.set(0, 0, mDisplaySize.x, mDisplaySize.y); - } - } - @VisibleForTesting static int getFreeformStartLeft(Rect bounds) { return bounds.left + bounds.width() / MARGIN_SIZE_DENOMINATOR; @@ -294,9 +283,9 @@ class LaunchingTaskPositioner implements LaunchingBoundsController.LaunchingBoun private static boolean boundsConflict(Rect proposal, ArrayList<TaskRecord> tasks) { for (int i = tasks.size() - 1; i >= 0; i--) { - TaskRecord task = tasks.get(i); - if (!task.mActivities.isEmpty() && task.mBounds != null) { - Rect bounds = task.mBounds; + final TaskRecord task = tasks.get(i); + if (!task.mActivities.isEmpty() && !task.matchParentBounds()) { + final Rect bounds = task.getOverrideBounds(); if (closeLeftTopCorner(proposal, bounds) || closeRightTopCorner(proposal, bounds) || closeLeftBottomCorner(proposal, bounds) || closeRightBottomCorner(proposal, bounds)) { diff --git a/services/core/java/com/android/server/am/RecentTasks.java b/services/core/java/com/android/server/am/RecentTasks.java index d35c37b54431..cecdc5c2c437 100644 --- a/services/core/java/com/android/server/am/RecentTasks.java +++ b/services/core/java/com/android/server/am/RecentTasks.java @@ -1444,8 +1444,8 @@ class RecentTasks { rti.affiliatedTaskId = tr.mAffiliatedTaskId; rti.affiliatedTaskColor = tr.mAffiliatedTaskColor; rti.numActivities = 0; - if (tr.mBounds != null) { - rti.bounds = new Rect(tr.mBounds); + if (!tr.matchParentBounds()) { + rti.bounds = new Rect(tr.getOverrideBounds()); } rti.supportsSplitScreenMultiWindow = tr.supportsSplitScreenWindowingMode(); rti.resizeMode = tr.mResizeMode; diff --git a/services/core/java/com/android/server/am/TaskRecord.java b/services/core/java/com/android/server/am/TaskRecord.java index a9c6eee05bf6..b69cad42f486 100644 --- a/services/core/java/com/android/server/am/TaskRecord.java +++ b/services/core/java/com/android/server/am/TaskRecord.java @@ -19,9 +19,6 @@ package com.android.server.am; import static android.app.ActivityManager.RESIZE_MODE_FORCED; import static android.app.ActivityManager.RESIZE_MODE_SYSTEM; import static android.app.ActivityManager.StackId.INVALID_STACK_ID; -import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT; -import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME; -import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS; import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD; import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED; import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM; @@ -293,11 +290,6 @@ class TaskRecord extends ConfigurationContainer implements TaskWindowContainerLi final ActivityManagerService mService; - // Whether or not this task covers the entire screen; by default tasks are fullscreen. - boolean mFullscreen = true; - - // Bounds of the Task. null for fullscreen tasks. - Rect mBounds = null; private final Rect mTmpStableBounds = new Rect(); private final Rect mTmpNonDecorBounds = new Rect(); private final Rect mTmpRect = new Rect(); @@ -480,68 +472,76 @@ class TaskRecord extends ConfigurationContainer implements TaskWindowContainerLi } boolean resize(Rect bounds, int resizeMode, boolean preserveWindow, boolean deferResume) { - if (!isResizeable()) { - Slog.w(TAG, "resizeTask: task " + this + " not resizeable."); - return true; - } + mService.mWindowManager.deferSurfaceLayout(); - // If this is a forced resize, let it go through even if the bounds is not changing, - // as we might need a relayout due to surface size change (to/from fullscreen). - final boolean forced = (resizeMode & RESIZE_MODE_FORCED) != 0; - if (Objects.equals(mBounds, bounds) && !forced) { - // Nothing to do here... - return true; - } - bounds = validateBounds(bounds); - - if (mWindowContainerController == null) { - // Task doesn't exist in window manager yet (e.g. was restored from recents). - // All we can do for now is update the bounds so it can be used when the task is - // added to window manager. - updateOverrideConfiguration(bounds); - if (!inFreeformWindowingMode()) { - // re-restore the task so it can have the proper stack association. - mService.mStackSupervisor.restoreRecentTaskLocked(this, null, !ON_TOP); + try { + if (!isResizeable()) { + Slog.w(TAG, "resizeTask: task " + this + " not resizeable."); + return true; } - return true; - } - if (!canResizeToBounds(bounds)) { - throw new IllegalArgumentException("resizeTask: Can not resize task=" + this - + " to bounds=" + bounds + " resizeMode=" + mResizeMode); - } + // If this is a forced resize, let it go through even if the bounds is not changing, + // as we might need a relayout due to surface size change (to/from fullscreen). + final boolean forced = (resizeMode & RESIZE_MODE_FORCED) != 0; + if (equivalentOverrideBounds(bounds) && !forced) { + // Nothing to do here... + return true; + } - // Do not move the task to another stack here. - // This method assumes that the task is already placed in the right stack. - // we do not mess with that decision and we only do the resize! + if (mWindowContainerController == null) { + // Task doesn't exist in window manager yet (e.g. was restored from recents). + // All we can do for now is update the bounds so it can be used when the task is + // added to window manager. + updateOverrideConfiguration(bounds); + if (!inFreeformWindowingMode()) { + // re-restore the task so it can have the proper stack association. + mService.mStackSupervisor.restoreRecentTaskLocked(this, null, !ON_TOP); + } + return true; + } - Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "am.resizeTask_" + taskId); + if (!canResizeToBounds(bounds)) { + throw new IllegalArgumentException("resizeTask: Can not resize task=" + this + + " to bounds=" + bounds + " resizeMode=" + mResizeMode); + } - final boolean updatedConfig = updateOverrideConfiguration(bounds); - // This variable holds information whether the configuration didn't change in a significant - // way and the activity was kept the way it was. If it's false, it means the activity had - // to be relaunched due to configuration change. - boolean kept = true; - if (updatedConfig) { - final ActivityRecord r = topRunningActivityLocked(); - if (r != null && !deferResume) { - kept = r.ensureActivityConfigurationLocked(0 /* globalChanges */, preserveWindow); - mService.mStackSupervisor.ensureActivitiesVisibleLocked(r, 0, !PRESERVE_WINDOWS); - if (!kept) { - mService.mStackSupervisor.resumeFocusedStackTopActivityLocked(); + // Do not move the task to another stack here. + // This method assumes that the task is already placed in the right stack. + // we do not mess with that decision and we only do the resize! + + Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "am.resizeTask_" + taskId); + + final boolean updatedConfig = updateOverrideConfiguration(bounds); + // This variable holds information whether the configuration didn't change in a significant + + // way and the activity was kept the way it was. If it's false, it means the activity + // had + // to be relaunched due to configuration change. + boolean kept = true; + if (updatedConfig) { + final ActivityRecord r = topRunningActivityLocked(); + if (r != null && !deferResume) { + kept = r.ensureActivityConfigurationLocked(0 /* globalChanges */, + preserveWindow); + mService.mStackSupervisor.ensureActivitiesVisibleLocked(r, 0, + !PRESERVE_WINDOWS); + if (!kept) { + mService.mStackSupervisor.resumeFocusedStackTopActivityLocked(); + } } } - } - mWindowContainerController.resize(mBounds, getOverrideConfiguration(), kept, forced); + mWindowContainerController.resize(kept, forced); - Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER); - return kept; + Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER); + return kept; + } finally { + mService.mWindowManager.continueSurfaceLayout(); + } } // TODO: Investigate combining with the resize() method above. void resizeWindowContainer() { - mWindowContainerController.resize(mBounds, getOverrideConfiguration(), false /* relayout */, - false /* forced */); + mWindowContainerController.resize(false /* relayout */, false /* forced */); } void getWindowContainerBounds(Rect bounds) { @@ -686,16 +686,17 @@ class TaskRecord extends ConfigurationContainer implements TaskWindowContainerLi // Make sure the task has the appropriate bounds/size for the stack it is in. final boolean toStackSplitScreenPrimary = toStackWindowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY; + final Rect configBounds = getOverrideBounds(); if ((toStackWindowingMode == WINDOWING_MODE_FULLSCREEN || toStackWindowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY) - && !Objects.equals(mBounds, toStack.mBounds)) { - kept = resize(toStack.mBounds, RESIZE_MODE_SYSTEM, !mightReplaceWindow, + && !Objects.equals(configBounds, toStack.getOverrideBounds())) { + kept = resize(toStack.getOverrideBounds(), RESIZE_MODE_SYSTEM, !mightReplaceWindow, deferResume); } else if (toStackWindowingMode == WINDOWING_MODE_FREEFORM) { Rect bounds = getLaunchBounds(); if (bounds == null) { mService.mStackSupervisor.getLaunchingBoundsController().layoutTask(this, null); - bounds = mBounds; + bounds = configBounds; } kept = resize(bounds, RESIZE_MODE_FORCED, !mightReplaceWindow, deferResume); } else if (toStackSplitScreenPrimary || toStackWindowingMode == WINDOWING_MODE_PINNED) { @@ -704,7 +705,7 @@ class TaskRecord extends ConfigurationContainer implements TaskWindowContainerLi // mode mService.mStackSupervisor.moveRecentsStackToFront(reason); } - kept = resize(toStack.mBounds, RESIZE_MODE_SYSTEM, !mightReplaceWindow, + kept = resize(toStack.getOverrideBounds(), RESIZE_MODE_SYSTEM, !mightReplaceWindow, deferResume); } } finally { @@ -1501,8 +1502,10 @@ class TaskRecord extends ConfigurationContainer implements TaskWindowContainerLi return true; } final boolean landscape = bounds.width() > bounds.height(); + final Rect configBounds = getOverrideBounds(); if (mResizeMode == RESIZE_MODE_FORCE_RESIZABLE_PRESERVE_ORIENTATION) { - return mBounds == null || landscape == (mBounds.width() > mBounds.height()); + return configBounds.isEmpty() + || landscape == (configBounds.width() > configBounds.height()); } return (mResizeMode != RESIZE_MODE_FORCE_RESIZABLE_PORTRAIT_ONLY || !landscape) && (mResizeMode != RESIZE_MODE_FORCE_RESIZABLE_LANDSCAPE_ONLY || landscape); @@ -1920,8 +1923,9 @@ class TaskRecord extends ConfigurationContainer implements TaskWindowContainerLi return; } + final Rect configBounds = getOverrideBounds(); if (adjustWidth) { - if (mBounds != null && bounds.right == mBounds.right) { + if (!configBounds.isEmpty() && bounds.right == configBounds.right) { bounds.left = bounds.right - minWidth; } else { // Either left bounds match, or neither match, or the previous bounds were @@ -1930,7 +1934,7 @@ class TaskRecord extends ConfigurationContainer implements TaskWindowContainerLi } } if (adjustHeight) { - if (mBounds != null && bounds.bottom == mBounds.bottom) { + if (!configBounds.isEmpty() && bounds.bottom == configBounds.bottom) { bounds.top = bounds.bottom - minHeight; } else { // Either top bounds match, or neither match, or the previous bounds were @@ -1977,38 +1981,37 @@ class TaskRecord extends ConfigurationContainer implements TaskWindowContainerLi * @return True if the override configuration was updated. */ boolean updateOverrideConfiguration(Rect bounds, @Nullable Rect insetBounds) { - if (Objects.equals(mBounds, bounds)) { + if (equivalentOverrideBounds(bounds)) { return false; } + final Rect currentBounds = getOverrideBounds(); + mTmpConfig.setTo(getOverrideConfiguration()); - final boolean oldFullscreen = mFullscreen; + final boolean oldMatchParentBounds = matchParentBounds(); final Configuration newConfig = getOverrideConfiguration(); - mFullscreen = bounds == null; + final boolean matchParentBounds = bounds == null || bounds.isEmpty(); final boolean persistBounds = getWindowConfiguration().persistTaskBounds(); - if (mFullscreen) { - if (mBounds != null && persistBounds) { - mLastNonFullscreenBounds = mBounds; + if (matchParentBounds) { + if (!currentBounds.isEmpty() && persistBounds) { + mLastNonFullscreenBounds = currentBounds; } - mBounds = null; + setBounds(null); newConfig.unset(); } else { mTmpRect.set(bounds); adjustForMinimalTaskDimensions(mTmpRect); - if (mBounds == null) { - mBounds = new Rect(mTmpRect); - } else { - mBounds.set(mTmpRect); - } + setBounds(mTmpRect); + if (mStack == null || persistBounds) { - mLastNonFullscreenBounds = mBounds; + mLastNonFullscreenBounds = getOverrideBounds(); } computeOverrideConfiguration(newConfig, mTmpRect, insetBounds, mTmpRect.right != bounds.right, mTmpRect.bottom != bounds.bottom); } onOverrideConfigurationChanged(newConfig); - if (mFullscreen != oldFullscreen) { + if (matchParentBounds != oldMatchParentBounds) { mService.mStackSupervisor.scheduleUpdateMultiWindowMode(this); } @@ -2053,23 +2056,19 @@ class TaskRecord extends ConfigurationContainer implements TaskWindowContainerLi final int longSize = Math.max(compatScreenHeightDp, compatScreenWidthDp); final int shortSize = Math.min(compatScreenHeightDp, compatScreenWidthDp); config.screenLayout = Configuration.reduceScreenLayout(sl, longSize, shortSize); - } Rect updateOverrideConfigurationFromLaunchBounds() { - final Rect bounds = validateBounds(getLaunchBounds()); + final Rect bounds = getLaunchBounds(); updateOverrideConfiguration(bounds); - if (bounds != null) { - bounds.set(mBounds); + if (bounds != null && !bounds.isEmpty()) { + // TODO: Review if we actually want to do this - we are setting the launch bounds + // directly here. + bounds.set(getOverrideBounds()); } return bounds; } - static Rect validateBounds(Rect bounds) { - // TODO: Not needed once we have bounds in WindowConfiguration. - return (bounds != null && bounds.isEmpty()) ? null : bounds; - } - /** Updates the task's bounds and override configuration to match what is expected for the * input stack. */ void updateOverrideConfigurationForStack(ActivityStack inStack) { @@ -2082,7 +2081,7 @@ class TaskRecord extends ConfigurationContainer implements TaskWindowContainerLi throw new IllegalArgumentException("Can not position non-resizeable task=" + this + " in stack=" + inStack); } - if (mBounds != null) { + if (!matchParentBounds()) { return; } if (mLastNonFullscreenBounds != null) { @@ -2091,7 +2090,7 @@ class TaskRecord extends ConfigurationContainer implements TaskWindowContainerLi mService.mStackSupervisor.getLaunchingBoundsController().layoutTask(this, null); } } else { - updateOverrideConfiguration(inStack.mBounds); + updateOverrideConfiguration(inStack.getOverrideBounds()); } } @@ -2105,9 +2104,9 @@ class TaskRecord extends ConfigurationContainer implements TaskWindowContainerLi if (!isActivityTypeStandardOrUndefined() || windowingMode == WINDOWING_MODE_FULLSCREEN || (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY && !isResizeable())) { - return isResizeable() ? mStack.mBounds : null; + return isResizeable() ? mStack.getOverrideBounds() : null; } else if (!getWindowConfiguration().persistTaskBounds()) { - return mStack.mBounds; + return mStack.getOverrideBounds(); } return mLastNonFullscreenBounds; } @@ -2287,9 +2286,12 @@ class TaskRecord extends ConfigurationContainer implements TaskWindowContainerLi } proto.write(ACTIVITY_TYPE, getActivityType()); proto.write(RESIZE_MODE, mResizeMode); - proto.write(FULLSCREEN, mFullscreen); - if (mBounds != null) { - mBounds.writeToProto(proto, BOUNDS); + // TODO: Remove, no longer needed with windowingMode. + proto.write(FULLSCREEN, matchParentBounds()); + + if (!matchParentBounds()) { + final Rect bounds = getOverrideBounds(); + bounds.writeToProto(proto, BOUNDS); } proto.write(MIN_WIDTH, mMinWidth); proto.write(MIN_HEIGHT, mMinHeight); diff --git a/services/core/java/com/android/server/wm/AppWindowContainerController.java b/services/core/java/com/android/server/wm/AppWindowContainerController.java index a528ecdf537e..00a0d3d18f9c 100644 --- a/services/core/java/com/android/server/wm/AppWindowContainerController.java +++ b/services/core/java/com/android/server/wm/AppWindowContainerController.java @@ -181,13 +181,12 @@ public class AppWindowContainerController IApplicationToken token, AppWindowContainerListener listener, int index, int requestedOrientation, boolean fullscreen, boolean showForAllUsers, int configChanges, boolean voiceInteraction, boolean launchTaskBehind, boolean alwaysFocusable, - int targetSdkVersion, int rotationAnimationHint, long inputDispatchingTimeoutNanos, - Rect bounds) { + int targetSdkVersion, int rotationAnimationHint, long inputDispatchingTimeoutNanos) { this(taskController, token, listener, index, requestedOrientation, fullscreen, showForAllUsers, configChanges, voiceInteraction, launchTaskBehind, alwaysFocusable, targetSdkVersion, rotationAnimationHint, inputDispatchingTimeoutNanos, - WindowManagerService.getInstance(), bounds); + WindowManagerService.getInstance()); } public AppWindowContainerController(TaskWindowContainerController taskController, @@ -195,7 +194,7 @@ public class AppWindowContainerController int requestedOrientation, boolean fullscreen, boolean showForAllUsers, int configChanges, boolean voiceInteraction, boolean launchTaskBehind, boolean alwaysFocusable, int targetSdkVersion, int rotationAnimationHint, long inputDispatchingTimeoutNanos, - WindowManagerService service, Rect bounds) { + WindowManagerService service) { super(listener, service); mHandler = new H(service.mH.getLooper()); mToken = token; @@ -216,7 +215,7 @@ public class AppWindowContainerController atoken = createAppWindow(mService, token, voiceInteraction, task.getDisplayContent(), inputDispatchingTimeoutNanos, fullscreen, showForAllUsers, targetSdkVersion, requestedOrientation, rotationAnimationHint, configChanges, launchTaskBehind, - alwaysFocusable, this, bounds); + alwaysFocusable, this); if (DEBUG_TOKEN_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG_WM, "addAppToken: " + atoken + " controller=" + taskController + " at " + index); task.addChild(atoken, index); @@ -228,11 +227,11 @@ public class AppWindowContainerController boolean voiceInteraction, DisplayContent dc, long inputDispatchingTimeoutNanos, boolean fullscreen, boolean showForAllUsers, int targetSdk, int orientation, int rotationAnimationHint, int configChanges, boolean launchTaskBehind, - boolean alwaysFocusable, AppWindowContainerController controller, Rect bounds) { + boolean alwaysFocusable, AppWindowContainerController controller) { return new AppWindowToken(service, token, voiceInteraction, dc, inputDispatchingTimeoutNanos, fullscreen, showForAllUsers, targetSdk, orientation, rotationAnimationHint, configChanges, launchTaskBehind, alwaysFocusable, - controller, bounds); + controller); } public void removeContainer(int displayId) { @@ -299,17 +298,6 @@ public class AppWindowContainerController } } - // TODO(b/36505427): Maybe move to WindowContainerController so other sub-classes can use it as - // a generic way to set override config. Need to untangle current ways the override config is - // currently set for tasks and displays before we are doing that though. - public void onOverrideConfigurationChanged(Configuration overrideConfiguration, Rect bounds) { - synchronized(mWindowMap) { - if (mContainer != null) { - mContainer.onOverrideConfigurationChanged(overrideConfiguration, bounds); - } - } - } - public void setDisablePreviewScreenshots(boolean disable) { synchronized (mWindowMap) { if (mContainer == null) { diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java index 627f8cee3fd1..c39ce982e4cb 100644 --- a/services/core/java/com/android/server/wm/AppWindowToken.java +++ b/services/core/java/com/android/server/wm/AppWindowToken.java @@ -175,11 +175,6 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree private boolean mLastContainsShowWhenLockedWindow; private boolean mLastContainsDismissKeyguardWindow; - // The bounds of this activity. Mainly used for aspect-ratio compatibility. - // TODO(b/36505427): Every level on WindowContainer now has bounds information, which directly - // affects the configuration. We should probably move this into that class. - private final Rect mBounds = new Rect(); - ArrayDeque<Rect> mFrozenBounds = new ArrayDeque<>(); ArrayDeque<Configuration> mFrozenMergedConfig = new ArrayDeque<>(); @@ -196,8 +191,8 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree DisplayContent dc, long inputDispatchingTimeoutNanos, boolean fullscreen, boolean showForAllUsers, int targetSdk, int orientation, int rotationAnimationHint, int configChanges, boolean launchTaskBehind, boolean alwaysFocusable, - AppWindowContainerController controller, Rect bounds) { - this(service, token, voiceInteraction, dc, fullscreen, bounds); + AppWindowContainerController controller) { + this(service, token, voiceInteraction, dc, fullscreen); setController(controller); mInputDispatchingTimeoutNanos = inputDispatchingTimeoutNanos; mShowForAllUsers = showForAllUsers; @@ -214,7 +209,7 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree } AppWindowToken(WindowManagerService service, IApplicationToken token, boolean voiceInteraction, - DisplayContent dc, boolean fillsParent, Rect bounds) { + DisplayContent dc, boolean fillsParent) { super(service, token != null ? token.asBinder() : null, TYPE_APPLICATION, true, dc, false /* ownerCanManageAppTokens */); appToken = token; @@ -222,27 +217,6 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree mFillsParent = fillsParent; mInputApplicationHandle = new InputApplicationHandle(this); mAppAnimator = new AppWindowAnimator(this, service); - if (bounds != null) { - mBounds.set(bounds); - } - } - - void onOverrideConfigurationChanged(Configuration overrideConfiguration, Rect bounds) { - onOverrideConfigurationChanged(overrideConfiguration); - if (mBounds.equals(bounds)) { - return; - } - // TODO(b/36505427): If bounds is in WC, then we can automatically call onResize() when set. - mBounds.set(bounds); - onResize(); - } - - void getBounds(Rect outBounds) { - outBounds.set(mBounds); - } - - boolean hasBounds() { - return !mBounds.isEmpty(); } void onFirstWindowDrawn(WindowState win, WindowStateAnimator winAnimator) { diff --git a/services/core/java/com/android/server/wm/ConfigurationContainer.java b/services/core/java/com/android/server/wm/ConfigurationContainer.java index b534b8ac2244..d340923b754e 100644 --- a/services/core/java/com/android/server/wm/ConfigurationContainer.java +++ b/services/core/java/com/android/server/wm/ConfigurationContainer.java @@ -36,6 +36,7 @@ import static com.android.server.wm.proto.ConfigurationContainerProto.OVERRIDE_C import android.annotation.CallSuper; import android.app.WindowConfiguration; import android.content.res.Configuration; +import android.graphics.Rect; import android.util.proto.ProtoOutputStream; import java.io.PrintWriter; @@ -46,6 +47,11 @@ import java.util.ArrayList; * hierarchy. */ public abstract class ConfigurationContainer<E extends ConfigurationContainer> { + /** + * {@link #Rect} returned from {@link #getOverrideBounds()} to prevent original value from being + * set directly. + */ + private Rect mReturnBounds = new Rect(); /** Contains override configuration settings applied to this configuration container. */ private Configuration mOverrideConfiguration = new Configuration(); @@ -71,6 +77,16 @@ public abstract class ConfigurationContainer<E extends ConfigurationContainer> { // TODO: Can't have ag/2592611 soon enough! private final Configuration mTmpConfig = new Configuration(); + // Used for setting bounds + private final Rect mTmpRect = new Rect(); + + static final int BOUNDS_CHANGE_NONE = 0; + // Return value from {@link setBounds} indicating the position of the override bounds changed. + static final int BOUNDS_CHANGE_POSITION = 1; + // Return value from {@link setBounds} indicating the size of the override bounds changed. + static final int BOUNDS_CHANGE_SIZE = 1 << 1; + + /** * Returns full configuration applied to this configuration container. * This method should be used for getting settings applied in each particular level of the @@ -148,6 +164,118 @@ public abstract class ConfigurationContainer<E extends ConfigurationContainer> { } } + /** + * Indicates whether this container has not specified any bounds different from its parent. In + * this case, it will inherit the bounds of the first ancestor which specifies a bounds. + * @return {@code true} if no explicit bounds have been set at this container level. + * {@code false} otherwise. + */ + public boolean matchParentBounds() { + return getOverrideBounds().isEmpty(); + } + + /** + * Returns whether the bounds specified is considered the same as the existing override bounds. + * This is either when the two bounds are equal or the override bounds is empty and the + * specified bounds is null. + * + * @return {@code true} if the bounds are equivalent, {@code false} otherwise + */ + public boolean equivalentOverrideBounds(Rect bounds) { + return equivalentBounds(getOverrideBounds(), bounds); + } + + /** + * Returns whether the two bounds are equal to each other or are a combination of null or empty. + */ + public static boolean equivalentBounds(Rect bounds, Rect other) { + return bounds == other + || (bounds != null && (bounds.equals(other) || (bounds.isEmpty() && other == null))) + || (other != null && other.isEmpty() && bounds == null); + } + + /** + * Returns the effective bounds of this container, inheriting the first non-empty bounds set in + * its ancestral hierarchy, including itself. + * @return + */ + public Rect getBounds() { + mReturnBounds.set(getConfiguration().windowConfiguration.getBounds()); + return mReturnBounds; + } + + public void getBounds(Rect outBounds) { + outBounds.set(getBounds()); + } + + /** + * Returns the current bounds explicitly set on this container. The {@link Rect} handed back is + * shared for all calls to this method and should not be modified. + */ + public Rect getOverrideBounds() { + mReturnBounds.set(getOverrideConfiguration().windowConfiguration.getBounds()); + + return mReturnBounds; + } + + /** + * Sets the passed in {@link Rect} to the current bounds. + * @see {@link #getOverrideBounds()}. + */ + public void getOverrideBounds(Rect outBounds) { + outBounds.set(getOverrideBounds()); + } + + /** + * Sets the bounds at the current hierarchy level, overriding any bounds set on an ancestor. + * This value will be reported when {@link #getBounds()} and {@link #getOverrideBounds()}. If + * an empty {@link Rect} or null is specified, this container will be considered to match its + * parent bounds {@see #matchParentBounds} and will inherit bounds from its parent. + * @param bounds The bounds defining the container size. + * @return a bitmask representing the types of changes made to the bounds. + */ + public int setBounds(Rect bounds) { + int boundsChange = diffOverrideBounds(bounds); + + if (boundsChange == BOUNDS_CHANGE_NONE) { + return boundsChange; + } + + + mTmpConfig.setTo(getOverrideConfiguration()); + mTmpConfig.windowConfiguration.setBounds(bounds); + onOverrideConfigurationChanged(mTmpConfig); + + return boundsChange; + } + + public int setBounds(int left, int top, int right, int bottom) { + mTmpRect.set(left, top, right, bottom); + return setBounds(mTmpRect); + } + + int diffOverrideBounds(Rect bounds) { + if (equivalentOverrideBounds(bounds)) { + return BOUNDS_CHANGE_NONE; + } + + int boundsChange = BOUNDS_CHANGE_NONE; + + final Rect existingBounds = getOverrideBounds(); + + if (bounds == null || existingBounds.left != bounds.left + || existingBounds.top != bounds.top) { + boundsChange |= BOUNDS_CHANGE_POSITION; + } + + if (bounds == null || existingBounds.width() != bounds.width() + || existingBounds.height() != bounds.height()) { + boundsChange |= BOUNDS_CHANGE_SIZE; + } + + return boundsChange; + } + public WindowConfiguration getWindowConfiguration() { return mFullConfiguration.windowConfiguration; } diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java index 44dfa07794d2..3fb377385220 100644 --- a/services/core/java/com/android/server/wm/DisplayContent.java +++ b/services/core/java/com/android/server/wm/DisplayContent.java @@ -314,6 +314,9 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo private final Matrix mTmpMatrix = new Matrix(); private final Region mTmpRegion = new Region(); + /** Used for handing back size of display */ + private final Rect mTmpBounds = new Rect(); + WindowManagerService mService; /** Remove this display when animation on it has completed. */ @@ -1223,6 +1226,8 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo mCompatibleScreenScale = CompatibilityInfo.computeCompatibleScaling(mDisplayMetrics, mCompatDisplayMetrics); } + + updateBounds(); return mDisplayInfo; } @@ -1541,8 +1546,17 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo // See {@link PhoneWindowManager#setInitialDisplaySize}...sigh... mService.reconfigureDisplayLocked(this); - getDockedDividerController().onConfigurationChanged(); - getPinnedStackController().onConfigurationChanged(); + final DockedStackDividerController dividerController = getDockedDividerController(); + + if (dividerController != null) { + getDockedDividerController().onConfigurationChanged(); + } + + final PinnedStackController pinnedStackController = getPinnedStackController(); + + if (pinnedStackController != null) { + getPinnedStackController().onConfigurationChanged(); + } } /** @@ -1681,33 +1695,6 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo mInitialDisplayDensity = mDisplayInfo.logicalDensityDpi; } - void getLogicalDisplayRect(Rect out) { - // Uses same calculation as in LogicalDisplay#configureDisplayInTransactionLocked. - final int orientation = mDisplayInfo.rotation; - boolean rotated = (orientation == ROTATION_90 || orientation == ROTATION_270); - final int physWidth = rotated ? mBaseDisplayHeight : mBaseDisplayWidth; - final int physHeight = rotated ? mBaseDisplayWidth : mBaseDisplayHeight; - int width = mDisplayInfo.logicalWidth; - int left = (physWidth - width) / 2; - int height = mDisplayInfo.logicalHeight; - int top = (physHeight - height) / 2; - out.set(left, top, left + width, top + height); - } - - private void getLogicalDisplayRect(Rect out, int orientation) { - getLogicalDisplayRect(out); - - // Rotate the Rect if needed. - final int currentRotation = mDisplayInfo.rotation; - final int rotationDelta = deltaRotation(currentRotation, orientation); - if (rotationDelta == ROTATION_90 || rotationDelta == ROTATION_270) { - createRotationMatrix(rotationDelta, mBaseDisplayWidth, mBaseDisplayHeight, mTmpMatrix); - mTmpRectF.set(out); - mTmpMatrix.mapRect(mTmpRectF); - mTmpRectF.round(out); - } - } - /** * If display metrics changed, overrides are not set and it's not just a rotation - update base * values. @@ -1775,6 +1762,8 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo } mBaseDisplayRect.set(0, 0, mBaseDisplayWidth, mBaseDisplayHeight); + + updateBounds(); } void getContentRect(Rect out) { @@ -2104,7 +2093,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo } void rotateBounds(int oldRotation, int newRotation, Rect bounds) { - getLogicalDisplayRect(mTmpRect, newRotation); + getBounds(mTmpRect, newRotation); // Compute a transform matrix to undo the coordinate space transformation, // and present the window at the same physical position it previously occupied. @@ -2881,6 +2870,44 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo return mTmpApplySurfaceChangesTransactionState.focusDisplayed; } + private void updateBounds() { + calculateBounds(mTmpBounds); + setBounds(mTmpBounds); + } + + // Determines the current display bounds based on the current state + private void calculateBounds(Rect out) { + // Uses same calculation as in LogicalDisplay#configureDisplayInTransactionLocked. + final int orientation = mDisplayInfo.rotation; + boolean rotated = (orientation == ROTATION_90 || orientation == ROTATION_270); + final int physWidth = rotated ? mBaseDisplayHeight : mBaseDisplayWidth; + final int physHeight = rotated ? mBaseDisplayWidth : mBaseDisplayHeight; + int width = mDisplayInfo.logicalWidth; + int left = (physWidth - width) / 2; + int height = mDisplayInfo.logicalHeight; + int top = (physHeight - height) / 2; + out.set(left, top, left + width, top + height); + } + + @Override + public void getBounds(Rect out) { + calculateBounds(out); + } + + private void getBounds(Rect out, int orientation) { + getBounds(out); + + // Rotate the Rect if needed. + final int currentRotation = mDisplayInfo.rotation; + final int rotationDelta = deltaRotation(currentRotation, orientation); + if (rotationDelta == ROTATION_90 || rotationDelta == ROTATION_270) { + createRotationMatrix(rotationDelta, mBaseDisplayWidth, mBaseDisplayHeight, mTmpMatrix); + mTmpRectF.set(out); + mTmpMatrix.mapRect(mTmpRectF); + mTmpRectF.round(out); + } + } + void performLayout(boolean initial, boolean updateInputWindows) { if (!isLayoutNeeded()) { return; diff --git a/services/core/java/com/android/server/wm/DockedStackDividerController.java b/services/core/java/com/android/server/wm/DockedStackDividerController.java index 8308417fa141..a37598e706c6 100644 --- a/services/core/java/com/android/server/wm/DockedStackDividerController.java +++ b/services/core/java/com/android/server/wm/DockedStackDividerController.java @@ -655,8 +655,8 @@ public class DockedStackDividerController { } private boolean isWithinDisplay(Task task) { - task.mStack.getBounds(mTmpRect); - mDisplayContent.getLogicalDisplayRect(mTmpRect2); + task.getBounds(mTmpRect); + mDisplayContent.getBounds(mTmpRect2); return mTmpRect.intersect(mTmpRect2); } diff --git a/services/core/java/com/android/server/wm/InputMonitor.java b/services/core/java/com/android/server/wm/InputMonitor.java index 18b0f976dbd2..7e29a3aa811e 100644 --- a/services/core/java/com/android/server/wm/InputMonitor.java +++ b/services/core/java/com/android/server/wm/InputMonitor.java @@ -661,8 +661,8 @@ final class InputMonitor implements InputManagerService.WindowManagerCallbacks { if (w.inPinnedWindowingMode()) { if (mAddPipInputConsumerHandle && (inputWindowHandle.layer <= pipInputConsumer.mWindowHandle.layer)) { - // Update the bounds of the Pip input consumer to match the Pinned stack - w.getStack().getBounds(pipTouchableBounds); + // Update the bounds of the Pip input consumer to match the window bounds. + w.getBounds(pipTouchableBounds); pipInputConsumer.mWindowHandle.touchableRegion.set(pipTouchableBounds); addInputWindowHandle(pipInputConsumer.mWindowHandle); mAddPipInputConsumerHandle = false; diff --git a/services/core/java/com/android/server/wm/PinnedStackWindowController.java b/services/core/java/com/android/server/wm/PinnedStackWindowController.java index 41f076d7b6af..b021a7223e2e 100644 --- a/services/core/java/com/android/server/wm/PinnedStackWindowController.java +++ b/services/core/java/com/android/server/wm/PinnedStackWindowController.java @@ -106,7 +106,7 @@ public class PinnedStackWindowController extends StackWindowController { } else { // Otherwise, use the display bounds toBounds = new Rect(); - mContainer.getDisplayContent().getLogicalDisplayRect(toBounds); + mContainer.getDisplayContent().getBounds(toBounds); } } else if (fromFullscreen) { schedulePipModeChangedState = SCHEDULE_PIP_MODE_CHANGED_ON_END; diff --git a/services/core/java/com/android/server/wm/ScreenRotationAnimation.java b/services/core/java/com/android/server/wm/ScreenRotationAnimation.java index 70bf15ceb4c3..5a39de5c3242 100644 --- a/services/core/java/com/android/server/wm/ScreenRotationAnimation.java +++ b/services/core/java/com/android/server/wm/ScreenRotationAnimation.java @@ -28,7 +28,6 @@ import static com.android.server.wm.proto.ScreenRotationAnimationProto.STARTED; import android.content.Context; import android.graphics.Matrix; -import android.graphics.PixelFormat; import android.graphics.Rect; import android.util.Slog; import android.util.proto.ProtoOutputStream; @@ -230,7 +229,7 @@ class ScreenRotationAnimation { mService = service; mContext = context; mDisplayContent = displayContent; - displayContent.getLogicalDisplayRect(mOriginalDisplayRect); + displayContent.getBounds(mOriginalDisplayRect); // Screenshot does NOT include rotation! final Display display = displayContent.getDisplay(); @@ -312,7 +311,7 @@ class ScreenRotationAnimation { float x = mTmpFloats[Matrix.MTRANS_X]; float y = mTmpFloats[Matrix.MTRANS_Y]; if (mForceDefaultOrientation) { - mDisplayContent.getLogicalDisplayRect(mCurrentDisplayRect); + mDisplayContent.getBounds(mCurrentDisplayRect); x -= mCurrentDisplayRect.left; y -= mCurrentDisplayRect.top; } diff --git a/services/core/java/com/android/server/wm/StackWindowController.java b/services/core/java/com/android/server/wm/StackWindowController.java index 95c1d536123f..c2a4be55e30a 100644 --- a/services/core/java/com/android/server/wm/StackWindowController.java +++ b/services/core/java/com/android/server/wm/StackWindowController.java @@ -111,8 +111,7 @@ public class StackWindowController } } - public void positionChildAt(TaskWindowContainerController child, int position, Rect bounds, - Configuration overrideConfig) { + public void positionChildAt(TaskWindowContainerController child, int position) { synchronized (mWindowMap) { if (DEBUG_STACK) Slog.i(TAG_WM, "positionChildAt: positioning task=" + child + " at " + position); @@ -126,7 +125,7 @@ public class StackWindowController "positionChildAt: could not find stack for task=" + mContainer); return; } - child.mContainer.positionAt(position, bounds, overrideConfig); + child.mContainer.positionAt(position); mContainer.getDisplayContent().layoutAndAssignWindowLayersIfNeeded(); } } @@ -178,24 +177,22 @@ public class StackWindowController * Re-sizes a stack and its containing tasks. * * @param bounds New stack bounds. Passing in null sets the bounds to fullscreen. - * @param configs Configurations for tasks in the resized stack, keyed by task id. * @param taskBounds Bounds for tasks in the resized stack, keyed by task id. - * @return True if the stack is now fullscreen. + * @param taskTempInsetBounds Inset bounds for individual tasks, keyed by task id. */ - public boolean resize(Rect bounds, SparseArray<Configuration> configs, - SparseArray<Rect> taskBounds, SparseArray<Rect> taskTempInsetBounds) { + public void resize(Rect bounds, SparseArray<Rect> taskBounds, + SparseArray<Rect> taskTempInsetBounds) { synchronized (mWindowMap) { if (mContainer == null) { throw new IllegalArgumentException("resizeStack: stack " + this + " not found."); } // We might trigger a configuration change. Save the current task bounds for freezing. mContainer.prepareFreezingTaskBounds(); - if (mContainer.setBounds(bounds, configs, taskBounds, taskTempInsetBounds) + if (mContainer.setBounds(bounds, taskBounds, taskTempInsetBounds) && mContainer.isVisible()) { mContainer.getDisplayContent().setLayoutNeeded(); mService.mWindowPlacerLocked.performSurfacePlacement(); } - return mContainer.getRawFullscreen(); } } @@ -227,7 +224,7 @@ public class StackWindowController public void getRawBounds(Rect outBounds) { synchronized (mWindowMap) { - if (mContainer.getRawFullscreen()) { + if (mContainer.matchParentBounds()) { outBounds.setEmpty(); } else { mContainer.getRawBounds(outBounds); @@ -275,6 +272,7 @@ public class StackWindowController final Rect parentAppBounds = parentConfig.windowConfiguration.getAppBounds(); + config.windowConfiguration.setBounds(bounds); config.windowConfiguration.setAppBounds(!bounds.isEmpty() ? bounds : null); boolean intersectParentBounds = false; diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java index f70845e52bb9..8aa129a45373 100644 --- a/services/core/java/com/android/server/wm/Task.java +++ b/services/core/java/com/android/server/wm/Task.java @@ -53,12 +53,6 @@ import java.util.function.Consumer; class Task extends WindowContainer<AppWindowToken> { static final String TAG = TAG_WITH_CLASS_NAME ? "Task" : TAG_WM; - // Return value from {@link setBounds} indicating no change was made to the Task bounds. - private static final int BOUNDS_CHANGE_NONE = 0; - // Return value from {@link setBounds} indicating the position of the Task bounds changed. - private static final int BOUNDS_CHANGE_POSITION = 1; - // Return value from {@link setBounds} indicating the size of the Task bounds changed. - private static final int BOUNDS_CHANGE_SIZE = 1 << 1; // TODO: Track parent marks like this in WindowContainer. TaskStack mStack; @@ -67,8 +61,6 @@ class Task extends WindowContainer<AppWindowToken> { private boolean mDeferRemoval = false; final WindowManagerService mService; - // Content limits relative to the DisplayContent this sits in. - private Rect mBounds = new Rect(); final Rect mPreparedFrozenBounds = new Rect(); final Configuration mPreparedFrozenMergedConfig = new Configuration(); @@ -78,13 +70,12 @@ class Task extends WindowContainer<AppWindowToken> { // Device rotation as of the last time {@link #mBounds} was set. private int mRotation; - // Whether mBounds is fullscreen - private boolean mFillsParent = true; - // For comparison with DisplayContent bounds. private Rect mTmpRect = new Rect(); // For handling display rotations. private Rect mTmpRect2 = new Rect(); + // For retrieving dim bounds + private Rect mTmpRect3 = new Rect(); // Resize mode of the task. See {@link ActivityInfo#resizeMode} private int mResizeMode; @@ -108,8 +99,8 @@ class Task extends WindowContainer<AppWindowToken> { private Dimmer mDimmer = new Dimmer(this); private final Rect mTmpDimBoundsRect = new Rect(); - Task(int taskId, TaskStack stack, int userId, WindowManagerService service, Rect bounds, - int resizeMode, boolean supportsPictureInPicture, TaskDescription taskDescription, + Task(int taskId, TaskStack stack, int userId, WindowManagerService service, int resizeMode, + boolean supportsPictureInPicture, TaskDescription taskDescription, TaskWindowContainerController controller) { mTaskId = taskId; mStack = stack; @@ -118,7 +109,7 @@ class Task extends WindowContainer<AppWindowToken> { mResizeMode = resizeMode; mSupportsPictureInPicture = supportsPictureInPicture; setController(controller); - setBounds(bounds, getOverrideConfiguration()); + setBounds(getOverrideBounds()); mTaskDescription = taskDescription; // Tasks have no set orientation value (including SCREEN_ORIENTATION_UNSPECIFIED). @@ -227,9 +218,8 @@ class Task extends WindowContainer<AppWindowToken> { } /** @see com.android.server.am.ActivityManagerService#positionTaskInStack(int, int, int). */ - void positionAt(int position, Rect bounds, Configuration overrideConfig) { + void positionAt(int position) { mStack.positionChildAt(position, this, false /* includingParents */); - resizeLocked(bounds, overrideConfig, false /* force */); } @Override @@ -271,48 +261,37 @@ class Task extends WindowContainer<AppWindowToken> { } } - /** Set the task bounds. Passing in null sets the bounds to fullscreen. */ - // TODO: There is probably not a need to pass in overrideConfig anymore since any change to it - // will be automatically propagated from the AM. Also, mBound is going to be in - // WindowConfiguration long term. - private int setBounds(Rect bounds, Configuration overrideConfig) { - if (overrideConfig == null) { - overrideConfig = EMPTY; + public int setBounds(Rect bounds, boolean forceResize) { + final int boundsChanged = setBounds(bounds); + + if (forceResize && (boundsChanged & BOUNDS_CHANGE_SIZE) != BOUNDS_CHANGE_SIZE) { + onResize(); + return BOUNDS_CHANGE_SIZE | boundsChanged; } - boolean oldFullscreen = mFillsParent; + return boundsChanged; + } + + /** Set the task bounds. Passing in null sets the bounds to fullscreen. */ + @Override + public int setBounds(Rect bounds) { int rotation = Surface.ROTATION_0; final DisplayContent displayContent = mStack.getDisplayContent(); if (displayContent != null) { - displayContent.getLogicalDisplayRect(mTmpRect); rotation = displayContent.getDisplayInfo().rotation; - mFillsParent = bounds == null; - if (mFillsParent) { - bounds = mTmpRect; - } - } - - if (bounds == null) { + } else if (bounds == null) { // Can't set to fullscreen if we don't have a display to get bounds from... return BOUNDS_CHANGE_NONE; } - if (mBounds.equals(bounds) && oldFullscreen == mFillsParent && mRotation == rotation) { - return BOUNDS_CHANGE_NONE; - } - int boundsChange = BOUNDS_CHANGE_NONE; - if (mBounds.left != bounds.left || mBounds.top != bounds.top) { - boundsChange |= BOUNDS_CHANGE_POSITION; - } - if (mBounds.width() != bounds.width() || mBounds.height() != bounds.height()) { - boundsChange |= BOUNDS_CHANGE_SIZE; + if (equivalentOverrideBounds(bounds)) { + return BOUNDS_CHANGE_NONE; } - mBounds.set(bounds); + final int boundsChange = super.setBounds(bounds); mRotation = rotation; - onOverrideConfigurationChanged(overrideConfig); return boundsChange; } @@ -360,28 +339,12 @@ class Task extends WindowContainer<AppWindowToken> { return isResizeable(); } - boolean resizeLocked(Rect bounds, Configuration overrideConfig, boolean forced) { - int boundsChanged = setBounds(bounds, overrideConfig); - if (forced) { - boundsChanged |= BOUNDS_CHANGE_SIZE; - } - if (boundsChanged == BOUNDS_CHANGE_NONE) { - return false; - } - if ((boundsChanged & BOUNDS_CHANGE_SIZE) == BOUNDS_CHANGE_SIZE) { - onResize(); - } else { - onMovedByResize(); - } - return true; - } - /** * Prepares the task bounds to be frozen with the current size. See * {@link AppWindowToken#freezeBounds}. */ void prepareFreezingBounds() { - mPreparedFrozenBounds.set(mBounds); + mPreparedFrozenBounds.set(getBounds()); mPreparedFrozenMergedConfig.setTo(getConfiguration()); } @@ -407,30 +370,30 @@ class Task extends WindowContainer<AppWindowToken> { mTmpRect2.offsetTo(adjustedBounds.left, adjustedBounds.top); } setTempInsetBounds(tempInsetBounds); - resizeLocked(mTmpRect2, getOverrideConfiguration(), false /* forced */); + setBounds(mTmpRect2, false /* forced */); } /** Return true if the current bound can get outputted to the rest of the system as-is. */ private boolean useCurrentBounds() { final DisplayContent displayContent = getDisplayContent(); - return mFillsParent + return matchParentBounds() || !inSplitScreenSecondaryWindowingMode() || displayContent == null || displayContent.getSplitScreenPrimaryStackIgnoringVisibility() != null; } - /** Original bounds of the task if applicable, otherwise fullscreen rect. */ - void getBounds(Rect out) { + @Override + public void getBounds(Rect out) { if (useCurrentBounds()) { // No need to adjust the output bounds if fullscreen or the docked stack is visible // since it is already what we want to represent to the rest of the system. - out.set(mBounds); + super.getBounds(out); return; } // The bounds has been adjusted to accommodate for a docked stack, but the docked stack is // not currently visible. Go ahead a represent it as fullscreen to the rest of the system. - mStack.getDisplayContent().getLogicalDisplayRect(out); + mStack.getDisplayContent().getBounds(out); } /** @@ -490,7 +453,7 @@ class Task extends WindowContainer<AppWindowToken> { return; } - if (!mFillsParent) { + if (!matchParentBounds()) { // When minimizing the docked stack when going home, we don't adjust the task bounds // so we need to intersect the task bounds with the stack bounds here. // @@ -501,11 +464,11 @@ class Task extends WindowContainer<AppWindowToken> { mStack.getBounds(out); } else { mStack.getBounds(mTmpRect); - mTmpRect.intersect(mBounds); + mTmpRect.intersect(getBounds()); } out.set(mTmpRect); } else { - out.set(mBounds); + out.set(getBounds()); } return; } @@ -513,7 +476,7 @@ class Task extends WindowContainer<AppWindowToken> { // The bounds has been adjusted to accommodate for a docked stack, but the docked stack is // not currently visible. Go ahead a represent it as fullscreen to the rest of the system. if (displayContent != null) { - displayContent.getLogicalDisplayRect(out); + displayContent.getBounds(out); } } @@ -541,10 +504,10 @@ class Task extends WindowContainer<AppWindowToken> { if (displayContent == null) { return; } - if (mFillsParent) { + if (matchParentBounds()) { // TODO: Yeah...not sure if this works with WindowConfiguration, but shouldn't be a // problem once we move mBounds into WindowConfiguration. - setBounds(null, getOverrideConfiguration()); + setBounds(null); return; } final int newRotation = displayContent.getDisplayInfo().rotation; @@ -557,18 +520,18 @@ class Task extends WindowContainer<AppWindowToken> { // task bounds so it stays in the same place. // - Rotate the bounds and notify activity manager if the task can be resized independently // from its stack. The stack will take care of task rotation for the other case. - mTmpRect2.set(mBounds); + mTmpRect2.set(getBounds()); if (!getWindowConfiguration().canResizeTask()) { - setBounds(mTmpRect2, getOverrideConfiguration()); + setBounds(mTmpRect2); return; } displayContent.rotateBounds(mRotation, newRotation, mTmpRect2); - if (setBounds(mTmpRect2, getOverrideConfiguration()) != BOUNDS_CHANGE_NONE) { + if (setBounds(mTmpRect2) != BOUNDS_CHANGE_NONE) { final TaskWindowContainerController controller = getController(); if (controller != null) { - controller.requestResize(mBounds, RESIZE_MODE_SYSTEM_SCREEN_ROTATION); + controller.requestResize(getBounds(), RESIZE_MODE_SYSTEM_SCREEN_ROTATION); } } } @@ -632,7 +595,7 @@ class Task extends WindowContainer<AppWindowToken> { boolean isFullscreen() { if (useCurrentBounds()) { - return mFillsParent; + return matchParentBounds(); } // The bounds has been adjusted to accommodate for a docked stack, but the docked stack // is not currently visible. Go ahead a represent it as fullscreen to the rest of the @@ -661,7 +624,7 @@ class Task extends WindowContainer<AppWindowToken> { @Override boolean fillsParent() { - return mFillsParent || !getWindowConfiguration().canResizeTask(); + return matchParentBounds() || !getWindowConfiguration().canResizeTask(); } @Override @@ -711,8 +674,8 @@ class Task extends WindowContainer<AppWindowToken> { final AppWindowToken appWindowToken = mChildren.get(i); appWindowToken.writeToProto(proto, APP_WINDOW_TOKENS, trim); } - proto.write(FILLS_PARENT, mFillsParent); - mBounds.writeToProto(proto, BOUNDS); + proto.write(FILLS_PARENT, matchParentBounds()); + getBounds().writeToProto(proto, BOUNDS); mTempInsetBounds.writeToProto(proto, TEMP_INSET_BOUNDS); proto.end(token); } @@ -721,8 +684,7 @@ class Task extends WindowContainer<AppWindowToken> { final String doublePrefix = prefix + " "; pw.println(prefix + "taskId=" + mTaskId); - pw.println(doublePrefix + "mFillsParent=" + mFillsParent); - pw.println(doublePrefix + "mBounds=" + mBounds.toShortString()); + pw.println(doublePrefix + "mBounds=" + getBounds().toShortString()); pw.println(doublePrefix + "mdr=" + mDeferRemoval); pw.println(doublePrefix + "appTokens=" + mChildren); pw.println(doublePrefix + "mTempInsetBounds=" + mTempInsetBounds.toShortString()); diff --git a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java b/services/core/java/com/android/server/wm/TaskSnapshotSurface.java index e3c7515a0179..41915a32704d 100644 --- a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java +++ b/services/core/java/com/android/server/wm/TaskSnapshotSurface.java @@ -18,9 +18,7 @@ package com.android.server.wm; import static android.graphics.Color.WHITE; import static android.graphics.Color.alpha; -import static android.view.SurfaceControl.HIDDEN; import static android.view.WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM; -import static android.view.WindowManager.LayoutParams.FLAG_DIM_BEHIND; import static android.view.WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED; import static android.view.WindowManager.LayoutParams.FLAG_IGNORE_CHEEK_PRESSES; import static android.view.WindowManager.LayoutParams.FLAG_LOCAL_FOCUS_MODE; diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java index 8a930efea678..4a3a3fc960a5 100644 --- a/services/core/java/com/android/server/wm/TaskStack.java +++ b/services/core/java/com/android/server/wm/TaskStack.java @@ -36,7 +36,6 @@ import static com.android.server.wm.DragResizeMode.DRAG_RESIZE_MODE_DOCKED_DIVID import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TASK_MOVEMENT; import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; -import static com.android.server.wm.WindowManagerService.LAYER_OFFSET_DIM; import static com.android.server.wm.proto.StackProto.ANIMATION_BACKGROUND_SURFACE_IS_DIMMING; import static com.android.server.wm.proto.StackProto.BOUNDS; import static com.android.server.wm.proto.StackProto.FILLS_PARENT; @@ -88,9 +87,6 @@ public class TaskStack extends WindowContainer<Task> implements private Rect mTmpRect2 = new Rect(); private Rect mTmpRect3 = new Rect(); - /** Content limits relative to the DisplayContent this sits in. */ - private Rect mBounds = new Rect(); - /** Stack bounds adjusted to screen content area (taking into account IM windows, etc.) */ private final Rect mAdjustedBounds = new Rect(); @@ -100,9 +96,6 @@ public class TaskStack extends WindowContainer<Task> implements */ private final Rect mFullyAdjustedImeBounds = new Rect(); - /** Whether mBounds is fullscreen */ - private boolean mFillsParent = true; - // Device rotation as of the last time {@link #mBounds} was set. private int mRotation; @@ -180,27 +173,20 @@ public class TaskStack extends WindowContainer<Task> implements /** * Set the bounds of the stack and its containing tasks. * @param stackBounds New stack bounds. Passing in null sets the bounds to fullscreen. - * @param configs Configuration for individual tasks, keyed by task id. * @param taskBounds Bounds for individual tasks, keyed by task id. + * @param taskTempInsetBounds Inset bounds for individual tasks, keyed by task id. * @return True if the stack bounds was changed. * */ boolean setBounds( - Rect stackBounds, SparseArray<Configuration> configs, SparseArray<Rect> taskBounds, - SparseArray<Rect> taskTempInsetBounds) { + Rect stackBounds, SparseArray<Rect> taskBounds, SparseArray<Rect> taskTempInsetBounds) { setBounds(stackBounds); // Update bounds of containing tasks. for (int taskNdx = mChildren.size() - 1; taskNdx >= 0; --taskNdx) { final Task task = mChildren.get(taskNdx); - Configuration config = configs.get(task.mTaskId); - if (config != null) { - Rect bounds = taskBounds.get(task.mTaskId); - task.resizeLocked(bounds, config, false /* forced */); - task.setTempInsetBounds(taskTempInsetBounds != null ? - taskTempInsetBounds.get(task.mTaskId) : null); - } else { - Slog.wtf(TAG_WM, "No config for task: " + task + ", is there a mismatch with AM?"); - } + task.setBounds(taskBounds.get(task.mTaskId), false /* forced */); + task.setTempInsetBounds(taskTempInsetBounds != null ? + taskTempInsetBounds.get(task.mTaskId) : null); } return true; } @@ -227,20 +213,20 @@ public class TaskStack extends WindowContainer<Task> implements final boolean adjusted = !mAdjustedBounds.isEmpty(); Rect insetBounds = null; if (adjusted && isAdjustedForMinimizedDockedStack()) { - insetBounds = mBounds; + insetBounds = getRawBounds(); } else if (adjusted && mAdjustedForIme) { if (mImeGoingAway) { - insetBounds = mBounds; + insetBounds = getRawBounds(); } else { insetBounds = mFullyAdjustedImeBounds; } } - alignTasksToAdjustedBounds(adjusted ? mAdjustedBounds : mBounds, insetBounds); + alignTasksToAdjustedBounds(adjusted ? mAdjustedBounds : getRawBounds(), insetBounds); mDisplayContent.setLayoutNeeded(); } private void alignTasksToAdjustedBounds(Rect adjustedBounds, Rect tempInsetBounds) { - if (mFillsParent) { + if (matchParentBounds()) { return; } @@ -253,13 +239,15 @@ public class TaskStack extends WindowContainer<Task> implements } } - private void setAnimationBackgroundBounds(Rect bounds) { + private void updateAnimationBackgroundBounds() { if (mAnimationBackgroundSurface == null) { return; } + getRawBounds(mTmpRect); // TODO: Should be in relative coordinates. - getPendingTransaction().setSize(mAnimationBackgroundSurface, bounds.width(), bounds.height()) - .setPosition(mAnimationBackgroundSurface, bounds.left, bounds.top); + getPendingTransaction().setSize(mAnimationBackgroundSurface, mTmpRect.width(), + mTmpRect.height()).setPosition(mAnimationBackgroundSurface, mTmpRect.left, + mTmpRect.top); scheduleAnimation(); } @@ -283,50 +271,53 @@ public class TaskStack extends WindowContainer<Task> implements scheduleAnimation(); } - private boolean setBounds(Rect bounds) { - boolean oldFullscreen = mFillsParent; + @Override + public int setBounds(Rect bounds) { + return setBounds(getOverrideBounds(), bounds); + } + + private int setBounds(Rect existing, Rect bounds) { int rotation = Surface.ROTATION_0; int density = DENSITY_DPI_UNDEFINED; if (mDisplayContent != null) { - mDisplayContent.getLogicalDisplayRect(mTmpRect); + mDisplayContent.getBounds(mTmpRect); rotation = mDisplayContent.getDisplayInfo().rotation; density = mDisplayContent.getDisplayInfo().logicalDensityDpi; - mFillsParent = bounds == null; - if (mFillsParent) { - bounds = mTmpRect; - } } - if (bounds == null) { - // Can't set to fullscreen if we don't have a display to get bounds from... - return false; - } - if (mBounds.equals(bounds) && oldFullscreen == mFillsParent && mRotation == rotation) { - return false; + if (equivalentBounds(existing, bounds) && mRotation == rotation) { + return BOUNDS_CHANGE_NONE; } - setAnimationBackgroundBounds(bounds); + final int result = super.setBounds(bounds); + + if (mDisplayContent != null) { + updateAnimationBackgroundBounds(); + } - mBounds.set(bounds); mRotation = rotation; mDensity = density; updateAdjustedBounds(); - return true; + return result; } /** Bounds of the stack without adjusting for other factors in the system like visibility * of docked stack. - * Most callers should be using {@link #getBounds} as it take into consideration other system - * factors. */ + * Most callers should be using {@link ConfigurationContainer#getOverrideBounds} as it take into + * consideration other system factors. */ void getRawBounds(Rect out) { - out.set(mBounds); + out.set(getRawBounds()); + } + + Rect getRawBounds() { + return super.getBounds(); } /** Return true if the current bound can get outputted to the rest of the system as-is. */ private boolean useCurrentBounds() { - if (mFillsParent + if (matchParentBounds() || !inSplitScreenSecondaryWindowingMode() || mDisplayContent == null || mDisplayContent.getSplitScreenPrimaryStack() != null) { @@ -335,24 +326,29 @@ public class TaskStack extends WindowContainer<Task> implements return false; } - public void getBounds(Rect out) { + @Override + public void getBounds(Rect bounds) { + bounds.set(getBounds()); + } + + @Override + public Rect getBounds() { if (useCurrentBounds()) { // If we're currently adjusting for IME or minimized docked stack, we use the adjusted // bounds; otherwise, no need to adjust the output bounds if fullscreen or the docked // stack is visible since it is already what we want to represent to the rest of the // system. if (!mAdjustedBounds.isEmpty()) { - out.set(mAdjustedBounds); + return mAdjustedBounds; } else { - out.set(mBounds); + return super.getBounds(); } - return; } // The bounds has been adjusted to accommodate for a docked stack, but the docked stack // is not currently visible. Go ahead a represent it as fullscreen to the rest of the // system. - mDisplayContent.getLogicalDisplayRect(out); + return mDisplayContent.getBounds(); } /** @@ -373,7 +369,7 @@ public class TaskStack extends WindowContainer<Task> implements mBoundsAnimationSourceHintBounds.setEmpty(); } - mPreAnimationBounds.set(mBounds); + mPreAnimationBounds.set(getRawBounds()); } /** @@ -418,12 +414,12 @@ public class TaskStack extends WindowContainer<Task> implements if (bounds != null) { setBounds(bounds); return; - } else if (mFillsParent) { + } else if (matchParentBounds()) { setBounds(null); return; } - mTmpRect2.set(mBounds); + mTmpRect2.set(getRawBounds()); final int newRotation = mDisplayContent.getDisplayInfo().rotation; final int newDensity = mDisplayContent.getDisplayInfo().logicalDensityDpi; if (mRotation == newRotation && mDensity == newDensity) { @@ -466,14 +462,14 @@ public class TaskStack extends WindowContainer<Task> implements return false; } - if (mFillsParent) { + if (matchParentBounds()) { // Update stack bounds again since rotation changed since updateDisplayInfo(). setBounds(null); // Return false since we don't need the client to resize. return false; } - mTmpRect2.set(mBounds); + mTmpRect2.set(getRawBounds()); mDisplayContent.rotateBounds(mRotation, newRotation, mTmpRect2); if (inSplitScreenPrimaryWindowingMode()) { repositionPrimarySplitScreenStackAfterRotation(mTmpRect2); @@ -510,7 +506,7 @@ public class TaskStack extends WindowContainer<Task> implements if (mDisplayContent.getDockedDividerController().canPrimaryStackDockTo(dockSide)) { return; } - mDisplayContent.getLogicalDisplayRect(mTmpRect); + mDisplayContent.getBounds(mTmpRect); dockSide = DockedDividerUtils.invertDockSide(dockSide); switch (dockSide) { case DOCKED_LEFT: @@ -755,7 +751,7 @@ public class TaskStack extends WindowContainer<Task> implements // not fullscreen. If it's fullscreen, it means that we are in the transition of // dismissing it, so we must not resize this stack. bounds = new Rect(); - mDisplayContent.getLogicalDisplayRect(mTmpRect); + mDisplayContent.getBounds(mTmpRect); mTmpRect2.setEmpty(); if (splitScreenStack != null) { splitScreenStack.getRawBounds(mTmpRect2); @@ -818,7 +814,7 @@ public class TaskStack extends WindowContainer<Task> implements } if (!inSplitScreenWindowingMode() || mDisplayContent == null) { - outStackBounds.set(mBounds); + outStackBounds.set(getRawBounds()); return; } @@ -833,7 +829,7 @@ public class TaskStack extends WindowContainer<Task> implements // The docked stack is being dismissed, but we caught before it finished being // dismissed. In that case we want to treat it as if it is not occupying any space and // let others occupy the whole display. - mDisplayContent.getLogicalDisplayRect(outStackBounds); + mDisplayContent.getBounds(outStackBounds); return; } @@ -841,11 +837,11 @@ public class TaskStack extends WindowContainer<Task> implements if (dockedSide == DOCKED_INVALID) { // Not sure how you got here...Only thing we can do is return current bounds. Slog.e(TAG_WM, "Failed to get valid docked side for docked stack=" + dockedStack); - outStackBounds.set(mBounds); + outStackBounds.set(getRawBounds()); return; } - mDisplayContent.getLogicalDisplayRect(mTmpRect); + mDisplayContent.getBounds(mTmpRect); dockedStack.getRawBounds(mTmpRect2); final boolean dockedOnTopOrLeft = dockedSide == DOCKED_TOP || dockedSide == DOCKED_LEFT; getStackDockedModeBounds(mTmpRect, outStackBounds, mTmpRect2, @@ -1146,14 +1142,14 @@ public class TaskStack extends WindowContainer<Task> implements // occluded by IME. We shift its bottom up by the height of the IME, but // leaves at least 30% of the top stack visible. final int minTopStackBottom = - getMinTopStackBottom(displayContentRect, mBounds.bottom); + getMinTopStackBottom(displayContentRect, getRawBounds().bottom); final int bottom = Math.max( - mBounds.bottom - yOffset + dividerWidth - dividerWidthInactive, + getRawBounds().bottom - yOffset + dividerWidth - dividerWidthInactive, minTopStackBottom); - mTmpAdjustedBounds.set(mBounds); - mTmpAdjustedBounds.bottom = - (int) (mAdjustImeAmount * bottom + (1 - mAdjustImeAmount) * mBounds.bottom); - mFullyAdjustedImeBounds.set(mBounds); + mTmpAdjustedBounds.set(getRawBounds()); + mTmpAdjustedBounds.bottom = (int) (mAdjustImeAmount * bottom + (1 - mAdjustImeAmount) + * getRawBounds().bottom); + mFullyAdjustedImeBounds.set(getRawBounds()); } else { // When the stack is on bottom and has no focus, it's only adjusted for divider width. final int dividerWidthDelta = dividerWidthInactive - dividerWidth; @@ -1163,22 +1159,24 @@ public class TaskStack extends WindowContainer<Task> implements // We try to move it up by the height of the IME window, but only to the extent // that leaves at least 30% of the top stack visible. // 'top' is where the top of bottom stack will move to in this case. - final int topBeforeImeAdjust = mBounds.top - dividerWidth + dividerWidthInactive; + final int topBeforeImeAdjust = + getRawBounds().top - dividerWidth + dividerWidthInactive; final int minTopStackBottom = - getMinTopStackBottom(displayContentRect, mBounds.top - dividerWidth); + getMinTopStackBottom(displayContentRect, + getRawBounds().top - dividerWidth); final int top = Math.max( - mBounds.top - yOffset, minTopStackBottom + dividerWidthInactive); + getRawBounds().top - yOffset, minTopStackBottom + dividerWidthInactive); - mTmpAdjustedBounds.set(mBounds); + mTmpAdjustedBounds.set(getRawBounds()); // Account for the adjustment for IME and divider width separately. // (top - topBeforeImeAdjust) is the amount of movement due to IME only, // and dividerWidthDelta is due to divider width change only. - mTmpAdjustedBounds.top = mBounds.top + + mTmpAdjustedBounds.top = getRawBounds().top + (int) (mAdjustImeAmount * (top - topBeforeImeAdjust) + mAdjustDividerAmount * dividerWidthDelta); - mFullyAdjustedImeBounds.set(mBounds); + mFullyAdjustedImeBounds.set(getRawBounds()); mFullyAdjustedImeBounds.top = top; - mFullyAdjustedImeBounds.bottom = top + mBounds.height(); + mFullyAdjustedImeBounds.bottom = top + getRawBounds().height(); } return true; } @@ -1192,21 +1190,21 @@ public class TaskStack extends WindowContainer<Task> implements if (dockSide == DOCKED_TOP) { mService.getStableInsetsLocked(DEFAULT_DISPLAY, mTmpRect); int topInset = mTmpRect.top; - mTmpAdjustedBounds.set(mBounds); - mTmpAdjustedBounds.bottom = - (int) (minimizeAmount * topInset + (1 - minimizeAmount) * mBounds.bottom); + mTmpAdjustedBounds.set(getRawBounds()); + mTmpAdjustedBounds.bottom = (int) (minimizeAmount * topInset + (1 - minimizeAmount) + * getRawBounds().bottom); } else if (dockSide == DOCKED_LEFT) { - mTmpAdjustedBounds.set(mBounds); - final int width = mBounds.width(); + mTmpAdjustedBounds.set(getRawBounds()); + final int width = getRawBounds().width(); mTmpAdjustedBounds.right = (int) (minimizeAmount * mDockedStackMinimizeThickness - + (1 - minimizeAmount) * mBounds.right); + + (1 - minimizeAmount) * getRawBounds().right); mTmpAdjustedBounds.left = mTmpAdjustedBounds.right - width; } else if (dockSide == DOCKED_RIGHT) { - mTmpAdjustedBounds.set(mBounds); - mTmpAdjustedBounds.left = - (int) (minimizeAmount * (mBounds.right - mDockedStackMinimizeThickness) - + (1 - minimizeAmount) * mBounds.left); + mTmpAdjustedBounds.set(getRawBounds()); + mTmpAdjustedBounds.left = (int) (minimizeAmount * + (getRawBounds().right - mDockedStackMinimizeThickness) + + (1 - minimizeAmount) * getRawBounds().left); } return true; } @@ -1228,9 +1226,9 @@ public class TaskStack extends WindowContainer<Task> implements if (dockSide == DOCKED_TOP) { mService.getStableInsetsLocked(DEFAULT_DISPLAY, mTmpRect); int topInset = mTmpRect.top; - return mBounds.bottom - topInset; + return getRawBounds().bottom - topInset; } else if (dockSide == DOCKED_LEFT || dockSide == DOCKED_RIGHT) { - return mBounds.width() - mDockedStackMinimizeThickness; + return getRawBounds().width() - mDockedStackMinimizeThickness; } else { return 0; } @@ -1264,11 +1262,12 @@ public class TaskStack extends WindowContainer<Task> implements return; } - final Rect insetBounds = mImeGoingAway ? mBounds : mFullyAdjustedImeBounds; + final Rect insetBounds = mImeGoingAway ? getRawBounds() : mFullyAdjustedImeBounds; task.alignToAdjustedBounds(mAdjustedBounds, insetBounds, getDockSide() == DOCKED_TOP); mDisplayContent.setLayoutNeeded(); } + boolean isAdjustedForMinimizedDockedStack() { return mMinimizeAmount != 0f; } @@ -1282,8 +1281,8 @@ public class TaskStack extends WindowContainer<Task> implements for (int taskNdx = mChildren.size() - 1; taskNdx >= 0; taskNdx--) { mChildren.get(taskNdx).writeToProto(proto, TASKS, trim); } - proto.write(FILLS_PARENT, mFillsParent); - mBounds.writeToProto(proto, BOUNDS); + proto.write(FILLS_PARENT, matchParentBounds()); + getRawBounds().writeToProto(proto, BOUNDS); proto.write(ANIMATION_BACKGROUND_SURFACE_IS_DIMMING, mAnimationBackgroundSurfaceIsShown); proto.end(token); } @@ -1291,8 +1290,7 @@ public class TaskStack extends WindowContainer<Task> implements public void dump(String prefix, PrintWriter pw) { pw.println(prefix + "mStackId=" + mStackId); pw.println(prefix + "mDeferRemoval=" + mDeferRemoval); - pw.println(prefix + "mFillsParent=" + mFillsParent); - pw.println(prefix + "mBounds=" + mBounds.toShortString()); + pw.println(prefix + "mBounds=" + getRawBounds().toShortString()); if (mMinimizeAmount != 0f) { pw.println(prefix + "mMinimizeAmount=" + mMinimizeAmount); } @@ -1323,18 +1321,10 @@ public class TaskStack extends WindowContainer<Task> implements } } - /** Fullscreen status of the stack without adjusting for other factors in the system like - * visibility of docked stack. - * Most callers should be using {@link #fillsParent} as it take into consideration other - * system factors. */ - boolean getRawFullscreen() { - return mFillsParent; - } - @Override boolean fillsParent() { if (useCurrentBounds()) { - return mFillsParent; + return matchParentBounds(); } // The bounds has been adjusted to accommodate for a docked stack, but the docked stack // is not currently visible. Go ahead a represent it as fullscreen to the rest of the @@ -1360,7 +1350,7 @@ public class TaskStack extends WindowContainer<Task> implements * information which side of the screen was the dock anchored. */ int getDockSide() { - return getDockSide(mBounds); + return getDockSide(getRawBounds()); } private int getDockSide(Rect bounds) { @@ -1370,7 +1360,7 @@ public class TaskStack extends WindowContainer<Task> implements if (mDisplayContent == null) { return DOCKED_INVALID; } - mDisplayContent.getLogicalDisplayRect(mTmpRect); + mDisplayContent.getBounds(mTmpRect); final int orientation = mDisplayContent.getConfiguration().orientation; return getDockSideUnchecked(bounds, mTmpRect, orientation); } @@ -1490,7 +1480,7 @@ public class TaskStack extends WindowContainer<Task> implements */ if (task.isActivityTypeHome() && isMinimizedDockAndHomeStackResizable()) { - mDisplayContent.getLogicalDisplayRect(mTmpRect); + mDisplayContent.getBounds(mTmpRect); } else { task.getDimBounds(mTmpRect); } diff --git a/services/core/java/com/android/server/wm/TaskWindowContainerController.java b/services/core/java/com/android/server/wm/TaskWindowContainerController.java index b3bb0b7e001d..5caae32dbeb4 100644 --- a/services/core/java/com/android/server/wm/TaskWindowContainerController.java +++ b/services/core/java/com/android/server/wm/TaskWindowContainerController.java @@ -18,7 +18,6 @@ package com.android.server.wm; import android.app.ActivityManager.TaskDescription; import android.app.ActivityManager.TaskSnapshot; -import android.content.res.Configuration; import android.graphics.Rect; import android.os.Handler; import android.os.Looper; @@ -30,6 +29,7 @@ import com.android.internal.annotations.VisibleForTesting; import java.lang.ref.WeakReference; import static com.android.server.EventLogTags.WM_TASK_CREATED; +import static com.android.server.wm.ConfigurationContainer.BOUNDS_CHANGE_NONE; import static com.android.server.wm.DragResizeMode.DRAG_RESIZE_MODE_DOCKED_DIVIDER; import static com.android.server.wm.WindowContainer.POSITION_BOTTOM; import static com.android.server.wm.WindowContainer.POSITION_TOP; @@ -75,7 +75,7 @@ public class TaskWindowContainerController + stackController); } EventLog.writeEvent(WM_TASK_CREATED, taskId, stack.mStackId); - final Task task = createTask(taskId, stack, userId, bounds, resizeMode, + final Task task = createTask(taskId, stack, userId, resizeMode, supportsPictureInPicture, taskDescription); final int position = toTop ? POSITION_TOP : POSITION_BOTTOM; // We only want to move the parents to the parents if we are creating this task at the @@ -85,10 +85,10 @@ public class TaskWindowContainerController } @VisibleForTesting - Task createTask(int taskId, TaskStack stack, int userId, Rect bounds, int resizeMode, + Task createTask(int taskId, TaskStack stack, int userId, int resizeMode, boolean supportsPictureInPicture, TaskDescription taskDescription) { - return new Task(taskId, stack, userId, mService, bounds, resizeMode, - supportsPictureInPicture, taskDescription, this); + return new Task(taskId, stack, userId, mService, resizeMode, supportsPictureInPicture, + taskDescription, this); } @Override @@ -151,14 +151,14 @@ public class TaskWindowContainerController } } - public void resize(Rect bounds, Configuration overrideConfig, boolean relayout, - boolean forced) { + public void resize(boolean relayout, boolean forced) { synchronized (mWindowMap) { if (mContainer == null) { throw new IllegalArgumentException("resizeTask: taskId " + mTaskId + " not found."); } - if (mContainer.resizeLocked(bounds, overrideConfig, forced) && relayout) { + if (mContainer.setBounds(mContainer.getOverrideBounds(), forced) != BOUNDS_CHANGE_NONE + && relayout) { mContainer.getDisplayContent().layoutAndAssignWindowLayersIfNeeded(); } } diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java index a5e62884a9fb..610453e6e92b 100644 --- a/services/core/java/com/android/server/wm/WindowContainer.java +++ b/services/core/java/com/android/server/wm/WindowContainer.java @@ -318,11 +318,24 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer< * @see #mFullConfiguration */ @Override - final public void onOverrideConfigurationChanged(Configuration overrideConfiguration) { + public void onOverrideConfigurationChanged(Configuration overrideConfiguration) { + // We must diff before the configuration is applied so that we can capture the change + // against the existing bounds. + final int diff = diffOverrideBounds(overrideConfiguration.windowConfiguration.getBounds()); super.onOverrideConfigurationChanged(overrideConfiguration); if (mParent != null) { mParent.onDescendantOverrideConfigurationChanged(); } + + if (diff == BOUNDS_CHANGE_NONE) { + return; + } + + if ((diff & BOUNDS_CHANGE_SIZE) == BOUNDS_CHANGE_SIZE) { + onResize(); + } else { + onMovedByResize(); + } } /** diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index d88cf4dad14f..1cd40806619f 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -126,7 +126,6 @@ import android.app.AppOpsManager; import android.app.IActivityManager; import android.app.IAssistDataReceiver; import android.content.BroadcastReceiver; -import android.content.ClipData; import android.content.ContentResolver; import android.content.Context; import android.content.Intent; @@ -5517,7 +5516,7 @@ public class WindowManagerService extends IWindowManager.Stub } void reconfigureDisplayLocked(@NonNull DisplayContent displayContent) { - if (!mDisplayReady) { + if (!displayContent.isReady()) { return; } displayContent.configureDisplayPolicy(); diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index e53fccf3e943..90e9c230b501 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -814,7 +814,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP layoutXDiff = 0; layoutYDiff = 0; } else { - getContainerBounds(mContainingFrame); + getBounds(mContainingFrame); if (mAppToken != null && !mAppToken.mFrozenBounds.isEmpty()) { // If the bounds are frozen, we still want to translate the window freely and only @@ -972,7 +972,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP mContentInsets.setEmpty(); mVisibleInsets.setEmpty(); } else { - getDisplayContent().getLogicalDisplayRect(mTmpRect); + getDisplayContent().getBounds(mTmpRect); // Override right and/or bottom insets in case if the frame doesn't fit the screen in // non-fullscreen mode. boolean overrideRightInset = !windowsAreFloating && !inFullscreenContainer @@ -1044,6 +1044,18 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP + " of=" + mOutsets.toShortString()); } + // TODO: Look into whether this override is still necessary. + @Override + public Rect getBounds() { + if (isInMultiWindowMode()) { + return getTask().getBounds(); + } else if (mAppToken != null){ + return mAppToken.getBounds(); + } else { + return super.getBounds(); + } + } + @Override public Rect getFrameLw() { return mFrame; @@ -2951,33 +2963,12 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP /** Is this window in a container that takes up the entire screen space? */ private boolean inFullscreenContainer() { - if (mAppToken == null) { - return true; - } - if (mAppToken.hasBounds()) { - return false; - } - return !isInMultiWindowMode(); + return mAppToken == null || (mAppToken.matchParentBounds() && !isInMultiWindowMode()); } /** @return true when the window is in fullscreen task, but has non-fullscreen bounds set. */ boolean isLetterboxedAppWindow() { - final Task task = getTask(); - final boolean taskIsFullscreen = task != null && task.isFullscreen(); - final boolean appWindowIsFullscreen = mAppToken != null && !mAppToken.hasBounds(); - - return taskIsFullscreen && !appWindowIsFullscreen; - } - - /** Returns the appropriate bounds to use for computing frames. */ - private void getContainerBounds(Rect outBounds) { - if (isInMultiWindowMode()) { - getTask().getBounds(outBounds); - } else if (mAppToken != null){ - mAppToken.getBounds(outBounds); - } else { - outBounds.setEmpty(); - } + return !isInMultiWindowMode() && mAppToken != null && !mAppToken.matchParentBounds(); } boolean isDragResizeChanged() { diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java index d11b0dbcc130..d2b37481a429 100644 --- a/services/core/java/com/android/server/wm/WindowStateAnimator.java +++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java @@ -1971,7 +1971,7 @@ class WindowStateAnimator { final float width = w.mFrame.width(); final float height = w.mFrame.height(); - mService.getDefaultDisplayContentLocked().getLogicalDisplayRect(displayRect); + mService.getDefaultDisplayContentLocked().getBounds(displayRect); final float displayWidth = displayRect.width(); final float displayHeight = displayRect.height(); diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityRecordTests.java b/services/tests/servicestests/src/com/android/server/am/ActivityRecordTests.java index d90e284d44a0..ee45595f9a87 100644 --- a/services/tests/servicestests/src/com/android/server/am/ActivityRecordTests.java +++ b/services/tests/servicestests/src/com/android/server/am/ActivityRecordTests.java @@ -37,7 +37,6 @@ import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; -import android.content.ComponentName; import android.graphics.Rect; import android.platform.test.annotations.Presubmit; import android.support.test.filters.MediumTest; diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityStarterTests.java b/services/tests/servicestests/src/com/android/server/am/ActivityStarterTests.java index bc503c49a99a..b4919b6f9c52 100644 --- a/services/tests/servicestests/src/com/android/server/am/ActivityStarterTests.java +++ b/services/tests/servicestests/src/com/android/server/am/ActivityStarterTests.java @@ -28,7 +28,6 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED; import android.app.ActivityOptions; import android.app.IApplicationThread; -import android.content.ComponentName; import android.content.Intent; import android.content.pm.ActivityInfo; import android.content.pm.ApplicationInfo; @@ -108,8 +107,8 @@ public class ActivityStarterTests extends ActivityTestsBase { final Rect bounds = new Rect(10, 10, 100, 100); mStarter.updateBounds(task, bounds); - assertEquals(task.mBounds, bounds); - assertEquals(task.getStack().mBounds, null); + assertEquals(task.getOverrideBounds(), bounds); + assertEquals(new Rect(), task.getStack().getOverrideBounds()); // When in a resizeable stack, the stack bounds should be updated as well. final TaskRecord task2 = new TaskBuilder(mService.mStackSupervisor) @@ -124,10 +123,10 @@ public class ActivityStarterTests extends ActivityTestsBase { // In the case of no animation, the stack and task bounds should be set immediately. if (!ANIMATE) { - assertEquals(task2.getStack().mBounds, bounds); - assertEquals(task2.mBounds, bounds); + assertEquals(task2.getStack().getOverrideBounds(), bounds); + assertEquals(task2.getOverrideBounds(), bounds); } else { - assertEquals(task2.mBounds, null); + assertEquals(task2.getOverrideBounds(), new Rect()); } } diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java b/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java index 9683e229d50f..2fffb892c5f0 100644 --- a/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java +++ b/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java @@ -19,6 +19,7 @@ package com.android.server.am; 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 org.mockito.Mockito.mock; import static org.mockito.Mockito.doNothing; @@ -415,6 +416,12 @@ public class ActivityTestsBase { @Override protected T createStackWindowController(int displayId, boolean onTop, Rect outBounds) { mContainerController = (T) WindowTestUtils.createMockStackWindowContainerController(); + + // 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); + } return mContainerController; } diff --git a/services/tests/servicestests/src/com/android/server/am/LaunchingTaskPositionerTests.java b/services/tests/servicestests/src/com/android/server/am/LaunchingTaskPositionerTests.java index 01e2da61f0d4..13daf3e94508 100644 --- a/services/tests/servicestests/src/com/android/server/am/LaunchingTaskPositionerTests.java +++ b/services/tests/servicestests/src/com/android/server/am/LaunchingTaskPositionerTests.java @@ -16,7 +16,6 @@ package com.android.server.am; -import android.content.ComponentName; import android.content.pm.ActivityInfo.WindowLayout; import android.graphics.Rect; import android.platform.test.annotations.Presubmit; @@ -93,8 +92,8 @@ public class LaunchingTaskPositionerTests extends ActivityTestsBase { */ @Test public void testInitialBounds() throws Exception { - assertEquals(mStack.mBounds, STACK_BOUNDS); - assertEquals(mTask.mBounds, null); + assertEquals(mStack.getOverrideBounds(), STACK_BOUNDS); + assertEquals(mTask.getOverrideBounds(), new Rect()); } /** @@ -182,7 +181,7 @@ public class LaunchingTaskPositionerTests extends ActivityTestsBase { mService.mStackSupervisor.getLaunchingBoundsController().layoutTask(mTask, layout); // Second task will be laid out on top of the first so starting bounds is the same. - final Rect expectedBounds = new Rect(mTask.mBounds); + final Rect expectedBounds = new Rect(mTask.getOverrideBounds()); ActivityRecord activity = null; TaskRecord secondTask = null; @@ -203,14 +202,16 @@ public class LaunchingTaskPositionerTests extends ActivityTestsBase { if ((gravity & (Gravity.TOP | Gravity.RIGHT)) == (Gravity.TOP | Gravity.RIGHT) || (gravity & (Gravity.BOTTOM | Gravity.RIGHT)) == (Gravity.BOTTOM | Gravity.RIGHT)) { - expectedBounds.offset(-LaunchingTaskPositioner.getHorizontalStep(mStack.mBounds), - 0); + expectedBounds.offset(-LaunchingTaskPositioner.getHorizontalStep( + mStack.getOverrideBounds()), 0); } else if ((gravity & Gravity.TOP) == Gravity.TOP || (gravity & Gravity.BOTTOM) == Gravity.BOTTOM) { - expectedBounds.offset(LaunchingTaskPositioner.getHorizontalStep(mStack.mBounds), 0); + expectedBounds.offset( + LaunchingTaskPositioner.getHorizontalStep(mStack.getOverrideBounds()), 0); } else { - expectedBounds.offset(LaunchingTaskPositioner.getHorizontalStep(mStack.mBounds), - LaunchingTaskPositioner.getVerticalStep(mStack.mBounds)); + expectedBounds.offset( + LaunchingTaskPositioner.getHorizontalStep(mStack.getOverrideBounds()), + LaunchingTaskPositioner.getVerticalStep(mStack.getOverrideBounds())); } assertEquals(mResult, expectedBounds); @@ -228,10 +229,12 @@ public class LaunchingTaskPositionerTests extends ActivityTestsBase { private Rect getDefaultBounds(int gravity) { final Rect bounds = new Rect(); - bounds.set(mStack.mBounds); + bounds.set(mStack.getOverrideBounds()); - final int verticalInset = LaunchingTaskPositioner.getFreeformStartTop(mStack.mBounds); - final int horizontalInset = LaunchingTaskPositioner.getFreeformStartLeft(mStack.mBounds); + final int verticalInset = + LaunchingTaskPositioner.getFreeformStartTop(mStack.getOverrideBounds()); + final int horizontalInset = + LaunchingTaskPositioner.getFreeformStartLeft(mStack.getOverrideBounds()); bounds.inset(horizontalInset, verticalInset); diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowFrameTests.java b/services/tests/servicestests/src/com/android/server/wm/WindowFrameTests.java index 5d2bb4d92620..503e1ac4563d 100644 --- a/services/tests/servicestests/src/com/android/server/wm/WindowFrameTests.java +++ b/services/tests/servicestests/src/com/android/server/wm/WindowFrameTests.java @@ -21,7 +21,7 @@ import org.junit.Test; import org.junit.runner.RunWith; import android.app.ActivityManager.TaskDescription; -import android.content.Context; +import android.content.res.Configuration; import android.graphics.Rect; import android.platform.test.annotations.Presubmit; import android.support.test.InstrumentationRegistry; @@ -75,11 +75,23 @@ public class WindowFrameTests extends WindowTestsBase { final Rect mInsetBounds = new Rect(); boolean mFullscreenForTest = true; TaskWithBounds(Rect bounds) { - super(0, mStubStack, 0, sWm, null, 0, false, new TaskDescription(), null); + super(0, mStubStack, 0, sWm, 0, false, new TaskDescription(), null); mBounds = bounds; + setBounds(bounds); } + + @Override + public Rect getBounds() { + return mBounds; + } + + @Override + public void getBounds(Rect out) { + out.set(mBounds); + } + @Override - void getBounds(Rect outBounds) { + public void getOverrideBounds(Rect outBounds) { outBounds.set(mBounds); } @Override @@ -395,7 +407,9 @@ public class WindowFrameTests extends WindowTestsBase { final int xInset = logicalWidth / 10; final int yInset = logicalWidth / 10; final Rect cf = new Rect(xInset, yInset, logicalWidth - xInset, logicalHeight - yInset); - w.mAppToken.onOverrideConfigurationChanged(w.mAppToken.getOverrideConfiguration(), cf); + Configuration config = new Configuration(w.mAppToken.getOverrideConfiguration()); + config.windowConfiguration.setBounds(cf); + w.mAppToken.onOverrideConfigurationChanged(config); pf.set(0, 0, logicalWidth, logicalHeight); task.mFullscreenForTest = true; diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowTestUtils.java b/services/tests/servicestests/src/com/android/server/wm/WindowTestUtils.java index 1aafac66bae4..b2334e848d4d 100644 --- a/services/tests/servicestests/src/com/android/server/wm/WindowTestUtils.java +++ b/services/tests/servicestests/src/com/android/server/wm/WindowTestUtils.java @@ -29,11 +29,17 @@ import android.view.WindowManager; import static android.app.AppOpsManager.OP_NONE; import static android.content.pm.ActivityInfo.RESIZE_MODE_UNRESIZEABLE; import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; -import static android.content.res.Configuration.EMPTY; + import static com.android.server.wm.WindowContainer.POSITION_TOP; +import static org.mockito.Mockito.any; +import static org.mockito.Mockito.anyBoolean; +import static org.mockito.Mockito.anyFloat; +import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; +import org.mockito.invocation.InvocationOnMock; + /** * A collection of static functions that can be referenced by other test packages to provide access * to WindowManager related test functionality. @@ -64,13 +70,24 @@ public class WindowTestUtils { public static StackWindowController createMockStackWindowContainerController() { StackWindowController controller = mock(StackWindowController.class); controller.mContainer = mock(TestTaskStack.class); + + // many components rely on the {@link StackWindowController#adjustConfigurationForBounds} + // to properly set bounds values in the configuration. We must mimick those actions here. + doAnswer((InvocationOnMock invocationOnMock) -> { + final Configuration config = invocationOnMock.<Configuration>getArgument(7); + final Rect bounds = invocationOnMock.<Rect>getArgument(0); + config.windowConfiguration.setBounds(bounds); + return null; + }).when(controller).adjustConfigurationForBounds(any(), any(), any(), any(), + anyBoolean(), anyBoolean(), anyFloat(), any(), any()); + return controller; } /** Creates a {@link Task} and adds it to the specified {@link TaskStack}. */ public static Task createTaskInStack(WindowManagerService service, TaskStack stack, int userId) { - final Task newTask = new Task(sNextTaskId++, stack, userId, service, null, 0, false, + final Task newTask = new Task(sNextTaskId++, stack, userId, service, 0, false, new ActivityManager.TaskDescription(), null); stack.addTask(newTask, POSITION_TOP); return newTask; @@ -98,17 +115,17 @@ public class WindowTestUtils { TestAppWindowToken(DisplayContent dc) { super(dc.mService, new IApplicationToken.Stub() { public String getName() {return null;} - }, false, dc, true /* fillsParent */, null /* bounds */); + }, false, dc, true /* fillsParent */); } TestAppWindowToken(WindowManagerService service, IApplicationToken token, boolean voiceInteraction, DisplayContent dc, long inputDispatchingTimeoutNanos, boolean fullscreen, boolean showForAllUsers, int targetSdk, int orientation, int rotationAnimationHint, int configChanges, boolean launchTaskBehind, - boolean alwaysFocusable, AppWindowContainerController controller, Rect bounds) { + boolean alwaysFocusable, AppWindowContainerController controller) { super(service, token, voiceInteraction, dc, inputDispatchingTimeoutNanos, fullscreen, showForAllUsers, targetSdk, orientation, rotationAnimationHint, configChanges, - launchTaskBehind, alwaysFocusable, controller, bounds); + launchTaskBehind, alwaysFocusable, controller); } int getWindowsCount() { @@ -175,10 +192,10 @@ public class WindowTestUtils { private boolean mUseLocalIsAnimating = false; private boolean mIsAnimating = false; - TestTask(int taskId, TaskStack stack, int userId, WindowManagerService service, Rect bounds, + TestTask(int taskId, TaskStack stack, int userId, WindowManagerService service, int resizeMode, boolean supportsPictureInPicture, TaskWindowContainerController controller) { - super(taskId, stack, userId, service, bounds, resizeMode, supportsPictureInPicture, + super(taskId, stack, userId, service, resizeMode, supportsPictureInPicture, new ActivityManager.TaskDescription(), controller); } @@ -247,9 +264,9 @@ public class WindowTestUtils { } @Override - TestTask createTask(int taskId, TaskStack stack, int userId, Rect bounds, int resizeMode, + TestTask createTask(int taskId, TaskStack stack, int userId, int resizeMode, boolean supportsPictureInPicture, ActivityManager.TaskDescription taskDescription) { - return new TestTask(taskId, stack, userId, mService, bounds, resizeMode, + return new TestTask(taskId, stack, userId, mService, resizeMode, supportsPictureInPicture, this); } } @@ -269,8 +286,7 @@ public class WindowTestUtils { true /* showForAllUsers */, 0 /* configChanges */, false /* voiceInteraction */, false /* launchTaskBehind */, false /* alwaysFocusable */, 0 /* targetSdkVersion */, 0 /* rotationAnimationHint */, - 0 /* inputDispatchingTimeoutNanos */, taskController.mService, - null /* bounds */); + 0 /* inputDispatchingTimeoutNanos */, taskController.mService); mToken = token; } @@ -279,12 +295,12 @@ public class WindowTestUtils { boolean voiceInteraction, DisplayContent dc, long inputDispatchingTimeoutNanos, boolean fullscreen, boolean showForAllUsers, int targetSdk, int orientation, int rotationAnimationHint, int configChanges, boolean launchTaskBehind, - boolean alwaysFocusable, AppWindowContainerController controller, Rect bounds) { + boolean alwaysFocusable, AppWindowContainerController controller) { return new TestAppWindowToken(service, token, voiceInteraction, dc, inputDispatchingTimeoutNanos, fullscreen, showForAllUsers, targetSdk, orientation, rotationAnimationHint, configChanges, launchTaskBehind, alwaysFocusable, - controller, bounds); + controller); } AppWindowToken getAppWindowToken(DisplayContent dc) { |