From bfa81adfbe1819d55737dbbb2fb9157e50dbe022 Mon Sep 17 00:00:00 2001 From: Wale Ogunwale Date: Wed, 24 May 2017 15:14:42 -0700 Subject: [PATCH] Fix unnecessary relaunches when unlocking with fingerprint sensor. When the device is unlocked using the fingerprint sensor in an orientation opposite to the lockscreen orientation, the app that will be visible is first relaunched in the current lockscreen orientation and then later relaunched in the correct orientation. If the keygaurd is going away then: - Don't let keyguard affect device orientation. We want to use the orientation of the app that will be visible. - Allow the rotation sensor to be enabled even though draw isn't complete so window manager can get the updated or last rotation reading. - Don't clear the previous proposed sensor reading to allow window manager to use the information to update the orientation as needed vs. falling back to the previous orientation. Change-Id: I8369723d6a77f2c602f1ef080371fa7cd9ee094e Fixes: 38494778 Test: Launch an app that doesn't fix orientation like clock, hold the device in landscape, press the power button, unlock the device using the fingerprint sensor, and verify the the app isn't relaunched. --- .../android/view/WindowManagerInternal.java | 3 + .../android/server/am/KeyguardController.java | 9 ++- .../server/policy/PhoneWindowManager.java | 18 ++++-- .../policy/WindowOrientationListener.java | 58 +++++++++++++------ .../com/android/server/wm/DisplayContent.java | 7 ++- .../server/wm/WindowManagerService.java | 14 ++++- .../com/android/server/wm/WindowState.java | 2 +- 7 files changed, 82 insertions(+), 29 deletions(-) diff --git a/core/java/android/view/WindowManagerInternal.java b/core/java/android/view/WindowManagerInternal.java index bf0e10f993ad7..55aed529037df 100644 --- a/core/java/android/view/WindowManagerInternal.java +++ b/core/java/android/view/WindowManagerInternal.java @@ -225,6 +225,9 @@ public abstract class WindowManagerInternal { */ public abstract boolean isKeyguardLocked(); + /** @return {@code true} if the keyguard is going away. */ + public abstract boolean isKeyguardGoingAway(); + /** * Gets the frame of a window given its token. * diff --git a/services/core/java/com/android/server/am/KeyguardController.java b/services/core/java/com/android/server/am/KeyguardController.java index 144eb11cbf854..2e0ec0b361e2b 100644 --- a/services/core/java/com/android/server/am/KeyguardController.java +++ b/services/core/java/com/android/server/am/KeyguardController.java @@ -97,7 +97,7 @@ class KeyguardController { mKeyguardShowing = showing; dismissDockedStackIfNeeded(); if (showing) { - mKeyguardGoingAway = false; + setKeyguardGoingAway(false); mDismissalRequested = false; } mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS); @@ -114,7 +114,7 @@ class KeyguardController { if (mKeyguardShowing) { mWindowManager.deferSurfaceLayout(); try { - mKeyguardGoingAway = true; + setKeyguardGoingAway(true); mWindowManager.prepareAppTransition(TRANSIT_KEYGUARD_GOING_AWAY, false /* alwaysKeepCurrent */, convertTransitFlags(flags), false /* forceOverride */); @@ -139,6 +139,11 @@ class KeyguardController { mWindowManager.dismissKeyguard(callback); } + private void setKeyguardGoingAway(boolean keyguardGoingAway) { + mKeyguardGoingAway = keyguardGoingAway; + mWindowManager.setKeyguardGoingAway(keyguardGoingAway); + } + private void failCallback(IKeyguardDismissCallback callback) { try { callback.onDismissError(); diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java index 908e51711b113..e3bc91971b06e 100644 --- a/services/core/java/com/android/server/policy/PhoneWindowManager.java +++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java @@ -60,7 +60,6 @@ import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_DRAW_ST import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_STATUS_BAR_VISIBLE_TRANSPARENT; import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD; import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS; -import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_TASK_SNAPSHOT; import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_SYSTEM_ERROR; import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_CROSSFADE; import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_JUMPCUT; @@ -1128,16 +1127,25 @@ public class PhoneWindowManager implements WindowManagerPolicy { + ", mOrientationSensorEnabled=" + mOrientationSensorEnabled + ", mKeyguardDrawComplete=" + mKeyguardDrawComplete + ", mWindowManagerDrawComplete=" + mWindowManagerDrawComplete); + final boolean keyguardGoingAway = mWindowManagerInternal.isKeyguardGoingAway(); + boolean disable = true; // Note: We postpone the rotating of the screen until the keyguard as well as the - // window manager have reported a draw complete. - if (mScreenOnEarly && mAwake && - mKeyguardDrawComplete && mWindowManagerDrawComplete) { + // window manager have reported a draw complete or the keyguard is going away in dismiss + // mode. + if (mScreenOnEarly && mAwake && ((mKeyguardDrawComplete && mWindowManagerDrawComplete) + || keyguardGoingAway)) { if (needSensorRunningLp()) { disable = false; //enable listener if not already enabled if (!mOrientationSensorEnabled) { - mOrientationListener.enable(); + // Don't clear the current sensor orientation if the keyguard is going away in + // dismiss mode. This allows window manager to use the last sensor reading to + // determine the orientation vs. falling back to the last known orientation if + // the sensor reading was cleared which can cause it to relaunch the app that + // will show in the wrong orientation first before correcting leading to app + // launch delays. + mOrientationListener.enable(!keyguardGoingAway /* clearCurrentRotation */); if(localLOGV) Slog.v(TAG, "Enabling listeners"); mOrientationSensorEnabled = true; } diff --git a/services/core/java/com/android/server/policy/WindowOrientationListener.java b/services/core/java/com/android/server/policy/WindowOrientationListener.java index 8ef0acbd38080..64f64c0d45d61 100644 --- a/services/core/java/com/android/server/policy/WindowOrientationListener.java +++ b/services/core/java/com/android/server/policy/WindowOrientationListener.java @@ -109,24 +109,37 @@ public abstract class WindowOrientationListener { * {@link #onProposedRotationChanged(int)} when the device orientation changes. */ public void enable() { + enable(true /* clearCurrentRotation */); + } + + /** + * Enables the WindowOrientationListener so it will monitor the sensor and call + * {@link #onProposedRotationChanged(int)} when the device orientation changes. + * + * @param clearCurrentRotation True if the current proposed sensor rotation should be cleared as + * part of the reset. + */ + public void enable(boolean clearCurrentRotation) { synchronized (mLock) { if (mSensor == null) { Slog.w(TAG, "Cannot detect sensors. Not enabled"); return; } - if (mEnabled == false) { - if (LOG) { - Slog.d(TAG, "WindowOrientationListener enabled"); - } - mOrientationJudge.resetLocked(); - if (mSensor.getType() == Sensor.TYPE_ACCELEROMETER) { - mSensorManager.registerListener( - mOrientationJudge, mSensor, mRate, DEFAULT_BATCH_LATENCY, mHandler); - } else { - mSensorManager.registerListener(mOrientationJudge, mSensor, mRate, mHandler); - } - mEnabled = true; + if (mEnabled) { + return; } + if (LOG) { + Slog.d(TAG, "WindowOrientationListener enabled clearCurrentRotation=" + + clearCurrentRotation); + } + mOrientationJudge.resetLocked(clearCurrentRotation); + if (mSensor.getType() == Sensor.TYPE_ACCELEROMETER) { + mSensorManager.registerListener( + mOrientationJudge, mSensor, mRate, DEFAULT_BATCH_LATENCY, mHandler); + } else { + mSensorManager.registerListener(mOrientationJudge, mSensor, mRate, mHandler); + } + mEnabled = true; } } @@ -278,8 +291,11 @@ public abstract class WindowOrientationListener { * Resets the state of the judge. * * Should only be called when holding WindowOrientationListener lock. + * + * @param clearCurrentRotation True if the current proposed sensor rotation should be + * cleared as part of the reset. */ - public abstract void resetLocked(); + public abstract void resetLocked(boolean clearCurrentRotation); /** * Dumps internal state of the orientation judge. @@ -602,7 +618,7 @@ public abstract class WindowOrientationListener { if (LOG) { Slog.v(TAG, "Resetting orientation listener."); } - resetLocked(); + resetLocked(true /* clearCurrentRotation */); skipSample = true; } else { final float alpha = timeDeltaMS / (FILTER_TIME_CONSTANT_MS + timeDeltaMS); @@ -778,9 +794,11 @@ public abstract class WindowOrientationListener { } @Override - public void resetLocked() { + public void resetLocked(boolean clearCurrentRotation) { mLastFilteredTimestampNanos = Long.MIN_VALUE; - mProposedRotation = -1; + if (clearCurrentRotation) { + mProposedRotation = -1; + } mFlatTimestampNanos = Long.MIN_VALUE; mFlat = false; mSwingTimestampNanos = Long.MIN_VALUE; @@ -1015,9 +1033,11 @@ public abstract class WindowOrientationListener { } @Override - public void resetLocked() { - mProposedRotation = -1; - mDesiredRotation = -1; + public void resetLocked(boolean clearCurrentRotation) { + if (clearCurrentRotation) { + mProposedRotation = -1; + mDesiredRotation = -1; + } mTouching = false; mTouchEndedTimestampNanos = Long.MIN_VALUE; unscheduleRotationEvaluationLocked(); diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java index 221e7957ef352..b5476d7e056b4 100644 --- a/services/core/java/com/android/server/wm/DisplayContent.java +++ b/services/core/java/com/android/server/wm/DisplayContent.java @@ -3492,10 +3492,15 @@ class DisplayContent extends WindowContainer implements WindowManagerP pw.print(prefix); pw.print("mOrientationChanging="); pw.print(mOrientationChanging); pw.print(" mAppFreezing="); pw.print(mAppFreezing); - pw.print(" mTurnOnScreen="); pw.println(mTurnOnScreen); + pw.print(" mTurnOnScreen="); pw.print(mTurnOnScreen); pw.print(" mReportOrientationChanged="); pw.println(mReportOrientationChanged); } if (mLastFreezeDuration != 0) {