Loading services/core/java/com/android/server/wm/ActivityRecord.java +40 −21 Original line number Diff line number Diff line Loading @@ -6224,6 +6224,13 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A return mRemoteAnimationDefinition; } @Override void applyFixedRotationTransform(DisplayInfo info, DisplayFrames displayFrames, Configuration config) { super.applyFixedRotationTransform(info, displayFrames, config); ensureActivityConfiguration(0 /* globalChanges */, false /* preserveWindow */); } void setRequestedOrientation(int requestedOrientation) { setOrientation(requestedOrientation, mayFreezeScreenLocked()); mAtmService.getTaskChangeNotificationController().notifyActivityRequestedOrientationChanged( Loading Loading @@ -6462,11 +6469,20 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A @Override void resolveOverrideConfiguration(Configuration newParentConfiguration) { Configuration resolvedConfig = getResolvedOverrideConfiguration(); super.resolveOverrideConfiguration(newParentConfiguration); final Configuration resolvedConfig = getResolvedOverrideConfiguration(); if (isFixedRotationTransforming()) { // The resolved configuration is applied with rotated display configuration. If this // activity matches its parent (the following resolving procedures are no-op), then it // can use the resolved configuration directly. Otherwise (e.g. fixed aspect ratio), // the rotated configuration is used as parent configuration to compute the actual // resolved configuration. It is like putting the activity in a rotated container. mTmpConfig.setTo(resolvedConfig); newParentConfiguration = mTmpConfig; } if (mCompatDisplayInsets != null) { resolveSizeCompatModeConfiguration(newParentConfiguration); } else { super.resolveOverrideConfiguration(newParentConfiguration); // We ignore activities' requested orientation in multi-window modes. Task level may // take them into consideration when calculating bounds. if (getParent() != null && getParent().inMultiWindowMode()) { Loading Loading @@ -6495,7 +6511,6 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A * inheriting the parent bounds. */ private void resolveSizeCompatModeConfiguration(Configuration newParentConfiguration) { super.resolveOverrideConfiguration(newParentConfiguration); final Configuration resolvedConfig = getResolvedOverrideConfiguration(); final Rect resolvedBounds = resolvedConfig.windowConfiguration.getBounds(); Loading Loading @@ -6669,15 +6684,12 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A mTmpPrevBounds.set(getBounds()); super.onConfigurationChanged(newParentConfig); if (shouldUseSizeCompatMode()) { final Rect overrideBounds = getResolvedOverrideBounds(); if (task != null && !overrideBounds.isEmpty() // If the changes come from change-listener, the incoming parent configuration is // still the old one. Make sure their orientations are the same to reduce computing // the compatibility bounds for the intermediate state. && (task.getConfiguration().orientation == newParentConfig.orientation)) { if (task != null && !overrideBounds.isEmpty()) { final Rect taskBounds = task.getBounds(); // Since we only center the activity horizontally, if only the fixed height is smaller // than its container, the override bounds don't need to take effect. // Since we only center the activity horizontally, if only the fixed height is // smaller than its container, the override bounds don't need to take effect. if ((overrideBounds.width() != taskBounds.width() || overrideBounds.height() > taskBounds.height())) { calculateCompatBoundsTransformation(newParentConfig); Loading @@ -6692,6 +6704,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A mSizeCompatScale = 1f; updateSurfacePosition(); } } final int newWinMode = getWindowingMode(); if ((prevWinMode != newWinMode) && (mDisplayContent != null) Loading Loading @@ -7710,6 +7723,12 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A return; } win.getAnimationFrames(outFrame, outInsets, outStableInsets, outSurfaceInsets); if (isFixedRotationTransforming()) { // This activity has been rotated but the display is still in old rotation. Because the // animation applies in display space coordinates, the rotated animation frames need to // be unrotated to avoid being cropped. unrotateAnimationFrames(outFrame, outInsets, outStableInsets, outSurfaceInsets); } } void setPictureInPictureParams(PictureInPictureParams p) { Loading services/core/java/com/android/server/wm/AppTransition.java +7 −0 Original line number Diff line number Diff line Loading @@ -528,6 +528,12 @@ public class AppTransition implements Dump { } } private void notifyAppTransitionTimeoutLocked() { for (int i = 0; i < mListeners.size(); i++) { mListeners.get(i).onAppTransitionTimeoutLocked(); } } private int notifyAppTransitionStartingLocked(int transit, long duration, long statusBarAnimationStartTime, long statusBarAnimationDuration) { int redoLayout = 0; Loading Loading @@ -2300,6 +2306,7 @@ public class AppTransition implements Dump { if (dc == null) { return; } notifyAppTransitionTimeoutLocked(); if (isTransitionSet() || !dc.mOpeningApps.isEmpty() || !dc.mClosingApps.isEmpty() || !dc.mChangingApps.isEmpty()) { ProtoLog.v(WM_DEBUG_APP_TRANSITIONS, Loading services/core/java/com/android/server/wm/ConfigurationContainer.java +3 −12 Original line number Diff line number Diff line Loading @@ -113,13 +113,6 @@ public abstract class ConfigurationContainer<E extends ConfigurationContainer> { * @see #mFullConfiguration */ public void onConfigurationChanged(Configuration newParentConfig) { onConfigurationChanged(newParentConfig, true /*forwardToChildren*/); } // TODO(root-unify): Consolidate with onConfigurationChanged() method above once unification is // done. This is only currently need during the process of unification where we don't want // configuration forwarded to a child from both parents. public void onConfigurationChanged(Configuration newParentConfig, boolean forwardToChildren) { mResolvedTmpConfig.setTo(mResolvedOverrideConfiguration); resolveOverrideConfiguration(newParentConfig); mFullConfiguration.setTo(newParentConfig); Loading @@ -141,13 +134,11 @@ public abstract class ConfigurationContainer<E extends ConfigurationContainer> { mChangeListeners.get(i).onMergedOverrideConfigurationChanged( mMergedOverrideConfiguration); } if (forwardToChildren) { for (int i = getChildCount() - 1; i >= 0; --i) { final ConfigurationContainer child = getChildAt(i); child.onConfigurationChanged(mFullConfiguration); } } } /** * Resolves the current requested override configuration into Loading services/core/java/com/android/server/wm/DisplayContent.java +200 −33 Original line number Diff line number Diff line Loading @@ -259,6 +259,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo implements WindowManagerPolicy.DisplayContentInfo { private static final String TAG = TAG_WITH_CLASS_NAME ? "DisplayContent" : TAG_WM; private static final String TAG_STACK = TAG + POSTFIX_STACK; private static final int NO_ROTATION = -1; /** The default scaling mode that scales content automatically. */ static final int FORCE_SCALING_MODE_AUTO = 0; Loading Loading @@ -515,6 +516,13 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo */ ActivityRecord mFocusedApp = null; /** * The launching activity which is using fixed rotation transformation. * * @see #handleTopActivityLaunchingInDifferentOrientation */ ActivityRecord mFixedRotationLaunchingApp; /** Windows added since {@link #mCurrentFocus} was set to null. Used for ANR blaming. */ final ArrayList<WindowState> mWinAddedSinceNullFocus = new ArrayList<>(); Loading Loading @@ -1308,6 +1316,9 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo if (mDisplayRotation.isWaitingForRemoteRotation()) { return; } // Clear the record because the display will sync to current rotation. mFixedRotationLaunchingApp = null; final boolean configUpdated = updateDisplayOverrideConfigurationLocked(); if (configUpdated) { return; Loading Loading @@ -1367,7 +1378,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo * {@link #sendNewConfiguration} if the method returns {@code true}. */ boolean updateOrientation() { return mDisplayRotation.updateOrientation(getOrientation(), false /* forceUpdate */); return updateOrientation(false /* forceUpdate */); } /** Loading @@ -1390,7 +1401,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo } Configuration config = null; if (mDisplayRotation.updateOrientation(getOrientation(), forceUpdate)) { if (updateOrientation(forceUpdate)) { // If we changed the orientation but mOrientationChangeComplete is already true, // we used seamless rotation, and we don't need to freeze the screen. if (freezeDisplayToken != null && !mWmService.mRoot.mOrientationChangeComplete) { Loading Loading @@ -1421,6 +1432,126 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo return config; } private boolean updateOrientation(boolean forceUpdate) { final int orientation = getOrientation(); // The last orientation source is valid only after getOrientation. final WindowContainer orientationSource = getLastOrientationSource(); final ActivityRecord r = orientationSource != null ? orientationSource.asActivityRecord() : null; // Currently there is no use case from non-activity. if (r != null && handleTopActivityLaunchingInDifferentOrientation(r)) { mFixedRotationLaunchingApp = r; // Display orientation should be deferred until the top fixed rotation is finished. return false; } return mDisplayRotation.updateOrientation(orientation, forceUpdate); } /** @return a valid rotation if the activity can use different orientation than the display. */ @Surface.Rotation private int rotationForActivityInDifferentOrientation(@NonNull ActivityRecord r) { if (!mWmService.mIsFixedRotationTransformEnabled) { return NO_ROTATION; } if (r.inMultiWindowMode() || r.getRequestedConfigurationOrientation() == getConfiguration().orientation) { return NO_ROTATION; } final int currentRotation = getRotation(); final int rotation = mDisplayRotation.rotationForOrientation(r.getRequestedOrientation(), currentRotation); if (rotation == currentRotation) { return NO_ROTATION; } return rotation; } /** * We need to keep display rotation fixed for a while when the activity in different orientation * is launching until the launch animation is done to avoid showing the previous activity * inadvertently in a wrong orientation. * * @return {@code true} if the fixed rotation is started. */ private boolean handleTopActivityLaunchingInDifferentOrientation(@NonNull ActivityRecord r) { if (!mWmService.mIsFixedRotationTransformEnabled) { return false; } if (r.isFinishingFixedRotationTransform()) { return false; } if (r.hasFixedRotationTransform()) { // It has been set and not yet finished. return true; } if (!mAppTransition.isTransitionSet()) { // Apply normal rotation animation in case of the activity set different requested // orientation without activity switch. return false; } if (!mOpeningApps.contains(r) // Without screen rotation, the rotation behavior of non-top visible activities is // undefined. So the fixed rotated activity needs to cover the screen. && r.findMainWindow() != mDisplayPolicy.getTopFullscreenOpaqueWindow()) { return false; } final int rotation = rotationForActivityInDifferentOrientation(r); if (rotation == NO_ROTATION) { return false; } if (!r.getParent().matchParentBounds()) { // Because the fixed rotated configuration applies to activity directly, if its parent // has it own policy for bounds, the activity bounds based on parent is unknown. return false; } startFixedRotationTransform(r, rotation); mAppTransition.registerListenerLocked(new WindowManagerInternal.AppTransitionListener() { void done() { r.clearFixedRotationTransform(); mAppTransition.unregisterListener(this); } @Override public void onAppTransitionFinishedLocked(IBinder token) { if (token == r.token) { done(); } } @Override public void onAppTransitionCancelledLocked(int transit) { done(); } @Override public void onAppTransitionTimeoutLocked() { done(); } }); return true; } /** @return {@code true} if the display orientation will be changed. */ boolean continueUpdateOrientationForDiffOrienLaunchingApp(WindowToken token) { if (token != mFixedRotationLaunchingApp) { return false; } if (updateOrientation()) { sendNewConfiguration(); return true; } return false; } private void startFixedRotationTransform(WindowToken token, int rotation) { mTmpConfiguration.unset(); final DisplayInfo info = computeScreenConfiguration(mTmpConfiguration, rotation); final WmDisplayCutout cutout = calculateDisplayCutoutForRotation(rotation); final DisplayFrames displayFrames = new DisplayFrames(mDisplayId, info, cutout); token.applyFixedRotationTransform(info, displayFrames, mTmpConfiguration); } /** * Update rotation of the display. * Loading Loading @@ -1621,6 +1752,63 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo rotated ? mInitialDisplayWidth : mInitialDisplayHeight); } /** * Compute display info and configuration according to the given rotation without changing * current display. */ DisplayInfo computeScreenConfiguration(Configuration outConfig, int rotation) { final boolean rotated = (rotation == ROTATION_90 || rotation == ROTATION_270); final int dw = rotated ? mBaseDisplayHeight : mBaseDisplayWidth; final int dh = rotated ? mBaseDisplayWidth : mBaseDisplayHeight; outConfig.windowConfiguration.getBounds().set(0, 0, dw, dh); final int uiMode = getConfiguration().uiMode; final DisplayCutout displayCutout = calculateDisplayCutoutForRotation(rotation).getDisplayCutout(); computeScreenAppConfiguration(outConfig, dw, dh, rotation, uiMode, displayCutout); final DisplayInfo displayInfo = new DisplayInfo(mDisplayInfo); displayInfo.rotation = rotation; displayInfo.logicalWidth = dw; displayInfo.logicalHeight = dh; final Rect appBounds = outConfig.windowConfiguration.getAppBounds(); displayInfo.appWidth = appBounds.width(); displayInfo.appHeight = appBounds.height(); displayInfo.displayCutout = displayCutout.isEmpty() ? null : displayCutout; computeSizeRangesAndScreenLayout(displayInfo, rotated, uiMode, dw, dh, mDisplayMetrics.density, outConfig); return displayInfo; } /** Compute configuration related to application without changing current display. */ private void computeScreenAppConfiguration(Configuration outConfig, int dw, int dh, int rotation, int uiMode, DisplayCutout displayCutout) { final int appWidth = mDisplayPolicy.getNonDecorDisplayWidth(dw, dh, rotation, uiMode, displayCutout); final int appHeight = mDisplayPolicy.getNonDecorDisplayHeight(dw, dh, rotation, uiMode, displayCutout); mDisplayPolicy.getNonDecorInsetsLw(rotation, dw, dh, displayCutout, mTmpRect); final int leftInset = mTmpRect.left; final int topInset = mTmpRect.top; // AppBounds at the root level should mirror the app screen size. outConfig.windowConfiguration.setAppBounds(leftInset /* left */, topInset /* top */, leftInset + appWidth /* right */, topInset + appHeight /* bottom */); outConfig.windowConfiguration.setRotation(rotation); outConfig.orientation = (dw <= dh) ? ORIENTATION_PORTRAIT : ORIENTATION_LANDSCAPE; final float density = mDisplayMetrics.density; outConfig.screenWidthDp = (int) (mDisplayPolicy.getConfigDisplayWidth(dw, dh, rotation, uiMode, displayCutout) / density); outConfig.screenHeightDp = (int) (mDisplayPolicy.getConfigDisplayHeight(dw, dh, rotation, uiMode, displayCutout) / density); outConfig.compatScreenWidthDp = (int) (outConfig.screenWidthDp / mCompatibleScreenScale); outConfig.compatScreenHeightDp = (int) (outConfig.screenHeightDp / mCompatibleScreenScale); final boolean rotated = (rotation == ROTATION_90 || rotation == ROTATION_270); outConfig.compatSmallestScreenWidthDp = computeCompatSmallestWidth(rotated, uiMode, dw, dh, displayCutout); } /** * Compute display configuration based on display properties and policy settings. * Do not call if mDisplayReady == false. Loading @@ -1629,42 +1817,19 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo final DisplayInfo displayInfo = updateDisplayAndOrientation(config.uiMode, config); calculateBounds(displayInfo, mTmpBounds); config.windowConfiguration.setBounds(mTmpBounds); final int dw = displayInfo.logicalWidth; final int dh = displayInfo.logicalHeight; config.orientation = (dw <= dh) ? ORIENTATION_PORTRAIT : ORIENTATION_LANDSCAPE; config.windowConfiguration.setWindowingMode(getWindowingMode()); config.windowConfiguration.setDisplayWindowingMode(getWindowingMode()); config.windowConfiguration.setRotation(displayInfo.rotation); final float density = mDisplayMetrics.density; config.screenWidthDp = (int)(mDisplayPolicy.getConfigDisplayWidth(dw, dh, displayInfo.rotation, config.uiMode, displayInfo.displayCutout) / density); config.screenHeightDp = (int)(mDisplayPolicy.getConfigDisplayHeight(dw, dh, displayInfo.rotation, config.uiMode, displayInfo.displayCutout) / density); mDisplayPolicy.getNonDecorInsetsLw(displayInfo.rotation, dw, dh, displayInfo.displayCutout, mTmpRect); final int leftInset = mTmpRect.left; final int topInset = mTmpRect.top; // appBounds at the root level should mirror the app screen size. config.windowConfiguration.setAppBounds(leftInset /* left */, topInset /* top */, leftInset + displayInfo.appWidth /* right */, topInset + displayInfo.appHeight /* bottom */); final boolean rotated = (displayInfo.rotation == Surface.ROTATION_90 || displayInfo.rotation == Surface.ROTATION_270); final int dw = displayInfo.logicalWidth; final int dh = displayInfo.logicalHeight; computeScreenAppConfiguration(config, dw, dh, displayInfo.rotation, config.uiMode, displayInfo.displayCutout); config.screenLayout = (config.screenLayout & ~Configuration.SCREENLAYOUT_ROUND_MASK) | ((displayInfo.flags & Display.FLAG_ROUND) != 0 ? Configuration.SCREENLAYOUT_ROUND_YES : Configuration.SCREENLAYOUT_ROUND_NO); config.compatScreenWidthDp = (int)(config.screenWidthDp / mCompatibleScreenScale); config.compatScreenHeightDp = (int)(config.screenHeightDp / mCompatibleScreenScale); config.compatSmallestScreenWidthDp = computeCompatSmallestWidth(rotated, config.uiMode, dw, dh, displayInfo.displayCutout); config.densityDpi = displayInfo.logicalDensityDpi; config.colorMode = Loading Loading @@ -2111,19 +2276,19 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo /** * In the general case, the orientation is computed from the above app windows first. If none of * the above app windows specify orientation, the orientation is computed from the child window * container, e.g. {@link AppWindowToken#getOrientation(int)}. * container, e.g. {@link ActivityRecord#getOrientation(int)}. */ @ScreenOrientation @Override int getOrientation() { final WindowManagerPolicy policy = mWmService.mPolicy; mLastOrientationSource = null; if (mIgnoreRotationForApps) { return SCREEN_ORIENTATION_USER; } if (mWmService.mDisplayFrozen) { if (policy.isKeyguardLocked()) { if (mWmService.mPolicy.isKeyguardLocked()) { // Use the last orientation the while the display is frozen with the keyguard // locked. This could be the keyguard forced orientation or from a SHOW_WHEN_LOCKED // window. We don't want to check the show when locked window directly though as Loading @@ -2135,7 +2300,9 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo return getLastOrientation(); } } return mRootDisplayArea.getOrientation(); final int rootOrientation = mRootDisplayArea.getOrientation(); mLastOrientationSource = mRootDisplayArea.getLastOrientationSource(); return rootOrientation; } void updateDisplayInfo() { Loading services/core/java/com/android/server/wm/DisplayPolicy.java +5 −4 Original line number Diff line number Diff line Loading @@ -1430,7 +1430,7 @@ public class DisplayPolicy { } } private void simulateLayoutDecorWindow(WindowState win, DisplayFrames displayFrames, int uiMode, private void simulateLayoutDecorWindow(WindowState win, DisplayFrames displayFrames, InsetsState insetsState, WindowFrames simulatedWindowFrames, Runnable layout) { win.setSimulatedWindowFrames(simulatedWindowFrames); try { Loading @@ -1454,7 +1454,7 @@ public class DisplayPolicy { final WindowFrames simulatedWindowFrames = new WindowFrames(); if (mNavigationBar != null) { simulateLayoutDecorWindow( mNavigationBar, displayFrames, uiMode, insetsState, simulatedWindowFrames, mNavigationBar, displayFrames, insetsState, simulatedWindowFrames, () -> layoutNavigationBar(displayFrames, uiMode, mLastNavVisible, mLastNavTranslucent, mLastNavAllowedHidden, mLastNotificationShadeForcesShowingNavigation, Loading @@ -1462,7 +1462,7 @@ public class DisplayPolicy { } if (mStatusBar != null) { simulateLayoutDecorWindow( mStatusBar, displayFrames, uiMode, insetsState, simulatedWindowFrames, mStatusBar, displayFrames, insetsState, simulatedWindowFrames, () -> layoutStatusBar(displayFrames, mLastSystemUiFlags, false /* isRealLayout */)); } Loading Loading @@ -1536,7 +1536,7 @@ public class DisplayPolicy { if (updateSysUiVisibility) { updateSystemUiVisibilityLw(); } layoutScreenDecorWindows(displayFrames, null /* transientFrames */); layoutScreenDecorWindows(displayFrames, null /* simulatedFrames */); postAdjustDisplayFrames(displayFrames); mLastNavVisible = navVisible; mLastNavTranslucent = navTranslucent; Loading Loading @@ -1939,6 +1939,7 @@ public class DisplayPolicy { final int requestedSysUiFl = PolicyControl.getSystemUiVisibility(null, attrs); final int sysUiFl = requestedSysUiFl | getImpliedSysUiFlagsForLayout(attrs); displayFrames = win.getDisplayFrames(displayFrames); final WindowFrames windowFrames = win.getWindowFrames(); sTmpLastParentFrame.set(windowFrames.mParentFrame); Loading Loading
services/core/java/com/android/server/wm/ActivityRecord.java +40 −21 Original line number Diff line number Diff line Loading @@ -6224,6 +6224,13 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A return mRemoteAnimationDefinition; } @Override void applyFixedRotationTransform(DisplayInfo info, DisplayFrames displayFrames, Configuration config) { super.applyFixedRotationTransform(info, displayFrames, config); ensureActivityConfiguration(0 /* globalChanges */, false /* preserveWindow */); } void setRequestedOrientation(int requestedOrientation) { setOrientation(requestedOrientation, mayFreezeScreenLocked()); mAtmService.getTaskChangeNotificationController().notifyActivityRequestedOrientationChanged( Loading Loading @@ -6462,11 +6469,20 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A @Override void resolveOverrideConfiguration(Configuration newParentConfiguration) { Configuration resolvedConfig = getResolvedOverrideConfiguration(); super.resolveOverrideConfiguration(newParentConfiguration); final Configuration resolvedConfig = getResolvedOverrideConfiguration(); if (isFixedRotationTransforming()) { // The resolved configuration is applied with rotated display configuration. If this // activity matches its parent (the following resolving procedures are no-op), then it // can use the resolved configuration directly. Otherwise (e.g. fixed aspect ratio), // the rotated configuration is used as parent configuration to compute the actual // resolved configuration. It is like putting the activity in a rotated container. mTmpConfig.setTo(resolvedConfig); newParentConfiguration = mTmpConfig; } if (mCompatDisplayInsets != null) { resolveSizeCompatModeConfiguration(newParentConfiguration); } else { super.resolveOverrideConfiguration(newParentConfiguration); // We ignore activities' requested orientation in multi-window modes. Task level may // take them into consideration when calculating bounds. if (getParent() != null && getParent().inMultiWindowMode()) { Loading Loading @@ -6495,7 +6511,6 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A * inheriting the parent bounds. */ private void resolveSizeCompatModeConfiguration(Configuration newParentConfiguration) { super.resolveOverrideConfiguration(newParentConfiguration); final Configuration resolvedConfig = getResolvedOverrideConfiguration(); final Rect resolvedBounds = resolvedConfig.windowConfiguration.getBounds(); Loading Loading @@ -6669,15 +6684,12 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A mTmpPrevBounds.set(getBounds()); super.onConfigurationChanged(newParentConfig); if (shouldUseSizeCompatMode()) { final Rect overrideBounds = getResolvedOverrideBounds(); if (task != null && !overrideBounds.isEmpty() // If the changes come from change-listener, the incoming parent configuration is // still the old one. Make sure their orientations are the same to reduce computing // the compatibility bounds for the intermediate state. && (task.getConfiguration().orientation == newParentConfig.orientation)) { if (task != null && !overrideBounds.isEmpty()) { final Rect taskBounds = task.getBounds(); // Since we only center the activity horizontally, if only the fixed height is smaller // than its container, the override bounds don't need to take effect. // Since we only center the activity horizontally, if only the fixed height is // smaller than its container, the override bounds don't need to take effect. if ((overrideBounds.width() != taskBounds.width() || overrideBounds.height() > taskBounds.height())) { calculateCompatBoundsTransformation(newParentConfig); Loading @@ -6692,6 +6704,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A mSizeCompatScale = 1f; updateSurfacePosition(); } } final int newWinMode = getWindowingMode(); if ((prevWinMode != newWinMode) && (mDisplayContent != null) Loading Loading @@ -7710,6 +7723,12 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A return; } win.getAnimationFrames(outFrame, outInsets, outStableInsets, outSurfaceInsets); if (isFixedRotationTransforming()) { // This activity has been rotated but the display is still in old rotation. Because the // animation applies in display space coordinates, the rotated animation frames need to // be unrotated to avoid being cropped. unrotateAnimationFrames(outFrame, outInsets, outStableInsets, outSurfaceInsets); } } void setPictureInPictureParams(PictureInPictureParams p) { Loading
services/core/java/com/android/server/wm/AppTransition.java +7 −0 Original line number Diff line number Diff line Loading @@ -528,6 +528,12 @@ public class AppTransition implements Dump { } } private void notifyAppTransitionTimeoutLocked() { for (int i = 0; i < mListeners.size(); i++) { mListeners.get(i).onAppTransitionTimeoutLocked(); } } private int notifyAppTransitionStartingLocked(int transit, long duration, long statusBarAnimationStartTime, long statusBarAnimationDuration) { int redoLayout = 0; Loading Loading @@ -2300,6 +2306,7 @@ public class AppTransition implements Dump { if (dc == null) { return; } notifyAppTransitionTimeoutLocked(); if (isTransitionSet() || !dc.mOpeningApps.isEmpty() || !dc.mClosingApps.isEmpty() || !dc.mChangingApps.isEmpty()) { ProtoLog.v(WM_DEBUG_APP_TRANSITIONS, Loading
services/core/java/com/android/server/wm/ConfigurationContainer.java +3 −12 Original line number Diff line number Diff line Loading @@ -113,13 +113,6 @@ public abstract class ConfigurationContainer<E extends ConfigurationContainer> { * @see #mFullConfiguration */ public void onConfigurationChanged(Configuration newParentConfig) { onConfigurationChanged(newParentConfig, true /*forwardToChildren*/); } // TODO(root-unify): Consolidate with onConfigurationChanged() method above once unification is // done. This is only currently need during the process of unification where we don't want // configuration forwarded to a child from both parents. public void onConfigurationChanged(Configuration newParentConfig, boolean forwardToChildren) { mResolvedTmpConfig.setTo(mResolvedOverrideConfiguration); resolveOverrideConfiguration(newParentConfig); mFullConfiguration.setTo(newParentConfig); Loading @@ -141,13 +134,11 @@ public abstract class ConfigurationContainer<E extends ConfigurationContainer> { mChangeListeners.get(i).onMergedOverrideConfigurationChanged( mMergedOverrideConfiguration); } if (forwardToChildren) { for (int i = getChildCount() - 1; i >= 0; --i) { final ConfigurationContainer child = getChildAt(i); child.onConfigurationChanged(mFullConfiguration); } } } /** * Resolves the current requested override configuration into Loading
services/core/java/com/android/server/wm/DisplayContent.java +200 −33 Original line number Diff line number Diff line Loading @@ -259,6 +259,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo implements WindowManagerPolicy.DisplayContentInfo { private static final String TAG = TAG_WITH_CLASS_NAME ? "DisplayContent" : TAG_WM; private static final String TAG_STACK = TAG + POSTFIX_STACK; private static final int NO_ROTATION = -1; /** The default scaling mode that scales content automatically. */ static final int FORCE_SCALING_MODE_AUTO = 0; Loading Loading @@ -515,6 +516,13 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo */ ActivityRecord mFocusedApp = null; /** * The launching activity which is using fixed rotation transformation. * * @see #handleTopActivityLaunchingInDifferentOrientation */ ActivityRecord mFixedRotationLaunchingApp; /** Windows added since {@link #mCurrentFocus} was set to null. Used for ANR blaming. */ final ArrayList<WindowState> mWinAddedSinceNullFocus = new ArrayList<>(); Loading Loading @@ -1308,6 +1316,9 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo if (mDisplayRotation.isWaitingForRemoteRotation()) { return; } // Clear the record because the display will sync to current rotation. mFixedRotationLaunchingApp = null; final boolean configUpdated = updateDisplayOverrideConfigurationLocked(); if (configUpdated) { return; Loading Loading @@ -1367,7 +1378,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo * {@link #sendNewConfiguration} if the method returns {@code true}. */ boolean updateOrientation() { return mDisplayRotation.updateOrientation(getOrientation(), false /* forceUpdate */); return updateOrientation(false /* forceUpdate */); } /** Loading @@ -1390,7 +1401,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo } Configuration config = null; if (mDisplayRotation.updateOrientation(getOrientation(), forceUpdate)) { if (updateOrientation(forceUpdate)) { // If we changed the orientation but mOrientationChangeComplete is already true, // we used seamless rotation, and we don't need to freeze the screen. if (freezeDisplayToken != null && !mWmService.mRoot.mOrientationChangeComplete) { Loading Loading @@ -1421,6 +1432,126 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo return config; } private boolean updateOrientation(boolean forceUpdate) { final int orientation = getOrientation(); // The last orientation source is valid only after getOrientation. final WindowContainer orientationSource = getLastOrientationSource(); final ActivityRecord r = orientationSource != null ? orientationSource.asActivityRecord() : null; // Currently there is no use case from non-activity. if (r != null && handleTopActivityLaunchingInDifferentOrientation(r)) { mFixedRotationLaunchingApp = r; // Display orientation should be deferred until the top fixed rotation is finished. return false; } return mDisplayRotation.updateOrientation(orientation, forceUpdate); } /** @return a valid rotation if the activity can use different orientation than the display. */ @Surface.Rotation private int rotationForActivityInDifferentOrientation(@NonNull ActivityRecord r) { if (!mWmService.mIsFixedRotationTransformEnabled) { return NO_ROTATION; } if (r.inMultiWindowMode() || r.getRequestedConfigurationOrientation() == getConfiguration().orientation) { return NO_ROTATION; } final int currentRotation = getRotation(); final int rotation = mDisplayRotation.rotationForOrientation(r.getRequestedOrientation(), currentRotation); if (rotation == currentRotation) { return NO_ROTATION; } return rotation; } /** * We need to keep display rotation fixed for a while when the activity in different orientation * is launching until the launch animation is done to avoid showing the previous activity * inadvertently in a wrong orientation. * * @return {@code true} if the fixed rotation is started. */ private boolean handleTopActivityLaunchingInDifferentOrientation(@NonNull ActivityRecord r) { if (!mWmService.mIsFixedRotationTransformEnabled) { return false; } if (r.isFinishingFixedRotationTransform()) { return false; } if (r.hasFixedRotationTransform()) { // It has been set and not yet finished. return true; } if (!mAppTransition.isTransitionSet()) { // Apply normal rotation animation in case of the activity set different requested // orientation without activity switch. return false; } if (!mOpeningApps.contains(r) // Without screen rotation, the rotation behavior of non-top visible activities is // undefined. So the fixed rotated activity needs to cover the screen. && r.findMainWindow() != mDisplayPolicy.getTopFullscreenOpaqueWindow()) { return false; } final int rotation = rotationForActivityInDifferentOrientation(r); if (rotation == NO_ROTATION) { return false; } if (!r.getParent().matchParentBounds()) { // Because the fixed rotated configuration applies to activity directly, if its parent // has it own policy for bounds, the activity bounds based on parent is unknown. return false; } startFixedRotationTransform(r, rotation); mAppTransition.registerListenerLocked(new WindowManagerInternal.AppTransitionListener() { void done() { r.clearFixedRotationTransform(); mAppTransition.unregisterListener(this); } @Override public void onAppTransitionFinishedLocked(IBinder token) { if (token == r.token) { done(); } } @Override public void onAppTransitionCancelledLocked(int transit) { done(); } @Override public void onAppTransitionTimeoutLocked() { done(); } }); return true; } /** @return {@code true} if the display orientation will be changed. */ boolean continueUpdateOrientationForDiffOrienLaunchingApp(WindowToken token) { if (token != mFixedRotationLaunchingApp) { return false; } if (updateOrientation()) { sendNewConfiguration(); return true; } return false; } private void startFixedRotationTransform(WindowToken token, int rotation) { mTmpConfiguration.unset(); final DisplayInfo info = computeScreenConfiguration(mTmpConfiguration, rotation); final WmDisplayCutout cutout = calculateDisplayCutoutForRotation(rotation); final DisplayFrames displayFrames = new DisplayFrames(mDisplayId, info, cutout); token.applyFixedRotationTransform(info, displayFrames, mTmpConfiguration); } /** * Update rotation of the display. * Loading Loading @@ -1621,6 +1752,63 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo rotated ? mInitialDisplayWidth : mInitialDisplayHeight); } /** * Compute display info and configuration according to the given rotation without changing * current display. */ DisplayInfo computeScreenConfiguration(Configuration outConfig, int rotation) { final boolean rotated = (rotation == ROTATION_90 || rotation == ROTATION_270); final int dw = rotated ? mBaseDisplayHeight : mBaseDisplayWidth; final int dh = rotated ? mBaseDisplayWidth : mBaseDisplayHeight; outConfig.windowConfiguration.getBounds().set(0, 0, dw, dh); final int uiMode = getConfiguration().uiMode; final DisplayCutout displayCutout = calculateDisplayCutoutForRotation(rotation).getDisplayCutout(); computeScreenAppConfiguration(outConfig, dw, dh, rotation, uiMode, displayCutout); final DisplayInfo displayInfo = new DisplayInfo(mDisplayInfo); displayInfo.rotation = rotation; displayInfo.logicalWidth = dw; displayInfo.logicalHeight = dh; final Rect appBounds = outConfig.windowConfiguration.getAppBounds(); displayInfo.appWidth = appBounds.width(); displayInfo.appHeight = appBounds.height(); displayInfo.displayCutout = displayCutout.isEmpty() ? null : displayCutout; computeSizeRangesAndScreenLayout(displayInfo, rotated, uiMode, dw, dh, mDisplayMetrics.density, outConfig); return displayInfo; } /** Compute configuration related to application without changing current display. */ private void computeScreenAppConfiguration(Configuration outConfig, int dw, int dh, int rotation, int uiMode, DisplayCutout displayCutout) { final int appWidth = mDisplayPolicy.getNonDecorDisplayWidth(dw, dh, rotation, uiMode, displayCutout); final int appHeight = mDisplayPolicy.getNonDecorDisplayHeight(dw, dh, rotation, uiMode, displayCutout); mDisplayPolicy.getNonDecorInsetsLw(rotation, dw, dh, displayCutout, mTmpRect); final int leftInset = mTmpRect.left; final int topInset = mTmpRect.top; // AppBounds at the root level should mirror the app screen size. outConfig.windowConfiguration.setAppBounds(leftInset /* left */, topInset /* top */, leftInset + appWidth /* right */, topInset + appHeight /* bottom */); outConfig.windowConfiguration.setRotation(rotation); outConfig.orientation = (dw <= dh) ? ORIENTATION_PORTRAIT : ORIENTATION_LANDSCAPE; final float density = mDisplayMetrics.density; outConfig.screenWidthDp = (int) (mDisplayPolicy.getConfigDisplayWidth(dw, dh, rotation, uiMode, displayCutout) / density); outConfig.screenHeightDp = (int) (mDisplayPolicy.getConfigDisplayHeight(dw, dh, rotation, uiMode, displayCutout) / density); outConfig.compatScreenWidthDp = (int) (outConfig.screenWidthDp / mCompatibleScreenScale); outConfig.compatScreenHeightDp = (int) (outConfig.screenHeightDp / mCompatibleScreenScale); final boolean rotated = (rotation == ROTATION_90 || rotation == ROTATION_270); outConfig.compatSmallestScreenWidthDp = computeCompatSmallestWidth(rotated, uiMode, dw, dh, displayCutout); } /** * Compute display configuration based on display properties and policy settings. * Do not call if mDisplayReady == false. Loading @@ -1629,42 +1817,19 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo final DisplayInfo displayInfo = updateDisplayAndOrientation(config.uiMode, config); calculateBounds(displayInfo, mTmpBounds); config.windowConfiguration.setBounds(mTmpBounds); final int dw = displayInfo.logicalWidth; final int dh = displayInfo.logicalHeight; config.orientation = (dw <= dh) ? ORIENTATION_PORTRAIT : ORIENTATION_LANDSCAPE; config.windowConfiguration.setWindowingMode(getWindowingMode()); config.windowConfiguration.setDisplayWindowingMode(getWindowingMode()); config.windowConfiguration.setRotation(displayInfo.rotation); final float density = mDisplayMetrics.density; config.screenWidthDp = (int)(mDisplayPolicy.getConfigDisplayWidth(dw, dh, displayInfo.rotation, config.uiMode, displayInfo.displayCutout) / density); config.screenHeightDp = (int)(mDisplayPolicy.getConfigDisplayHeight(dw, dh, displayInfo.rotation, config.uiMode, displayInfo.displayCutout) / density); mDisplayPolicy.getNonDecorInsetsLw(displayInfo.rotation, dw, dh, displayInfo.displayCutout, mTmpRect); final int leftInset = mTmpRect.left; final int topInset = mTmpRect.top; // appBounds at the root level should mirror the app screen size. config.windowConfiguration.setAppBounds(leftInset /* left */, topInset /* top */, leftInset + displayInfo.appWidth /* right */, topInset + displayInfo.appHeight /* bottom */); final boolean rotated = (displayInfo.rotation == Surface.ROTATION_90 || displayInfo.rotation == Surface.ROTATION_270); final int dw = displayInfo.logicalWidth; final int dh = displayInfo.logicalHeight; computeScreenAppConfiguration(config, dw, dh, displayInfo.rotation, config.uiMode, displayInfo.displayCutout); config.screenLayout = (config.screenLayout & ~Configuration.SCREENLAYOUT_ROUND_MASK) | ((displayInfo.flags & Display.FLAG_ROUND) != 0 ? Configuration.SCREENLAYOUT_ROUND_YES : Configuration.SCREENLAYOUT_ROUND_NO); config.compatScreenWidthDp = (int)(config.screenWidthDp / mCompatibleScreenScale); config.compatScreenHeightDp = (int)(config.screenHeightDp / mCompatibleScreenScale); config.compatSmallestScreenWidthDp = computeCompatSmallestWidth(rotated, config.uiMode, dw, dh, displayInfo.displayCutout); config.densityDpi = displayInfo.logicalDensityDpi; config.colorMode = Loading Loading @@ -2111,19 +2276,19 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo /** * In the general case, the orientation is computed from the above app windows first. If none of * the above app windows specify orientation, the orientation is computed from the child window * container, e.g. {@link AppWindowToken#getOrientation(int)}. * container, e.g. {@link ActivityRecord#getOrientation(int)}. */ @ScreenOrientation @Override int getOrientation() { final WindowManagerPolicy policy = mWmService.mPolicy; mLastOrientationSource = null; if (mIgnoreRotationForApps) { return SCREEN_ORIENTATION_USER; } if (mWmService.mDisplayFrozen) { if (policy.isKeyguardLocked()) { if (mWmService.mPolicy.isKeyguardLocked()) { // Use the last orientation the while the display is frozen with the keyguard // locked. This could be the keyguard forced orientation or from a SHOW_WHEN_LOCKED // window. We don't want to check the show when locked window directly though as Loading @@ -2135,7 +2300,9 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo return getLastOrientation(); } } return mRootDisplayArea.getOrientation(); final int rootOrientation = mRootDisplayArea.getOrientation(); mLastOrientationSource = mRootDisplayArea.getLastOrientationSource(); return rootOrientation; } void updateDisplayInfo() { Loading
services/core/java/com/android/server/wm/DisplayPolicy.java +5 −4 Original line number Diff line number Diff line Loading @@ -1430,7 +1430,7 @@ public class DisplayPolicy { } } private void simulateLayoutDecorWindow(WindowState win, DisplayFrames displayFrames, int uiMode, private void simulateLayoutDecorWindow(WindowState win, DisplayFrames displayFrames, InsetsState insetsState, WindowFrames simulatedWindowFrames, Runnable layout) { win.setSimulatedWindowFrames(simulatedWindowFrames); try { Loading @@ -1454,7 +1454,7 @@ public class DisplayPolicy { final WindowFrames simulatedWindowFrames = new WindowFrames(); if (mNavigationBar != null) { simulateLayoutDecorWindow( mNavigationBar, displayFrames, uiMode, insetsState, simulatedWindowFrames, mNavigationBar, displayFrames, insetsState, simulatedWindowFrames, () -> layoutNavigationBar(displayFrames, uiMode, mLastNavVisible, mLastNavTranslucent, mLastNavAllowedHidden, mLastNotificationShadeForcesShowingNavigation, Loading @@ -1462,7 +1462,7 @@ public class DisplayPolicy { } if (mStatusBar != null) { simulateLayoutDecorWindow( mStatusBar, displayFrames, uiMode, insetsState, simulatedWindowFrames, mStatusBar, displayFrames, insetsState, simulatedWindowFrames, () -> layoutStatusBar(displayFrames, mLastSystemUiFlags, false /* isRealLayout */)); } Loading Loading @@ -1536,7 +1536,7 @@ public class DisplayPolicy { if (updateSysUiVisibility) { updateSystemUiVisibilityLw(); } layoutScreenDecorWindows(displayFrames, null /* transientFrames */); layoutScreenDecorWindows(displayFrames, null /* simulatedFrames */); postAdjustDisplayFrames(displayFrames); mLastNavVisible = navVisible; mLastNavTranslucent = navTranslucent; Loading Loading @@ -1939,6 +1939,7 @@ public class DisplayPolicy { final int requestedSysUiFl = PolicyControl.getSystemUiVisibility(null, attrs); final int sysUiFl = requestedSysUiFl | getImpliedSysUiFlagsForLayout(attrs); displayFrames = win.getDisplayFrames(displayFrames); final WindowFrames windowFrames = win.getWindowFrames(); sTmpLastParentFrame.set(windowFrames.mParentFrame); Loading