diff options
author | 2016-10-04 20:58:42 +0000 | |
---|---|---|
committer | 2016-10-04 20:58:44 +0000 | |
commit | c65dc5529e72b8dfdb72b6d8739489ea68653000 (patch) | |
tree | 85d0dff5b21971bde59d807920967b5e07993f28 | |
parent | 3523728e77a76127fa728e5267f7f429c87b399a (diff) | |
parent | b14d4abc16ec7dd48737ab829e3f84b12017db7c (diff) |
Merge changes I99f18930,I5f6830d8 into nyc-mr1-dev
* changes:
Prevent any rotation while seamless rotation is pending.
Prevent triggering orientation changes until previous completes.
-rw-r--r-- | services/core/java/com/android/server/wm/WindowManagerService.java | 103 | ||||
-rw-r--r-- | services/core/java/com/android/server/wm/WindowStateAnimator.java | 4 |
2 files changed, 73 insertions, 34 deletions
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index ce0ad25ebcc6..7a73759f0388 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -654,6 +654,12 @@ public class WindowManagerService extends IWindowManager.Stub WindowManagerInternal.OnHardKeyboardStatusChangeListener mHardKeyboardStatusChangeListener; SettingsObserver mSettingsObserver; + // A count of the windows which are 'seamlessly rotated', e.g. a surface + // at an old orientation is being transformed. We freeze orientation updates + // while any windows are seamlessly rotated, so we need to track when this + // hits zero so we can apply deferred orientation updates. + int mSeamlessRotationCount = 0; + private final class SettingsObserver extends ContentObserver { private final Uri mDisplayInversionEnabledUri = Settings.Secure.getUriFor(Settings.Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED); @@ -6807,6 +6813,13 @@ public class WindowManagerService extends IWindowManager.Stub 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. @@ -6814,6 +6827,38 @@ public class WindowManagerService extends IWindowManager.Stub return false; } + final DisplayContent displayContent = getDefaultDisplayContentLocked(); + final WindowList windows = displayContent.getWindowList(); + + final int oldRotation = mRotation; + boolean rotateSeamlessly = mPolicy.shouldRotateSeamlessly(oldRotation, mRotation); + + if (rotateSeamlessly) { + for (int i = windows.size() - 1; i >= 0; i--) { + WindowState w = windows.get(i); + // 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. + if (w.mSeamlesslyRotated) { + return false; + } + // 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. + if (w.isChildWindow() & w.isVisibleNow() && + !w.mWinAnimator.mSurfaceController.getTransformToDisplayInverse()) { + 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. @@ -6832,7 +6877,7 @@ public class WindowManagerService extends IWindowManager.Stub if (mRotation == rotation && mAltOrientation == altOrientation) { // No change. - return false; + return false; } if (DEBUG_ORIENTATION) { @@ -6842,8 +6887,6 @@ public class WindowManagerService extends IWindowManager.Stub + ", lastOrientation=" + mLastOrientation); } - int oldRotation = mRotation; - mRotation = rotation; mAltOrientation = altOrientation; mPolicy.setRotationLw(mRotation); @@ -6852,7 +6895,6 @@ public class WindowManagerService extends IWindowManager.Stub mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT); mH.sendEmptyMessageDelayed(H.WINDOW_FREEZE_TIMEOUT, WINDOW_FREEZE_TIMEOUT_DURATION); mWaitingForConfig = true; - final DisplayContent displayContent = getDefaultDisplayContentLocked(); displayContent.layoutNeeded = true; final int[] anim = new int[2]; if (displayContent.isDimming()) { @@ -6860,33 +6902,6 @@ public class WindowManagerService extends IWindowManager.Stub } else { mPolicy.selectRotationAnimationLw(anim); } - boolean rotateSeamlessly = mPolicy.shouldRotateSeamlessly(oldRotation, mRotation); - final WindowList windows = displayContent.getWindowList(); - // We can't rotate seamlessly while an existing seamless rotation is still - // waiting on windows to finish drawing. - if (rotateSeamlessly) { - for (int i = windows.size() - 1; i >= 0; i--) { - WindowState w = windows.get(i); - if (w.mSeamlesslyRotated) { - rotateSeamlessly = false; - break; - } - // 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. - if (w.isChildWindow() & w.isVisibleNow() && - !w.mWinAnimator.mSurfaceController.getTransformToDisplayInverse()) { - rotateSeamlessly = false; - } - } - } if (!rotateSeamlessly) { startFreezingDisplayLocked(inTransaction, anim[0], anim[1]); @@ -6899,6 +6914,10 @@ public class WindowManagerService extends IWindowManager.Stub // 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 @@ -8914,8 +8933,8 @@ public class WindowManagerService extends IWindowManager.Stub if (w.mSeamlesslyRotated) { layoutNeeded = true; w.setDisplayLayoutNeeded(); + markForSeamlessRotation(w, false); } - w.mSeamlesslyRotated = false; } if (layoutNeeded) { mWindowPlacerLocked.performSurfacePlacement(); @@ -11501,6 +11520,26 @@ public class WindowManagerService extends IWindowManager.Stub mPolicy.registerShortcutKey(shortcutCode, shortcutKeyReceiver); } + void markForSeamlessRotation(WindowState w, boolean seamlesslyRotated) { + if (seamlesslyRotated == w.mSeamlesslyRotated) { + return; + } + w.mSeamlesslyRotated = seamlesslyRotated; + if (seamlesslyRotated) { + mSeamlessRotationCount++; + } else { + mSeamlessRotationCount--; + } + if (mSeamlessRotationCount == 0) { + if (DEBUG_ORIENTATION) { + Slog.i(TAG, "Performing post-rotate rotation after seamless rotation"); + } + if (updateRotationUncheckedLocked(false)) { + mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); + } + } + } + private final class LocalService extends WindowManagerInternal { @Override public void requestTraversalFromDisplayManager() { diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java index 0285f7075e95..650dac91eb7f 100644 --- a/services/core/java/com/android/server/wm/WindowStateAnimator.java +++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java @@ -1431,7 +1431,7 @@ class WindowStateAnimator { // If we are undergoing seamless rotation, the surface has already // been set up to persist at it's old location. We need to freeze // updates until a resize occurs. - w.mSeamlesslyRotated = w.mSeamlesslyRotated && !mSurfaceResized; + mService.markForSeamlessRotation(w, w.mSeamlesslyRotated && !mSurfaceResized); calculateSurfaceWindowCrop(mTmpClipRect, mTmpFinalClipRect); @@ -2156,7 +2156,7 @@ class WindowStateAnimator { cropRect.set(0, 0, w.mRequestedWidth, w.mRequestedWidth + w.mRequestedHeight); mSurfaceController.setCropInTransaction(cropRect, false); } else { - w.mSeamlesslyRotated = true; + mService.markForSeamlessRotation(w, true); transform.getValues(mService.mTmpFloats); float DsDx = mService.mTmpFloats[Matrix.MSCALE_X]; |