Move rotation methods to DisplayContent
This moves some of the rotation logic applied to displays
from WindowManagerService to DisplayContent. No changes in
logic.
Bug: 34242678
Test: android.server.cts.ActivityManagerDisplayTests
Test: #testRotationNotAffectingSecondaryScreen
Test: android.server.cts.ActivityManagerAppConfigurationTests
Change-Id: Ica8b5d700dea82edfc6b51b10be3362fc89854b0
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index cb3a663..e5b00f3 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -73,18 +73,24 @@
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TOKEN_MOVEMENT;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WALLPAPER;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WALLPAPER_LIGHT;
+import static com.android.server.wm.WindowManagerDebugConfig.SHOW_LIGHT_TRANSACTIONS;
import static com.android.server.wm.WindowManagerDebugConfig.SHOW_STACK_CRAWLS;
import static com.android.server.wm.WindowManagerDebugConfig.SHOW_TRANSACTIONS;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
+import static com.android.server.wm.WindowManagerService.CUSTOM_SCREEN_ROTATION;
import static com.android.server.wm.WindowManagerService.H.SEND_NEW_CONFIGURATION;
import static com.android.server.wm.WindowManagerService.H.UPDATE_DOCKED_STACK_DIVIDER;
import static com.android.server.wm.WindowManagerService.H.WINDOW_HIDE_TIMEOUT;
import static com.android.server.wm.WindowManagerService.LAYOUT_REPEAT_THRESHOLD;
+import static com.android.server.wm.WindowManagerService.MAX_ANIMATION_DURATION;
+import static com.android.server.wm.WindowManagerService.SEAMLESS_ROTATION_TIMEOUT_DURATION;
import static com.android.server.wm.WindowManagerService.TYPE_LAYER_MULTIPLIER;
import static com.android.server.wm.WindowManagerService.TYPE_LAYER_OFFSET;
import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_WILL_PLACE_SURFACES;
+import static com.android.server.wm.WindowManagerService.WINDOWS_FREEZING_SCREENS_ACTIVE;
import static com.android.server.wm.WindowManagerService.WINDOWS_FREEZING_SCREENS_TIMEOUT;
+import static com.android.server.wm.WindowManagerService.WINDOW_FREEZE_TIMEOUT_DURATION;
import static com.android.server.wm.WindowManagerService.dipToPixel;
import static com.android.server.wm.WindowManagerService.logSurface;
import static com.android.server.wm.WindowState.RESIZE_HANDLE_WIDTH_IN_DP;
@@ -94,6 +100,7 @@
import android.annotation.NonNull;
import android.app.ActivityManager.StackId;
+import android.content.res.CompatibilityInfo;
import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.graphics.GraphicBuffer;
@@ -113,6 +120,7 @@
import android.util.Slog;
import android.view.Display;
import android.view.DisplayInfo;
+import android.view.InputDevice;
import android.view.Surface;
import android.view.SurfaceControl;
import android.view.WindowManagerPolicy;
@@ -181,12 +189,27 @@
private final DisplayInfo mDisplayInfo = new DisplayInfo();
private final Display mDisplay;
private final DisplayMetrics mDisplayMetrics = new DisplayMetrics();
+ /**
+ * For default display it contains real metrics, empty for others.
+ * @see WindowManagerService#createWatermarkInTransaction()
+ */
+ final DisplayMetrics mRealDisplayMetrics = new DisplayMetrics();
+ /** @see #computeCompatSmallestWidth(boolean, int, int, int, int) */
+ private final DisplayMetrics mTmpDisplayMetrics = new DisplayMetrics();
+ /**
+ * Compat metrics computed based on {@link #mDisplayMetrics}.
+ * @see #updateDisplayAndOrientation(int)
+ */
+ private final DisplayMetrics mCompatDisplayMetrics = new DisplayMetrics();
+
+ /** The desired scaling factor for compatible apps. */
+ float mCompatibleScreenScale;
/**
* Current rotation of the display.
* Constants as per {@link android.view.Surface.Rotation}.
*
- * @see WindowManagerService#updateRotationUncheckedLocked(boolean, int)
+ * @see #updateRotationUnchecked(boolean)
*/
private int mRotation = 0;
/**
@@ -200,7 +223,7 @@
* Flag indicating that the application is receiving an orientation that has different metrics
* than it expected. E.g. Portrait instead of Landscape.
*
- * @see WindowManagerService#updateRotationUncheckedLocked(boolean, int)
+ * @see #updateRotationUnchecked(boolean)
*/
private boolean mAltOrientation = false;
/**
@@ -218,7 +241,7 @@
*/
private int mLastKeyguardForcedOrientation = SCREEN_ORIENTATION_UNSPECIFIED;
- Rect mBaseDisplayRect = new Rect();
+ private Rect mBaseDisplayRect = new Rect();
private Rect mContentRect = new Rect();
// Accessed directly by all users.
@@ -828,6 +851,514 @@
return mLastWindowForcedOrientation;
}
+ /**
+ * Update rotation of the display.
+ *
+ * Returns true if the rotation has been changed. In this case YOU MUST CALL
+ * {@link WindowManagerService#sendNewConfiguration(int)} TO UNFREEZE THE SCREEN.
+ */
+ boolean updateRotationUnchecked(boolean inTransaction) {
+ if (mService.mDeferredRotationPauseCount > 0) {
+ // Rotation updates have been paused temporarily. Defer the update until
+ // updates have been resumed.
+ if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Deferring rotation, rotation is paused.");
+ return false;
+ }
+
+ ScreenRotationAnimation screenRotationAnimation =
+ mService.mAnimator.getScreenRotationAnimationLocked(mDisplayId);
+ if (screenRotationAnimation != null && screenRotationAnimation.isAnimating()) {
+ // Rotation updates cannot be performed while the previous rotation change
+ // animation is still in progress. Skip this update. We will try updating
+ // again after the animation is finished and the display is unfrozen.
+ if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Deferring rotation, animation in progress.");
+ return false;
+ }
+ if (mService.mDisplayFrozen) {
+ // Even if the screen rotation animation has finished (e.g. isAnimating
+ // returns false), there is still some time where we haven't yet unfrozen
+ // the display. We also need to abort rotation here.
+ if (DEBUG_ORIENTATION) Slog.v(TAG_WM,
+ "Deferring rotation, still finishing previous rotation");
+ return false;
+ }
+
+ if (!mService.mDisplayEnabled) {
+ // No point choosing a rotation if the display is not enabled.
+ if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Deferring rotation, display is not enabled.");
+ return false;
+ }
+
+ final int oldRotation = mRotation;
+ final int lastOrientation = mLastOrientation;
+ final boolean oldAltOrientation = mAltOrientation;
+ int rotation = mService.mPolicy.rotationForOrientationLw(lastOrientation, oldRotation);
+ final boolean rotateSeamlessly;
+
+ if (mService.mPolicy.shouldRotateSeamlessly(oldRotation, rotation)) {
+ final WindowState seamlessRotated = getWindow((w) -> w.mSeamlesslyRotated);
+ if (seamlessRotated != null) {
+ // We can't rotate (seamlessly or not) while waiting for the last seamless rotation
+ // to complete (that is, waiting for windows to redraw). It's tempting to check
+ // w.mSeamlessRotationCount but that could be incorrect in the case of
+ // window-removal.
+ return false;
+ }
+
+ final WindowState cantSeamlesslyRotate = getWindow((w) ->
+ w.isChildWindow() && w.isVisibleNow()
+ && !w.mWinAnimator.mSurfaceController.getTransformToDisplayInverse());
+ if (cantSeamlesslyRotate != null) {
+ // In what can only be called an unfortunate workaround we require seamlessly
+ // rotated child windows to have the TRANSFORM_TO_DISPLAY_INVERSE flag. Due to
+ // limitations in the client API, there is no way for the client to set this flag in
+ // a race free fashion. If we seamlessly rotate a window which does not have this
+ // flag, but then gains it, we will get an incorrect visual result
+ // (rotated viewfinder). This means if we want to support seamlessly rotating
+ // windows which could gain this flag, we can't rotate windows without it. This
+ // limits seamless rotation in N to camera framework users, windows without
+ // children, and native code. This is unfortunate but having the camera work is our
+ // primary goal.
+ rotateSeamlessly = false;
+ } else {
+ rotateSeamlessly = true;
+ }
+ } else {
+ rotateSeamlessly = false;
+ }
+
+ // TODO: Implement forced rotation changes.
+ // Set mAltOrientation to indicate that the application is receiving
+ // an orientation that has different metrics than it expected.
+ // eg. Portrait instead of Landscape.
+
+ final boolean altOrientation = !mService.mPolicy.rotationHasCompatibleMetricsLw(
+ lastOrientation, rotation);
+
+ if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Selected orientation " + lastOrientation
+ + ", got rotation " + rotation + " which has "
+ + (altOrientation ? "incompatible" : "compatible") + " metrics");
+
+ if (oldRotation == rotation && oldAltOrientation == altOrientation) {
+ // No change.
+ return false;
+ }
+
+ if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Rotation changed to " + rotation
+ + (altOrientation ? " (alt)" : "") + " from " + oldRotation
+ + (oldAltOrientation ? " (alt)" : "") + ", lastOrientation=" + lastOrientation);
+
+ if (DisplayContent.deltaRotation(rotation, oldRotation) != 2) {
+ mService.mWaitingForConfig = true;
+ }
+
+ mRotation = rotation;
+ mAltOrientation = altOrientation;
+ if (isDefaultDisplay) {
+ mService.mPolicy.setRotationLw(rotation);
+ }
+
+ mService.mWindowsFreezingScreen = WINDOWS_FREEZING_SCREENS_ACTIVE;
+ mService.mH.removeMessages(WindowManagerService.H.WINDOW_FREEZE_TIMEOUT);
+ mService.mH.sendEmptyMessageDelayed(WindowManagerService.H.WINDOW_FREEZE_TIMEOUT,
+ WINDOW_FREEZE_TIMEOUT_DURATION);
+
+ setLayoutNeeded();
+ final int[] anim = new int[2];
+ if (isDimming()) {
+ anim[0] = anim[1] = 0;
+ } else {
+ mService.mPolicy.selectRotationAnimationLw(anim);
+ }
+
+ if (!rotateSeamlessly) {
+ mService.startFreezingDisplayLocked(inTransaction, anim[0], anim[1]);
+ // startFreezingDisplayLocked can reset the ScreenRotationAnimation.
+ screenRotationAnimation = mService.mAnimator.getScreenRotationAnimationLocked(
+ mDisplayId);
+ } else {
+ // The screen rotation animation uses a screenshot to freeze the screen
+ // while windows resize underneath.
+ // When we are rotating seamlessly, we allow the elements to transition
+ // to their rotated state independently and without a freeze required.
+ screenRotationAnimation = null;
+
+ // We have to reset this in case a window was removed before it
+ // finished seamless rotation.
+ mService.mSeamlessRotationCount = 0;
+ }
+
+ // We need to update our screen size information to match the new rotation. If the rotation
+ // has actually changed then this method will return true and, according to the comment at
+ // the top of the method, the caller is obligated to call computeNewConfigurationLocked().
+ // By updating the Display info here it will be available to
+ // #computeScreenConfiguration() later.
+ updateDisplayAndOrientation(getConfiguration().uiMode);
+
+ if (!inTransaction) {
+ if (SHOW_TRANSACTIONS) {
+ Slog.i(TAG_WM, ">>> OPEN TRANSACTION setRotationUnchecked");
+ }
+ mService.openSurfaceTransaction();
+ }
+ try {
+ // NOTE: We disable the rotation in the emulator because
+ // it doesn't support hardware OpenGL emulation yet.
+ if (CUSTOM_SCREEN_ROTATION && screenRotationAnimation != null
+ && screenRotationAnimation.hasScreenshot()) {
+ if (screenRotationAnimation.setRotationInTransaction(
+ rotation, mService.mFxSession,
+ MAX_ANIMATION_DURATION, mService.getTransitionAnimationScaleLocked(),
+ mDisplayInfo.logicalWidth, mDisplayInfo.logicalHeight)) {
+ mService.scheduleAnimationLocked();
+ }
+ }
+
+ if (rotateSeamlessly) {
+ forAllWindows(w -> {
+ w.mWinAnimator.seamlesslyRotateWindow(oldRotation, rotation);
+ }, true /* traverseTopToBottom */);
+ }
+
+ mService.mDisplayManagerInternal.performTraversalInTransactionFromWindowManager();
+ } finally {
+ if (!inTransaction) {
+ mService.closeSurfaceTransaction();
+ if (SHOW_LIGHT_TRANSACTIONS) {
+ Slog.i(TAG_WM, "<<< CLOSE TRANSACTION setRotationUnchecked");
+ }
+ }
+ }
+
+ forAllWindows(w -> {
+ // Discard surface after orientation change, these can't be reused.
+ if (w.mAppToken != null) {
+ w.mAppToken.destroySavedSurfaces();
+ }
+ if (w.mHasSurface && !rotateSeamlessly) {
+ if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Set mOrientationChanging of " + w);
+ w.mOrientationChanging = true;
+ mService.mRoot.mOrientationChangeComplete = false;
+ w.mLastFreezeDuration = 0;
+ }
+ w.mReportOrientationChanged = true;
+ }, true /* traverseTopToBottom */);
+
+ if (rotateSeamlessly) {
+ mService.mH.removeMessages(WindowManagerService.H.SEAMLESS_ROTATION_TIMEOUT);
+ mService.mH.sendEmptyMessageDelayed(WindowManagerService.H.SEAMLESS_ROTATION_TIMEOUT,
+ SEAMLESS_ROTATION_TIMEOUT_DURATION);
+ }
+
+ for (int i = mService.mRotationWatchers.size() - 1; i >= 0; i--) {
+ final WindowManagerService.RotationWatcher rotationWatcher
+ = mService.mRotationWatchers.get(i);
+ if (rotationWatcher.mDisplayId == mDisplayId) {
+ try {
+ rotationWatcher.mWatcher.onRotationChanged(rotation);
+ } catch (RemoteException e) {
+ // Ignore
+ }
+ }
+ }
+
+ // TODO (multi-display): Magnification is supported only for the default display.
+ // Announce rotation only if we will not animate as we already have the
+ // windows in final state. Otherwise, we make this call at the rotation end.
+ if (screenRotationAnimation == null && mService.mAccessibilityController != null
+ && isDefaultDisplay) {
+ mService.mAccessibilityController.onRotationChangedLocked(this);
+ }
+
+ return true;
+ }
+
+ /**
+ * Update {@link #mDisplayInfo} and other internal variables when display is rotated or config
+ * changed.
+ * Do not call if {@link WindowManagerService#mDisplayReady} == false.
+ */
+ private DisplayInfo updateDisplayAndOrientation(int uiMode) {
+ // Use the effective "visual" dimensions based on current rotation
+ final boolean rotated = (mRotation == ROTATION_90 || mRotation == ROTATION_270);
+ final int realdw = rotated ? mBaseDisplayHeight : mBaseDisplayWidth;
+ final int realdh = rotated ? mBaseDisplayWidth : mBaseDisplayHeight;
+ int dw = realdw;
+ int dh = realdh;
+
+ if (mAltOrientation) {
+ if (realdw > realdh) {
+ // Turn landscape into portrait.
+ int maxw = (int)(realdh/1.3f);
+ if (maxw < realdw) {
+ dw = maxw;
+ }
+ } else {
+ // Turn portrait into landscape.
+ int maxh = (int)(realdw/1.3f);
+ if (maxh < realdh) {
+ dh = maxh;
+ }
+ }
+ }
+
+ // Update application display metrics.
+ final int appWidth = mService.mPolicy.getNonDecorDisplayWidth(dw, dh, mRotation, uiMode,
+ mDisplayId);
+ final int appHeight = mService.mPolicy.getNonDecorDisplayHeight(dw, dh, mRotation, uiMode,
+ mDisplayId);
+ mDisplayInfo.rotation = mRotation;
+ mDisplayInfo.logicalWidth = dw;
+ mDisplayInfo.logicalHeight = dh;
+ mDisplayInfo.logicalDensityDpi = mBaseDisplayDensity;
+ mDisplayInfo.appWidth = appWidth;
+ mDisplayInfo.appHeight = appHeight;
+ if (isDefaultDisplay) {
+ mDisplayInfo.getLogicalMetrics(mRealDisplayMetrics,
+ CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null);
+ }
+ mDisplayInfo.getAppMetrics(mDisplayMetrics);
+ if (mDisplayScalingDisabled) {
+ mDisplayInfo.flags |= Display.FLAG_SCALING_DISABLED;
+ } else {
+ mDisplayInfo.flags &= ~Display.FLAG_SCALING_DISABLED;
+ }
+
+ mService.mDisplayManagerInternal.setDisplayInfoOverrideFromWindowManager(mDisplayId,
+ mDisplayInfo);
+
+ mBaseDisplayRect.set(0, 0, dw, dh);
+
+ if (isDefaultDisplay) {
+ mCompatibleScreenScale = CompatibilityInfo.computeCompatibleScaling(mDisplayMetrics,
+ mCompatDisplayMetrics);
+ }
+ return mDisplayInfo;
+ }
+
+ /**
+ * Compute display configuration based on display properties and policy settings.
+ * Do not call if mDisplayReady == false.
+ */
+ void computeScreenConfiguration(Configuration config) {
+ final DisplayInfo displayInfo = updateDisplayAndOrientation(config.uiMode);
+
+ final int dw = displayInfo.logicalWidth;
+ final int dh = displayInfo.logicalHeight;
+ config.orientation = (dw <= dh) ? Configuration.ORIENTATION_PORTRAIT :
+ Configuration.ORIENTATION_LANDSCAPE;
+ config.screenWidthDp =
+ (int)(mService.mPolicy.getConfigDisplayWidth(dw, dh, displayInfo.rotation,
+ config.uiMode, mDisplayId) / mDisplayMetrics.density);
+ config.screenHeightDp =
+ (int)(mService.mPolicy.getConfigDisplayHeight(dw, dh, displayInfo.rotation,
+ config.uiMode, mDisplayId) / mDisplayMetrics.density);
+ final boolean rotated = (displayInfo.rotation == Surface.ROTATION_90
+ || displayInfo.rotation == Surface.ROTATION_270);
+
+ computeSizeRangesAndScreenLayout(displayInfo, mDisplayId, rotated, config.uiMode, dw, dh,
+ mDisplayMetrics.density, config);
+
+ 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, mDisplayId);
+ config.densityDpi = displayInfo.logicalDensityDpi;
+
+ config.colorMode =
+ (displayInfo.isHdr()
+ ? Configuration.COLOR_MODE_HDR_YES
+ : Configuration.COLOR_MODE_HDR_NO)
+ | (displayInfo.isWideColorGamut()
+ ? Configuration.COLOR_MODE_WIDE_COLOR_GAMUT_YES
+ : Configuration.COLOR_MODE_WIDE_COLOR_GAMUT_NO);
+
+ // Update the configuration based on available input devices, lid switch,
+ // and platform configuration.
+ config.touchscreen = Configuration.TOUCHSCREEN_NOTOUCH;
+ config.keyboard = Configuration.KEYBOARD_NOKEYS;
+ config.navigation = Configuration.NAVIGATION_NONAV;
+
+ int keyboardPresence = 0;
+ int navigationPresence = 0;
+ final InputDevice[] devices = mService.mInputManager.getInputDevices();
+ final int len = devices != null ? devices.length : 0;
+ for (int i = 0; i < len; i++) {
+ InputDevice device = devices[i];
+ if (!device.isVirtual()) {
+ final int sources = device.getSources();
+ final int presenceFlag = device.isExternal() ?
+ WindowManagerPolicy.PRESENCE_EXTERNAL :
+ WindowManagerPolicy.PRESENCE_INTERNAL;
+
+ // TODO(multi-display): Configure on per-display basis.
+ if (mService.mIsTouchDevice) {
+ if ((sources & InputDevice.SOURCE_TOUCHSCREEN) ==
+ InputDevice.SOURCE_TOUCHSCREEN) {
+ config.touchscreen = Configuration.TOUCHSCREEN_FINGER;
+ }
+ } else {
+ config.touchscreen = Configuration.TOUCHSCREEN_NOTOUCH;
+ }
+
+ if ((sources & InputDevice.SOURCE_TRACKBALL) == InputDevice.SOURCE_TRACKBALL) {
+ config.navigation = Configuration.NAVIGATION_TRACKBALL;
+ navigationPresence |= presenceFlag;
+ } else if ((sources & InputDevice.SOURCE_DPAD) == InputDevice.SOURCE_DPAD
+ && config.navigation == Configuration.NAVIGATION_NONAV) {
+ config.navigation = Configuration.NAVIGATION_DPAD;
+ navigationPresence |= presenceFlag;
+ }
+
+ if (device.getKeyboardType() == InputDevice.KEYBOARD_TYPE_ALPHABETIC) {
+ config.keyboard = Configuration.KEYBOARD_QWERTY;
+ keyboardPresence |= presenceFlag;
+ }
+ }
+ }
+
+ if (config.navigation == Configuration.NAVIGATION_NONAV && mService.mHasPermanentDpad) {
+ config.navigation = Configuration.NAVIGATION_DPAD;
+ navigationPresence |= WindowManagerPolicy.PRESENCE_INTERNAL;
+ }
+
+ // Determine whether a hard keyboard is available and enabled.
+ // TODO(multi-display): Should the hardware keyboard be tied to a display or to a device?
+ boolean hardKeyboardAvailable = config.keyboard != Configuration.KEYBOARD_NOKEYS;
+ if (hardKeyboardAvailable != mService.mHardKeyboardAvailable) {
+ mService.mHardKeyboardAvailable = hardKeyboardAvailable;
+ mService.mH.removeMessages(WindowManagerService.H.REPORT_HARD_KEYBOARD_STATUS_CHANGE);
+ mService.mH.sendEmptyMessage(WindowManagerService.H.REPORT_HARD_KEYBOARD_STATUS_CHANGE);
+ }
+
+ // Let the policy update hidden states.
+ config.keyboardHidden = Configuration.KEYBOARDHIDDEN_NO;
+ config.hardKeyboardHidden = Configuration.HARDKEYBOARDHIDDEN_NO;
+ config.navigationHidden = Configuration.NAVIGATIONHIDDEN_NO;
+ mService.mPolicy.adjustConfigurationLw(config, keyboardPresence, navigationPresence);
+ }
+
+ private int computeCompatSmallestWidth(boolean rotated, int uiMode, int dw, int dh,
+ int displayId) {
+ mTmpDisplayMetrics.setTo(mDisplayMetrics);
+ final DisplayMetrics tmpDm = mTmpDisplayMetrics;
+ final int unrotDw, unrotDh;
+ if (rotated) {
+ unrotDw = dh;
+ unrotDh = dw;
+ } else {
+ unrotDw = dw;
+ unrotDh = dh;
+ }
+ int sw = reduceCompatConfigWidthSize(0, Surface.ROTATION_0, uiMode, tmpDm, unrotDw, unrotDh,
+ displayId);
+ sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_90, uiMode, tmpDm, unrotDh, unrotDw,
+ displayId);
+ sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_180, uiMode, tmpDm, unrotDw, unrotDh,
+ displayId);
+ sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_270, uiMode, tmpDm, unrotDh, unrotDw,
+ displayId);
+ return sw;
+ }
+
+ private int reduceCompatConfigWidthSize(int curSize, int rotation, int uiMode,
+ DisplayMetrics dm, int dw, int dh, int displayId) {
+ dm.noncompatWidthPixels = mService.mPolicy.getNonDecorDisplayWidth(dw, dh, rotation, uiMode,
+ displayId);
+ dm.noncompatHeightPixels = mService.mPolicy.getNonDecorDisplayHeight(dw, dh, rotation,
+ uiMode, displayId);
+ float scale = CompatibilityInfo.computeCompatibleScaling(dm, null);
+ int size = (int)(((dm.noncompatWidthPixels / scale) / dm.density) + .5f);
+ if (curSize == 0 || size < curSize) {
+ curSize = size;
+ }
+ return curSize;
+ }
+
+ private void computeSizeRangesAndScreenLayout(DisplayInfo displayInfo, int displayId,
+ boolean rotated, int uiMode, int dw, int dh, float density, Configuration outConfig) {
+
+ // We need to determine the smallest width that will occur under normal
+ // operation. To this, start with the base screen size and compute the
+ // width under the different possible rotations. We need to un-rotate
+ // the current screen dimensions before doing this.
+ int unrotDw, unrotDh;
+ if (rotated) {
+ unrotDw = dh;
+ unrotDh = dw;
+ } else {
+ unrotDw = dw;
+ unrotDh = dh;
+ }
+ displayInfo.smallestNominalAppWidth = 1<<30;
+ displayInfo.smallestNominalAppHeight = 1<<30;
+ displayInfo.largestNominalAppWidth = 0;
+ displayInfo.largestNominalAppHeight = 0;
+ adjustDisplaySizeRanges(displayInfo, displayId, Surface.ROTATION_0, uiMode, unrotDw,
+ unrotDh);
+ adjustDisplaySizeRanges(displayInfo, displayId, Surface.ROTATION_90, uiMode, unrotDh,
+ unrotDw);
+ adjustDisplaySizeRanges(displayInfo, displayId, Surface.ROTATION_180, uiMode, unrotDw,
+ unrotDh);
+ adjustDisplaySizeRanges(displayInfo, displayId, Surface.ROTATION_270, uiMode, unrotDh,
+ unrotDw);
+ int sl = Configuration.resetScreenLayout(outConfig.screenLayout);
+ sl = reduceConfigLayout(sl, Surface.ROTATION_0, density, unrotDw, unrotDh, uiMode,
+ displayId);
+ sl = reduceConfigLayout(sl, Surface.ROTATION_90, density, unrotDh, unrotDw, uiMode,
+ displayId);
+ sl = reduceConfigLayout(sl, Surface.ROTATION_180, density, unrotDw, unrotDh, uiMode,
+ displayId);
+ sl = reduceConfigLayout(sl, Surface.ROTATION_270, density, unrotDh, unrotDw, uiMode,
+ displayId);
+ outConfig.smallestScreenWidthDp = (int)(displayInfo.smallestNominalAppWidth / density);
+ outConfig.screenLayout = sl;
+ }
+
+ private int reduceConfigLayout(int curLayout, int rotation, float density, int dw, int dh,
+ int uiMode, int displayId) {
+ // Get the app screen size at this rotation.
+ int w = mService.mPolicy.getNonDecorDisplayWidth(dw, dh, rotation, uiMode, displayId);
+ int h = mService.mPolicy.getNonDecorDisplayHeight(dw, dh, rotation, uiMode, displayId);
+
+ // Compute the screen layout size class for this rotation.
+ int longSize = w;
+ int shortSize = h;
+ if (longSize < shortSize) {
+ int tmp = longSize;
+ longSize = shortSize;
+ shortSize = tmp;
+ }
+ longSize = (int)(longSize/density);
+ shortSize = (int)(shortSize/density);
+ return Configuration.reduceScreenLayout(curLayout, longSize, shortSize);
+ }
+
+ private void adjustDisplaySizeRanges(DisplayInfo displayInfo, int displayId, int rotation,
+ int uiMode, int dw, int dh) {
+ final int width = mService.mPolicy.getConfigDisplayWidth(dw, dh, rotation, uiMode,
+ displayId);
+ if (width < displayInfo.smallestNominalAppWidth) {
+ displayInfo.smallestNominalAppWidth = width;
+ }
+ if (width > displayInfo.largestNominalAppWidth) {
+ displayInfo.largestNominalAppWidth = width;
+ }
+ final int height = mService.mPolicy.getConfigDisplayHeight(dw, dh, rotation, uiMode,
+ displayId);
+ if (height < displayInfo.smallestNominalAppHeight) {
+ displayInfo.smallestNominalAppHeight = height;
+ }
+ if (height > displayInfo.largestNominalAppHeight) {
+ displayInfo.largestNominalAppHeight = height;
+ }
+ }
+
DockedStackDividerController getDockedDividerController() {
return mDividerControllerLocked;
}
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index 0222b3d..68d0f24 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -55,13 +55,11 @@
import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ADD_REMOVE;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_DISPLAY;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_KEEP_SCREEN_ON;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT_REPEATS;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ORIENTATION;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_POWER;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TOKEN_MOVEMENT;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WALLPAPER_LIGHT;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WINDOW_TRACE;
@@ -740,7 +738,7 @@
if (DEBUG_ORIENTATION) Slog.d(TAG, "Performing post-rotate rotation");
// TODO(multi-display): Update rotation for different displays separately.
final int displayId = defaultDisplay.getDisplayId();
- if (mService.updateRotationUncheckedLocked(false, displayId)) {
+ if (defaultDisplay.updateRotationUnchecked(false /* inTransaction */)) {
mService.mH.obtainMessage(SEND_NEW_CONFIGURATION, displayId).sendToTarget();
} else {
mUpdateRotation = false;
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 64614fe..b063e01 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -111,7 +111,6 @@
import android.content.IntentFilter;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
-import android.content.res.CompatibilityInfo;
import android.content.res.Configuration;
import android.database.ContentObserver;
import android.graphics.Bitmap;
@@ -592,11 +591,6 @@
boolean mIsTouchDevice;
- final DisplayMetrics mDisplayMetrics = new DisplayMetrics();
- final DisplayMetrics mRealDisplayMetrics = new DisplayMetrics();
- final DisplayMetrics mTmpDisplayMetrics = new DisplayMetrics();
- final DisplayMetrics mCompatDisplayMetrics = new DisplayMetrics();
-
final H mH = new H();
final Choreographer mChoreographer = Choreographer.getInstance();
@@ -841,9 +835,6 @@
final Configuration mTempConfiguration = new Configuration();
- // The desired scaling factor for compatible apps.
- float mCompatibleScreenScale;
-
// If true, only the core apps and services are being launched because the device
// is in a special boot mode, such as being encrypted or waiting for a decryption password.
// For example, when this flag is true, there will be no wallpaper service.
@@ -2461,10 +2452,10 @@
// to keep override configs clear of non-empty values (e.g. fontSize).
mTempConfiguration.unset();
mTempConfiguration.updateFrom(currentConfig);
- computeScreenConfigurationLocked(mTempConfiguration, displayId);
+ final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
+ displayContent.computeScreenConfiguration(mTempConfiguration);
if (currentConfig.diff(mTempConfiguration) != 0) {
mWaitingForConfig = true;
- final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
displayContent.setLayoutNeeded();
int anim[] = new int[2];
if (displayContent.isDimming()) {
@@ -2505,7 +2496,7 @@
if (dc.isDefaultDisplay) {
mPolicy.setCurrentOrientationLw(req);
}
- if (updateRotationUncheckedLocked(inTransaction, displayId)) {
+ if (dc.updateRotationUnchecked(inTransaction)) {
// changed
return true;
}
@@ -3843,10 +3834,12 @@
mDeferredRotationPauseCount -= 1;
if (mDeferredRotationPauseCount == 0) {
// TODO(multi-display): Update rotation for different displays separately.
- final int displayId = DEFAULT_DISPLAY;
- final boolean changed = updateRotationUncheckedLocked(false, displayId);
+ final DisplayContent displayContent = getDefaultDisplayContentLocked();
+ final boolean changed = displayContent.updateRotationUnchecked(
+ false /* inTransaction */);
if (changed) {
- mH.obtainMessage(H.SEND_NEW_CONFIGURATION, displayId).sendToTarget();
+ mH.obtainMessage(H.SEND_NEW_CONFIGURATION, displayContent.getDisplayId())
+ .sendToTarget();
}
}
}
@@ -3862,9 +3855,10 @@
try {
final boolean rotationChanged;
// TODO(multi-display): Update rotation for different displays separately.
- int displayId = DEFAULT_DISPLAY;
+ final DisplayContent displayContent = getDefaultDisplayContentLocked();
synchronized (mWindowMap) {
- rotationChanged = updateRotationUncheckedLocked(false, displayId);
+ rotationChanged = displayContent.updateRotationUnchecked(
+ false /* inTransaction */);
if (!rotationChanged || forceRelayout) {
getDefaultDisplayContentLocked().setLayoutNeeded();
mWindowPlacerLocked.performSurfacePlacement();
@@ -3872,234 +3866,13 @@
}
if (rotationChanged || alwaysSendConfiguration) {
- sendNewConfiguration(displayId);
+ sendNewConfiguration(displayContent.getDisplayId());
}
} finally {
Binder.restoreCallingIdentity(origId);
}
}
-
- // TODO(multidisplay): Rotate any display? Move to DisplayContent
- /**
- * Updates the current rotation of the specified display.
- *
- * Returns true if the rotation has been changed. In this case YOU MUST CALL
- * {@link #sendNewConfiguration(int)} TO UNFREEZE THE SCREEN.
- */
- boolean updateRotationUncheckedLocked(boolean inTransaction, int displayId) {
- if (mDeferredRotationPauseCount > 0) {
- // Rotation updates have been paused temporarily. Defer the update until
- // updates have been resumed.
- if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Deferring rotation, rotation is paused.");
- return false;
- }
-
- ScreenRotationAnimation screenRotationAnimation =
- mAnimator.getScreenRotationAnimationLocked(displayId);
- if (screenRotationAnimation != null && screenRotationAnimation.isAnimating()) {
- // Rotation updates cannot be performed while the previous rotation change
- // animation is still in progress. Skip this update. We will try updating
- // again after the animation is finished and the display is unfrozen.
- if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Deferring rotation, animation in progress.");
- return false;
- }
- if (mDisplayFrozen) {
- // Even if the screen rotation animation has finished (e.g. isAnimating
- // returns false), there is still some time where we haven't yet unfrozen
- // the display. We also need to abort rotation here.
- if (DEBUG_ORIENTATION) Slog.v(TAG_WM,
- "Deferring rotation, still finishing previous rotation");
- return false;
- }
-
- if (!mDisplayEnabled) {
- // No point choosing a rotation if the display is not enabled.
- if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Deferring rotation, display is not enabled.");
- return false;
- }
-
- final DisplayContent dc = mRoot.getDisplayContent(displayId);
-
- final int oldRotation = dc.getRotation();
- final int lastOrientation = dc.getLastOrientation();
- final boolean oldAltOrientation = dc.getAltOrientation();
- int rotation = mPolicy.rotationForOrientationLw(lastOrientation, oldRotation);
- final boolean rotateSeamlessly;
-
- if (mPolicy.shouldRotateSeamlessly(oldRotation, rotation)) {
- final WindowState seamlessRotated = dc.getWindow((w) -> w.mSeamlesslyRotated);
- if (seamlessRotated != null) {
- // We can't rotate (seamlessly or not) while waiting for the last seamless rotation
- // to complete (that is, waiting for windows to redraw). It's tempting to check
- // w.mSeamlessRotationCount but that could be incorrect in the case of
- // window-removal.
- return false;
- }
-
- final WindowState cantSeamlesslyRotate = dc.getWindow((w) ->
- w.isChildWindow() && w.isVisibleNow()
- && !w.mWinAnimator.mSurfaceController.getTransformToDisplayInverse());
- if (cantSeamlesslyRotate != null) {
- // In what can only be called an unfortunate workaround we require seamlessly
- // rotated child windows to have the TRANSFORM_TO_DISPLAY_INVERSE flag. Due to
- // limitations in the client API, there is no way for the client to set this flag in
- // a race free fashion. If we seamlessly rotate a window which does not have this
- // flag, but then gains it, we will get an incorrect visual result
- // (rotated viewfinder). This means if we want to support seamlessly rotating
- // windows which could gain this flag, we can't rotate windows without it. This
- // limits seamless rotation in N to camera framework users, windows without
- // children, and native code. This is unfortunate but having the camera work is our
- // primary goal.
- rotateSeamlessly = false;
- } else {
- rotateSeamlessly = true;
- }
- } else {
- rotateSeamlessly = false;
- }
-
- // TODO: Implement forced rotation changes.
- // Set mAltOrientation to indicate that the application is receiving
- // an orientation that has different metrics than it expected.
- // eg. Portrait instead of Landscape.
-
- boolean altOrientation = !mPolicy.rotationHasCompatibleMetricsLw(lastOrientation, rotation);
-
- if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Selected orientation " + lastOrientation
- + ", got rotation " + rotation + " which has "
- + (altOrientation ? "incompatible" : "compatible") + " metrics");
-
- if (oldRotation == rotation && oldAltOrientation == altOrientation) {
- // No change.
- return false;
- }
-
- if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Rotation changed to " + rotation
- + (altOrientation ? " (alt)" : "") + " from " + oldRotation
- + (oldAltOrientation ? " (alt)" : "") + ", lastOrientation=" + lastOrientation);
-
- if (DisplayContent.deltaRotation(rotation, oldRotation) != 2) {
- mWaitingForConfig = true;
- }
-
- dc.setRotation(rotation);
- dc.setAltOrientation(altOrientation);
- if (dc.isDefaultDisplay) {
- mPolicy.setRotationLw(rotation);
- }
-
- mWindowsFreezingScreen = WINDOWS_FREEZING_SCREENS_ACTIVE;
- mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT);
- mH.sendEmptyMessageDelayed(H.WINDOW_FREEZE_TIMEOUT, WINDOW_FREEZE_TIMEOUT_DURATION);
-
- dc.setLayoutNeeded();
- final int[] anim = new int[2];
- if (dc.isDimming()) {
- anim[0] = anim[1] = 0;
- } else {
- mPolicy.selectRotationAnimationLw(anim);
- }
-
- if (!rotateSeamlessly) {
- startFreezingDisplayLocked(inTransaction, anim[0], anim[1]);
- // startFreezingDisplayLocked can reset the ScreenRotationAnimation.
- screenRotationAnimation = mAnimator.getScreenRotationAnimationLocked(displayId);
- } else {
- // The screen rotation animation uses a screenshot to freeze the screen
- // while windows resize underneath.
- // When we are rotating seamlessly, we allow the elements to transition
- // to their rotated state independently and without a freeze required.
- screenRotationAnimation = null;
-
- // We have to reset this in case a window was removed before it
- // finished seamless rotation.
- mSeamlessRotationCount = 0;
- }
-
- // We need to update our screen size information to match the new rotation. If the rotation
- // has actually changed then this method will return true and, according to the comment at
- // the top of the method, the caller is obligated to call computeNewConfigurationLocked().
- // By updating the Display info here it will be available to
- // computeScreenConfigurationLocked later.
- updateDisplayAndOrientationLocked(dc.getConfiguration().uiMode, displayId);
-
- final DisplayInfo displayInfo = dc.getDisplayInfo();
- if (!inTransaction) {
- if (SHOW_TRANSACTIONS) {
- Slog.i(TAG_WM, ">>> OPEN TRANSACTION setRotationUnchecked");
- }
- openSurfaceTransaction();
- }
- try {
- // NOTE: We disable the rotation in the emulator because
- // it doesn't support hardware OpenGL emulation yet.
- if (CUSTOM_SCREEN_ROTATION && screenRotationAnimation != null
- && screenRotationAnimation.hasScreenshot()) {
- if (screenRotationAnimation.setRotationInTransaction(
- rotation, mFxSession,
- MAX_ANIMATION_DURATION, getTransitionAnimationScaleLocked(),
- displayInfo.logicalWidth, displayInfo.logicalHeight)) {
- scheduleAnimationLocked();
- }
- }
-
- if (rotateSeamlessly) {
- dc.forAllWindows(w -> {
- w.mWinAnimator.seamlesslyRotateWindow(oldRotation, rotation);
- }, true /* traverseTopToBottom */);
- }
-
- mDisplayManagerInternal.performTraversalInTransactionFromWindowManager();
- } finally {
- if (!inTransaction) {
- closeSurfaceTransaction();
- if (SHOW_LIGHT_TRANSACTIONS) {
- Slog.i(TAG_WM, "<<< CLOSE TRANSACTION setRotationUnchecked");
- }
- }
- }
-
- dc.forAllWindows(w -> {
- // Discard surface after orientation change, these can't be reused.
- if (w.mAppToken != null) {
- w.mAppToken.destroySavedSurfaces();
- }
- if (w.mHasSurface && !rotateSeamlessly) {
- if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Set mOrientationChanging of " + w);
- w.mOrientationChanging = true;
- mRoot.mOrientationChangeComplete = false;
- w.mLastFreezeDuration = 0;
- }
- w.mReportOrientationChanged = true;
- }, true /* traverseTopToBottom */);
-
- if (rotateSeamlessly) {
- mH.removeMessages(H.SEAMLESS_ROTATION_TIMEOUT);
- mH.sendEmptyMessageDelayed(H.SEAMLESS_ROTATION_TIMEOUT, SEAMLESS_ROTATION_TIMEOUT_DURATION);
- }
-
- for (int i = mRotationWatchers.size() - 1; i >= 0; i--) {
- final RotationWatcher rotationWatcher = mRotationWatchers.get(i);
- if (rotationWatcher.mDisplayId == displayId) {
- try {
- rotationWatcher.mWatcher.onRotationChanged(rotation);
- } catch (RemoteException e) {
- }
- }
- }
-
- // TODO (multidisplay): Magnification is supported only for the default display.
- // Announce rotation only if we will not animate as we already have the
- // windows in final state. Otherwise, we make this call at the rotation end.
- if (screenRotationAnimation == null && mAccessibilityController != null
- && dc.getDisplayId() == DEFAULT_DISPLAY) {
- mAccessibilityController.onRotationChangedLocked(getDefaultDisplayContentLocked());
- }
-
- return true;
- }
-
@Override
public int getDefaultDisplayRotation() {
synchronized (mWindowMap) {
@@ -4572,7 +4345,7 @@
// Something changed (E.g. device rotation), but no configuration update is needed.
// E.g. changing device rotation by 180 degrees. Go ahead and perform surface
// placement to unfreeze the display since we froze it when the rotation was updated
- // in updateRotationUncheckedLocked.
+ // in DisplayContent#updateRotationUnchecked.
synchronized (mWindowMap) {
if (mWaitingForConfig) {
mWaitingForConfig = false;
@@ -4597,297 +4370,9 @@
return null;
}
final Configuration config = new Configuration();
- computeScreenConfigurationLocked(config, displayId);
- return config;
- }
-
- private void adjustDisplaySizeRanges(DisplayInfo displayInfo, int displayId, int rotation,
- int uiMode, int dw, int dh) {
- final int width = mPolicy.getConfigDisplayWidth(dw, dh, rotation, uiMode, displayId);
- if (width < displayInfo.smallestNominalAppWidth) {
- displayInfo.smallestNominalAppWidth = width;
- }
- if (width > displayInfo.largestNominalAppWidth) {
- displayInfo.largestNominalAppWidth = width;
- }
- final int height = mPolicy.getConfigDisplayHeight(dw, dh, rotation, uiMode, displayId);
- if (height < displayInfo.smallestNominalAppHeight) {
- displayInfo.smallestNominalAppHeight = height;
- }
- if (height > displayInfo.largestNominalAppHeight) {
- displayInfo.largestNominalAppHeight = height;
- }
- }
-
- private int reduceConfigLayout(int curLayout, int rotation, float density,
- int dw, int dh, int uiMode, int displayId) {
- // Get the app screen size at this rotation.
- int w = mPolicy.getNonDecorDisplayWidth(dw, dh, rotation, uiMode, displayId);
- int h = mPolicy.getNonDecorDisplayHeight(dw, dh, rotation, uiMode, displayId);
-
- // Compute the screen layout size class for this rotation.
- int longSize = w;
- int shortSize = h;
- if (longSize < shortSize) {
- int tmp = longSize;
- longSize = shortSize;
- shortSize = tmp;
- }
- longSize = (int)(longSize/density);
- shortSize = (int)(shortSize/density);
- return Configuration.reduceScreenLayout(curLayout, longSize, shortSize);
- }
-
- private void computeSizeRangesAndScreenLayout(DisplayInfo displayInfo, int displayId,
- boolean rotated, int uiMode, int dw, int dh, float density, Configuration outConfig) {
-
- // We need to determine the smallest width that will occur under normal
- // operation. To this, start with the base screen size and compute the
- // width under the different possible rotations. We need to un-rotate
- // the current screen dimensions before doing this.
- int unrotDw, unrotDh;
- if (rotated) {
- unrotDw = dh;
- unrotDh = dw;
- } else {
- unrotDw = dw;
- unrotDh = dh;
- }
- displayInfo.smallestNominalAppWidth = 1<<30;
- displayInfo.smallestNominalAppHeight = 1<<30;
- displayInfo.largestNominalAppWidth = 0;
- displayInfo.largestNominalAppHeight = 0;
- adjustDisplaySizeRanges(displayInfo, displayId, Surface.ROTATION_0, uiMode, unrotDw,
- unrotDh);
- adjustDisplaySizeRanges(displayInfo, displayId, Surface.ROTATION_90, uiMode, unrotDh,
- unrotDw);
- adjustDisplaySizeRanges(displayInfo, displayId, Surface.ROTATION_180, uiMode, unrotDw,
- unrotDh);
- adjustDisplaySizeRanges(displayInfo, displayId, Surface.ROTATION_270, uiMode, unrotDh,
- unrotDw);
- int sl = Configuration.resetScreenLayout(outConfig.screenLayout);
- sl = reduceConfigLayout(sl, Surface.ROTATION_0, density, unrotDw, unrotDh, uiMode,
- displayId);
- sl = reduceConfigLayout(sl, Surface.ROTATION_90, density, unrotDh, unrotDw, uiMode,
- displayId);
- sl = reduceConfigLayout(sl, Surface.ROTATION_180, density, unrotDw, unrotDh, uiMode,
- displayId);
- sl = reduceConfigLayout(sl, Surface.ROTATION_270, density, unrotDh, unrotDw, uiMode,
- displayId);
- outConfig.smallestScreenWidthDp = (int)(displayInfo.smallestNominalAppWidth / density);
- outConfig.screenLayout = sl;
- }
-
- private int reduceCompatConfigWidthSize(int curSize, int rotation, int uiMode,
- DisplayMetrics dm, int dw, int dh, int displayId) {
- dm.noncompatWidthPixels = mPolicy.getNonDecorDisplayWidth(dw, dh, rotation, uiMode,
- displayId);
- dm.noncompatHeightPixels = mPolicy.getNonDecorDisplayHeight(dw, dh, rotation, uiMode,
- displayId);
- float scale = CompatibilityInfo.computeCompatibleScaling(dm, null);
- int size = (int)(((dm.noncompatWidthPixels / scale) / dm.density) + .5f);
- if (curSize == 0 || size < curSize) {
- curSize = size;
- }
- return curSize;
- }
-
- private int computeCompatSmallestWidth(boolean rotated, int uiMode, DisplayMetrics dm, int dw,
- int dh, int displayId) {
- mTmpDisplayMetrics.setTo(dm);
- final DisplayMetrics tmpDm = mTmpDisplayMetrics;
- final int unrotDw, unrotDh;
- if (rotated) {
- unrotDw = dh;
- unrotDh = dw;
- } else {
- unrotDw = dw;
- unrotDh = dh;
- }
- int sw = reduceCompatConfigWidthSize(0, Surface.ROTATION_0, uiMode, tmpDm, unrotDw, unrotDh,
- displayId);
- sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_90, uiMode, tmpDm, unrotDh, unrotDw,
- displayId);
- sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_180, uiMode, tmpDm, unrotDw, unrotDh,
- displayId);
- sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_270, uiMode, tmpDm, unrotDh, unrotDw,
- displayId);
- return sw;
- }
-
- /** Do not call if mDisplayReady == false */
- private DisplayInfo updateDisplayAndOrientationLocked(int uiMode, int displayId) {
final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
-
- // TODO(multi-display): Implement rotation for secondary displays.
- final boolean isDefaultDisplay = displayContent.isDefaultDisplay;
- final int displayRotation = displayContent.getRotation();
- final boolean altDisplayOrientation = displayContent.getAltOrientation();
-
- // Use the effective "visual" dimensions based on current rotation
- final boolean rotated = (displayRotation == Surface.ROTATION_90
- || displayRotation == Surface.ROTATION_270);
- final int realdw = rotated ?
- displayContent.mBaseDisplayHeight : displayContent.mBaseDisplayWidth;
- final int realdh = rotated ?
- displayContent.mBaseDisplayWidth : displayContent.mBaseDisplayHeight;
- int dw = realdw;
- int dh = realdh;
-
- if (altDisplayOrientation) {
- if (realdw > realdh) {
- // Turn landscape into portrait.
- int maxw = (int)(realdh/1.3f);
- if (maxw < realdw) {
- dw = maxw;
- }
- } else {
- // Turn portrait into landscape.
- int maxh = (int)(realdw/1.3f);
- if (maxh < realdh) {
- dh = maxh;
- }
- }
- }
-
- // Update application display metrics.
- final int appWidth = mPolicy.getNonDecorDisplayWidth(dw, dh, displayRotation, uiMode,
- displayId);
- final int appHeight = mPolicy.getNonDecorDisplayHeight(dw, dh, displayRotation, uiMode,
- displayId);
- final DisplayInfo displayInfo = displayContent.getDisplayInfo();
- displayInfo.rotation = displayRotation;
- displayInfo.logicalWidth = dw;
- displayInfo.logicalHeight = dh;
- displayInfo.logicalDensityDpi = displayContent.mBaseDisplayDensity;
- displayInfo.appWidth = appWidth;
- displayInfo.appHeight = appHeight;
- if (isDefaultDisplay) {
- displayInfo.getLogicalMetrics(mRealDisplayMetrics,
- CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null);
- }
- displayInfo.getAppMetrics(mDisplayMetrics);
- if (displayContent.mDisplayScalingDisabled) {
- displayInfo.flags |= Display.FLAG_SCALING_DISABLED;
- } else {
- displayInfo.flags &= ~Display.FLAG_SCALING_DISABLED;
- }
-
- mDisplayManagerInternal.setDisplayInfoOverrideFromWindowManager(
- displayContent.getDisplayId(), displayInfo);
-
- displayContent.mBaseDisplayRect.set(0, 0, dw, dh);
- if (false) {
- Slog.i(TAG_WM, "Set app display size: " + appWidth + " x " + appHeight);
- }
-
- if (isDefaultDisplay) {
- mCompatibleScreenScale = CompatibilityInfo.computeCompatibleScaling(mDisplayMetrics,
- mCompatDisplayMetrics);
- }
- return displayInfo;
- }
-
- /** Do not call if mDisplayReady == false */
- private void computeScreenConfigurationLocked(Configuration config, int displayId) {
- final DisplayInfo displayInfo = updateDisplayAndOrientationLocked(config.uiMode, displayId);
-
- final int dw = displayInfo.logicalWidth;
- final int dh = displayInfo.logicalHeight;
- config.orientation = (dw <= dh) ? Configuration.ORIENTATION_PORTRAIT :
- Configuration.ORIENTATION_LANDSCAPE;
- config.screenWidthDp =
- (int)(mPolicy.getConfigDisplayWidth(dw, dh, displayInfo.rotation, config.uiMode,
- displayId) / mDisplayMetrics.density);
- config.screenHeightDp =
- (int)(mPolicy.getConfigDisplayHeight(dw, dh, displayInfo.rotation, config.uiMode,
- displayId) / mDisplayMetrics.density);
- final boolean rotated = (displayInfo.rotation == Surface.ROTATION_90
- || displayInfo.rotation == Surface.ROTATION_270);
-
- computeSizeRangesAndScreenLayout(displayInfo, displayId, rotated, config.uiMode, dw, dh,
- mDisplayMetrics.density, config);
-
- 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,
- mDisplayMetrics, dw, dh, displayId);
- config.densityDpi = displayInfo.logicalDensityDpi;
-
- config.colorMode =
- (displayInfo.isHdr()
- ? Configuration.COLOR_MODE_HDR_YES
- : Configuration.COLOR_MODE_HDR_NO)
- | (displayInfo.isWideColorGamut()
- ? Configuration.COLOR_MODE_WIDE_COLOR_GAMUT_YES
- : Configuration.COLOR_MODE_WIDE_COLOR_GAMUT_NO);
-
- // Update the configuration based on available input devices, lid switch,
- // and platform configuration.
- config.touchscreen = Configuration.TOUCHSCREEN_NOTOUCH;
- config.keyboard = Configuration.KEYBOARD_NOKEYS;
- config.navigation = Configuration.NAVIGATION_NONAV;
-
- int keyboardPresence = 0;
- int navigationPresence = 0;
- final InputDevice[] devices = mInputManager.getInputDevices();
- final int len = devices != null ? devices.length : 0;
- for (int i = 0; i < len; i++) {
- InputDevice device = devices[i];
- if (!device.isVirtual()) {
- final int sources = device.getSources();
- final int presenceFlag = device.isExternal() ?
- WindowManagerPolicy.PRESENCE_EXTERNAL :
- WindowManagerPolicy.PRESENCE_INTERNAL;
-
- if (mIsTouchDevice) {
- if ((sources & InputDevice.SOURCE_TOUCHSCREEN) ==
- InputDevice.SOURCE_TOUCHSCREEN) {
- config.touchscreen = Configuration.TOUCHSCREEN_FINGER;
- }
- } else {
- config.touchscreen = Configuration.TOUCHSCREEN_NOTOUCH;
- }
-
- if ((sources & InputDevice.SOURCE_TRACKBALL) == InputDevice.SOURCE_TRACKBALL) {
- config.navigation = Configuration.NAVIGATION_TRACKBALL;
- navigationPresence |= presenceFlag;
- } else if ((sources & InputDevice.SOURCE_DPAD) == InputDevice.SOURCE_DPAD
- && config.navigation == Configuration.NAVIGATION_NONAV) {
- config.navigation = Configuration.NAVIGATION_DPAD;
- navigationPresence |= presenceFlag;
- }
-
- if (device.getKeyboardType() == InputDevice.KEYBOARD_TYPE_ALPHABETIC) {
- config.keyboard = Configuration.KEYBOARD_QWERTY;
- keyboardPresence |= presenceFlag;
- }
- }
- }
-
- if (config.navigation == Configuration.NAVIGATION_NONAV && mHasPermanentDpad) {
- config.navigation = Configuration.NAVIGATION_DPAD;
- navigationPresence |= WindowManagerPolicy.PRESENCE_INTERNAL;
- }
-
- // Determine whether a hard keyboard is available and enabled.
- boolean hardKeyboardAvailable = config.keyboard != Configuration.KEYBOARD_NOKEYS;
- if (hardKeyboardAvailable != mHardKeyboardAvailable) {
- mHardKeyboardAvailable = hardKeyboardAvailable;
- mH.removeMessages(H.REPORT_HARD_KEYBOARD_STATUS_CHANGE);
- mH.sendEmptyMessage(H.REPORT_HARD_KEYBOARD_STATUS_CHANGE);
- }
-
- // Let the policy update hidden states.
- config.keyboardHidden = Configuration.KEYBOARDHIDDEN_NO;
- config.hardKeyboardHidden = Configuration.HARDKEYBOARDHIDDEN_NO;
- config.navigationHidden = Configuration.NAVIGATIONHIDDEN_NO;
- mPolicy.adjustConfigurationLw(config, keyboardPresence, navigationPresence);
+ displayContent.computeScreenConfiguration(config);
+ return config;
}
void notifyHardKeyboardStatusChange() {
@@ -6099,7 +5584,7 @@
displayId);
final Configuration currentDisplayConfig = displayContent.getConfiguration();
mTempConfiguration.setTo(currentDisplayConfig);
- computeScreenConfigurationLocked(mTempConfiguration, displayId);
+ displayContent.computeScreenConfiguration(mTempConfiguration);
configChanged |= currentDisplayConfig.diff(mTempConfiguration) != 0;
if (configChanged) {
@@ -6562,7 +6047,8 @@
if (updateRotation) {
if (DEBUG_ORIENTATION) Slog.d(TAG_WM, "Performing post-rotate rotation");
- configChanged |= updateRotationUncheckedLocked(false, displayId);
+ configChanged |= displayContent.updateRotationUnchecked(
+ false /* inTransaction */);
}
if (configChanged) {
@@ -6605,8 +6091,9 @@
String[] toks = line.split("%");
if (toks != null && toks.length > 0) {
// TODO(multi-display): Show watermarks on secondary displays.
- mWatermark = new Watermark(getDefaultDisplayContentLocked().getDisplay(),
- mRealDisplayMetrics, mFxSession, toks);
+ final DisplayContent displayContent = getDefaultDisplayContentLocked();
+ mWatermark = new Watermark(displayContent.getDisplay(),
+ displayContent.mRealDisplayMetrics, mFxSession, toks);
}
}
} catch (FileNotFoundException e) {
@@ -7642,9 +7129,10 @@
if (DEBUG_ORIENTATION) {
Slog.i(TAG, "Performing post-rotate rotation after seamless rotation");
}
- final int displayId = w.getDisplayId();
- if (updateRotationUncheckedLocked(false, displayId)) {
- mH.obtainMessage(H.SEND_NEW_CONFIGURATION, displayId).sendToTarget();
+ final DisplayContent displayContent = w.getDisplayContent();
+ if (displayContent.updateRotationUnchecked(false /* inTransaction */)) {
+ mH.obtainMessage(H.SEND_NEW_CONFIGURATION, displayContent.getDisplayId())
+ .sendToTarget();
}
}
}
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index ccbc5ba..4e593d8 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -1273,8 +1273,8 @@
void prelayout() {
if (mEnforceSizeCompat) {
- mGlobalScale = mService.mCompatibleScreenScale;
- mInvGlobalScale = 1/mGlobalScale;
+ mGlobalScale = getDisplayContent().mCompatibleScreenScale;
+ mInvGlobalScale = 1 / mGlobalScale;
} else {
mGlobalScale = mInvGlobalScale = 1;
}