From 36c4db8bd3bd7dad4b6cb8abd9cdc1a627fe3bbc Mon Sep 17 00:00:00 2001 From: Jeff Brown Date: Fri, 19 Sep 2014 12:05:31 -0700 Subject: [PATCH] Decouple turning screen on from waking up in policy. This allows us to ensure windows are fully drawn before unblocking screen on while dozing. Bug: 17516245 Change-Id: Ibe63c212b8db855ce26a34a8169f33764b266ee6 --- core/java/android/view/WindowManagerPolicy.java | 30 +++-- .../internal/policy/impl/PhoneWindowManager.java | 142 ++++++++++++--------- .../android/server/am/ActivityManagerService.java | 2 - .../java/com/android/server/power/Notifier.java | 30 ++++- .../android/server/power/PowerManagerService.java | 20 ++- .../android/server/wm/WindowManagerService.java | 5 +- 6 files changed, 147 insertions(+), 82 deletions(-) diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java index fec7550af66d..d458ee4846cf 100644 --- a/core/java/android/view/WindowManagerPolicy.java +++ b/core/java/android/view/WindowManagerPolicy.java @@ -930,7 +930,12 @@ public interface WindowManagerPolicy { * A new window has been focused. */ public int focusChangedLw(WindowState lastFocus, WindowState newFocus); - + + /** + * Called when the device is waking up. + */ + public void wakingUp(); + /** * Called when the device is going to sleep. * @@ -939,26 +944,25 @@ public interface WindowManagerPolicy { */ public void goingToSleep(int why); - public interface ScreenOnListener { - void onScreenOn(); - } - /** - * Called when the device is waking up. + * Called when the device is about to turn on the screen to show content. + * When waking up, this method will be called once after the call to wakingUp(). + * When dozing, the method will be called sometime after the call to goingToSleep() and + * may be called repeatedly in the case where the screen is pulsing on and off. + * * Must call back on the listener to tell it when the higher-level system * is ready for the screen to go on (i.e. the lock screen is shown). */ - public void wakingUp(ScreenOnListener screenOnListener); + public void screenTurningOn(ScreenOnListener screenOnListener); - /** - * Return whether the screen is about to turn on or is currently on. - */ - public boolean isScreenOnEarly(); + public interface ScreenOnListener { + void onScreenOn(); + } /** - * Return whether the screen is fully turned on. + * Return whether the system is awake. */ - public boolean isScreenOnFully(); + public boolean isAwake(); /** * Tell the policy that the lid switch has changed state. diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java index fbaaf74b2fda..aa49d3747f39 100644 --- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java +++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java @@ -351,8 +351,8 @@ public class PhoneWindowManager implements WindowManagerPolicy { boolean mLidControlsSleep; int mShortPressOnPowerBehavior = -1; int mLongPressOnPowerBehavior = -1; - boolean mScreenOnEarly = false; - boolean mScreenOnFully = false; + boolean mAwakeEarly = false; + boolean mAwakeFully = false; boolean mOrientationSensorEnabled = false; int mCurrentAppOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; boolean mHasSoftInput = false; @@ -548,6 +548,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { private static final int MSG_DISPATCH_SHOW_GLOBAL_ACTIONS = 10; private static final int MSG_HIDE_BOOT_MESSAGE = 11; private static final int MSG_LAUNCH_VOICE_ASSIST_WITH_WAKE_LOCK = 12; + private static final int MSG_SCREEN_TURNING_ON = 13; private class PolicyHandler extends Handler { @Override @@ -573,22 +574,18 @@ public class PhoneWindowManager implements WindowManagerPolicy { break; case MSG_KEYGUARD_DRAWN_COMPLETE: if (DEBUG_WAKEUP) Slog.w(TAG, "Setting mKeyguardDrawComplete"); - mKeyguardDrawComplete = true; - finishScreenTurningOn(); + finishKeyguardDrawn(); break; case MSG_KEYGUARD_DRAWN_TIMEOUT: Slog.w(TAG, "Keyguard drawn timeout. Setting mKeyguardDrawComplete"); - mKeyguardDrawComplete = true; - finishScreenTurningOn(); + finishKeyguardDrawn(); break; case MSG_WINDOW_MANAGER_DRAWN_COMPLETE: if (DEBUG_WAKEUP) Slog.w(TAG, "Setting mWindowManagerDrawComplete"); - mHandler.removeMessages(MSG_KEYGUARD_DRAWN_TIMEOUT); - mWindowManagerDrawComplete = true; - finishScreenTurningOn(); + finishWindowsDrawn(); break; case MSG_WAKING_UP: - handleWakingUp((ScreenOnListener) msg.obj); + handleWakingUp(); break; case MSG_HIDE_BOOT_MESSAGE: handleHideBootMessage(); @@ -596,6 +593,9 @@ public class PhoneWindowManager implements WindowManagerPolicy { case MSG_LAUNCH_VOICE_ASSIST_WITH_WAKE_LOCK: launchVoiceAssistWithWakeLock(msg.arg1 != 0); break; + case MSG_SCREEN_TURNING_ON: + handleScreenTurningOn((ScreenOnListener)msg.obj); + break; } } } @@ -766,11 +766,11 @@ public class PhoneWindowManager implements WindowManagerPolicy { } //Could have been invoked due to screen turning on or off or //change of the currently visible window's orientation - if (localLOGV) Slog.v(TAG, "Screen status="+mScreenOnEarly+ + if (localLOGV) Slog.v(TAG, "Screen status="+mAwakeEarly+ ", current orientation="+mCurrentAppOrientation+ ", SensorEnabled="+mOrientationSensorEnabled); boolean disable = true; - if (mScreenOnEarly) { + if (mAwakeEarly) { if (needSensorRunningLp()) { disable = false; //enable listener if not already enabled @@ -1332,7 +1332,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { } private boolean shouldEnableWakeGestureLp() { - return mWakeGestureEnabledSetting && !mScreenOnEarly + return mWakeGestureEnabledSetting && !mAwakeEarly && (!mLidControlsSleep || mLidState != LID_CLOSED) && mWakeGestureListener.isSupported(); } @@ -4731,9 +4731,10 @@ public class PhoneWindowManager implements WindowManagerPolicy { @Override public void goingToSleep(int why) { EventLog.writeEvent(70000, 0); + if (DEBUG_WAKEUP) Slog.i(TAG, "Going to sleep..."); synchronized (mLock) { - mScreenOnEarly = false; - mScreenOnFully = false; + mAwakeEarly = false; + mAwakeFully = false; } if (mKeyguardDelegate != null) { mKeyguardDelegate.onScreenTurnedOff(why); @@ -4746,70 +4747,101 @@ public class PhoneWindowManager implements WindowManagerPolicy { } @Override - public void wakingUp(final ScreenOnListener screenOnListener) { + public void wakingUp() { EventLog.writeEvent(70000, 1); - if (DEBUG_WAKEUP) Slog.i(TAG, "Screen turning on...", - new RuntimeException("here").fillInStackTrace()); - mHandler.obtainMessage(MSG_WAKING_UP, screenOnListener).sendToTarget(); + if (DEBUG_WAKEUP) Slog.i(TAG, "Waking up..."); + mHandler.obtainMessage(MSG_WAKING_UP).sendToTarget(); } // Called on the mHandler thread. - private void handleWakingUp(final ScreenOnListener screenOnListener) { - if (screenOnListener != null) { - mScreenOnListener = screenOnListener; - } - + private void handleWakingUp() { synchronized (mLock) { - mScreenOnEarly = true; + mAwakeEarly = true; updateWakeGestureListenerLp(); updateOrientationListenerLp(); updateLockScreenTimeout(); } mKeyguardDrawComplete = false; - mWindowManagerDrawComplete = false; + mWindowManagerDrawComplete = false; // wait for later call to screenTurningOn if (mKeyguardDelegate != null) { mHandler.removeMessages(MSG_KEYGUARD_DRAWN_TIMEOUT); mHandler.sendEmptyMessageDelayed(MSG_KEYGUARD_DRAWN_TIMEOUT, 1000); mKeyguardDelegate.onScreenTurnedOn(mKeyguardDelegateCallback); + // ... eventually calls finishKeyguardDrawn } else { if (DEBUG_WAKEUP) Slog.d(TAG, "null mKeyguardDelegate: setting mKeyguardDrawComplete."); + finishKeyguardDrawn(); + } + } + + // Called on the mHandler thread. + private void finishKeyguardDrawn() { + if (!mKeyguardDrawComplete) { mKeyguardDrawComplete = true; + mHandler.removeMessages(MSG_KEYGUARD_DRAWN_TIMEOUT); + finishScreenTurningOn(); } + } + + @Override + public void screenTurningOn(final ScreenOnListener screenOnListener) { + EventLog.writeEvent(70000, 1); + if (DEBUG_WAKEUP) Slog.i(TAG, "Screen turning on..."); + mHandler.obtainMessage(MSG_SCREEN_TURNING_ON, screenOnListener).sendToTarget(); + } + + // Called on the mHandler thread. + private void handleScreenTurningOn(ScreenOnListener screenOnListener) { + mScreenOnListener = screenOnListener; + + mWindowManagerDrawComplete = false; mWindowManagerInternal.waitForAllWindowsDrawn(mWindowManagerDrawCallback, WAITING_FOR_DRAWN_TIMEOUT); + // ... eventually calls finishWindowsDrawn + } + + // Called on the mHandler thread. + private void finishWindowsDrawn() { + if (!mWindowManagerDrawComplete) { + mWindowManagerDrawComplete = true; + finishScreenTurningOn(); + } } // Called on the mHandler thread. private void finishScreenTurningOn() { if (DEBUG_WAKEUP) Slog.d(TAG, - "finishScreenTurningOn: mKeyguardDrawComplete=" + mKeyguardDrawComplete + "finishScreenTurningOn: mAwakeEarly=" + mAwakeEarly + + " mKeyguardDrawComplete=" + mKeyguardDrawComplete + " mWindowManagerDrawComplete=" + mWindowManagerDrawComplete); - if (!mKeyguardDrawComplete || !mWindowManagerDrawComplete) { - return; - } - - ScreenOnListener screenOnListener; + boolean awake; synchronized (mLock) { - mScreenOnFully = true; - screenOnListener = mScreenOnListener; - mScreenOnListener = null; - } + if ((mAwakeEarly && !mKeyguardDrawComplete) + || !mWindowManagerDrawComplete) { + return; + } - try { - mWindowManager.setEventDispatching(true); - } catch (RemoteException unhandled) { + if (mAwakeEarly) { + mAwakeFully = true; + } + awake = mAwakeFully; } - if (screenOnListener != null) { - screenOnListener.onScreenOn(); + if (DEBUG_WAKEUP) Slog.i(TAG, "Finished screen turning on..."); + + if (mScreenOnListener != null) { + mScreenOnListener.onScreenOn(); + mScreenOnListener = null; } - setKeyguardDrawn(); + if (awake) { + setKeyguardDrawnFirstTime(); - if (mBootMessageNeedsHiding) { - handleHideBootMessage(); - mBootMessageNeedsHiding = false; + if (mBootMessageNeedsHiding) { + handleHideBootMessage(); + mBootMessageNeedsHiding = false; + } } } @@ -4829,13 +4861,8 @@ public class PhoneWindowManager implements WindowManagerPolicy { } @Override - public boolean isScreenOnEarly() { - return mScreenOnEarly; - } - - @Override - public boolean isScreenOnFully() { - return mScreenOnFully; + public boolean isAwake() { + return mAwakeFully; } /** {@inheritDoc} */ @@ -4909,7 +4936,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { } } - private void setKeyguardDrawn() { + private void setKeyguardDrawnFirstTime() { synchronized (mLock) { mKeyguardDrawn = true; } @@ -5222,7 +5249,8 @@ public class PhoneWindowManager implements WindowManagerPolicy { synchronized (mLock) { mSystemBooted = true; } - wakingUp(null); + wakingUp(); + screenTurningOn(null); } ProgressDialog mBootMsgDialog = null; @@ -5352,7 +5380,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { private void updateLockScreenTimeout() { synchronized (mScreenLockTimeout) { - boolean enable = (mAllowLockscreenWhenOn && mScreenOnEarly && + boolean enable = (mAllowLockscreenWhenOn && mAwakeEarly && mKeyguardDelegate != null && mKeyguardDelegate.isSecure()); if (mLockScreenTimerActive != enable) { if (enable) { @@ -5890,8 +5918,8 @@ public class PhoneWindowManager implements WindowManagerPolicy { pw.print("mShortPressOnPowerBehavior="); pw.print(mShortPressOnPowerBehavior); pw.print(" mLongPressOnPowerBehavior="); pw.println(mLongPressOnPowerBehavior); pw.print(prefix); pw.print("mHasSoftInput="); pw.println(mHasSoftInput); - pw.print(prefix); pw.print("mScreenOnEarly="); pw.print(mScreenOnEarly); - pw.print(" mScreenOnFully="); pw.print(mScreenOnFully); + pw.print(prefix); pw.print("mAwakeEarly="); pw.print(mAwakeEarly); + pw.print(" mAwakeFully="); pw.print(mAwakeFully); pw.print(" mOrientationSensorEnabled="); pw.println(mOrientationSensorEnabled); pw.print(prefix); pw.print("mOverscanScreen=("); pw.print(mOverscanScreenLeft); pw.print(","); pw.print(mOverscanScreenTop); diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 190c16c06740..7d96b84e1ec1 100755 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -9958,7 +9958,6 @@ public final class ActivityManagerService extends ActivityManagerNative void goingToSleep() { synchronized(this) { mWentToSleep = true; - updateEventDispatchingLocked(); goToSleepIfNeededLocked(); } } @@ -10056,7 +10055,6 @@ public final class ActivityManagerService extends ActivityManagerNative void wakingUp() { synchronized(this) { mWentToSleep = false; - updateEventDispatchingLocked(); comeOutOfSleepIfNeededLocked(); } } diff --git a/services/core/java/com/android/server/power/Notifier.java b/services/core/java/com/android/server/power/Notifier.java index 464972428409..c720668de693 100644 --- a/services/core/java/com/android/server/power/Notifier.java +++ b/services/core/java/com/android/server/power/Notifier.java @@ -256,16 +256,11 @@ final class Notifier { if (mActualPowerState != POWER_STATE_AWAKE) { mActualPowerState = POWER_STATE_AWAKE; mPendingWakeUpBroadcast = true; - if (mPendingScreenOnUnblocker == null) { - mScreenOnBlocker.acquire(); - } - final ScreenOnUnblocker unblocker = new ScreenOnUnblocker(); - mPendingScreenOnUnblocker = unblocker; mHandler.post(new Runnable() { @Override public void run() { EventLog.writeEvent(EventLogTags.POWER_SCREEN_STATE, 1, 0, 0, 0); - mPolicy.wakingUp(unblocker); + mPolicy.wakingUp(); mActivityManagerInternal.wakingUp(); } }); @@ -338,6 +333,21 @@ final class Notifier { } /** + * Notifies that screen is about to be turned on (any state other than off). + */ + public void onScreenTurningOn() { + synchronized (mLock) { + final ScreenOnUnblocker unblocker = blockScreenOnLocked(); + mHandler.post(new Runnable() { + @Override + public void run() { + mPolicy.screenTurningOn(unblocker); + } + }); + } + } + + /** * Called when there has been user activity. */ public void onUserActivity(int event, int uid) { @@ -460,6 +470,14 @@ final class Notifier { } } + private ScreenOnUnblocker blockScreenOnLocked() { + if (mPendingScreenOnUnblocker == null) { + mScreenOnBlocker.acquire(); + } + mPendingScreenOnUnblocker = new ScreenOnUnblocker(); + return mPendingScreenOnUnblocker; + } + private final class ScreenOnUnblocker implements WindowManagerPolicy.ScreenOnListener { @Override public void onScreenOn() { diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java index c79a6d64121e..71e059ab3a60 100644 --- a/services/core/java/com/android/server/power/PowerManagerService.java +++ b/services/core/java/com/android/server/power/PowerManagerService.java @@ -1767,6 +1767,7 @@ public final class PowerManagerService extends SystemService if ((dirty & (DIRTY_WAKE_LOCKS | DIRTY_USER_ACTIVITY | DIRTY_WAKEFULNESS | DIRTY_ACTUAL_DISPLAY_POWER_STATE_UPDATED | DIRTY_BOOT_COMPLETED | DIRTY_SETTINGS | DIRTY_SCREEN_ON_BLOCKER_RELEASED)) != 0) { + boolean wasBlockerNeeded = isScreenOnBlockerNeededLocked(mDisplayPowerRequest); mDisplayPowerRequest.policy = getDesiredScreenPolicyLocked(); int screenBrightness = mScreenBrightnessSettingDefault; @@ -1803,8 +1804,6 @@ public final class PowerManagerService extends SystemService mDisplayPowerRequest.useProximitySensor = shouldUseProximitySensorLocked(); - mDisplayPowerRequest.blockScreenOn = mScreenOnBlocker.isHeld(); - mDisplayPowerRequest.lowPowerMode = mLowPowerModeEnabled; if (mDisplayPowerRequest.policy == DisplayPowerRequest.POLICY_DOZE) { @@ -1816,6 +1815,12 @@ public final class PowerManagerService extends SystemService mDisplayPowerRequest.dozeScreenBrightness = PowerManager.BRIGHTNESS_DEFAULT; } + if (!wasBlockerNeeded && isScreenOnBlockerNeededLocked(mDisplayPowerRequest) + && !mScreenOnBlocker.isHeld()) { + mNotifier.onScreenTurningOn(); + } + mDisplayPowerRequest.blockScreenOn = mScreenOnBlocker.isHeld(); + mDisplayReady = mDisplayManagerInternal.requestPowerState(mDisplayPowerRequest, mRequestWaitForNegativeProximity); mRequestWaitForNegativeProximity = false; @@ -1832,6 +1837,17 @@ public final class PowerManagerService extends SystemService return mDisplayReady && !oldDisplayReady; } + private static boolean isScreenOnBlockerNeededLocked(DisplayPowerRequest req) { + switch (req.policy) { + case DisplayPowerRequest.POLICY_OFF: + return false; + case DisplayPowerRequest.POLICY_DOZE: + return req.dozeScreenState != Display.STATE_OFF; + default: + return true; + } + } + private static boolean isValidBrightness(int value) { return value >= 0 && value <= 255; } diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index fdf2fc8b00e0..b3341ede7d57 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -3474,7 +3474,7 @@ public class WindowManagerService extends IWindowManager.Stub } boolean okToDisplay() { - return !mDisplayFrozen && mDisplayEnabled && mPolicy.isScreenOnFully(); + return !mDisplayFrozen && mDisplayEnabled && mPolicy.isAwake(); } AppWindowToken findAppWindowToken(IBinder token) { @@ -10397,7 +10397,7 @@ public class WindowManagerService extends IWindowManager.Stub return; } - if (!mDisplayReady || !mPolicy.isScreenOnFully()) { + if (!mDisplayReady || !mPolicy.isAwake()) { // No need to freeze the screen before the system is ready or if // the screen is off. return; @@ -11556,6 +11556,7 @@ public class WindowManagerService extends IWindowManager.Stub } } + @Override public void waitForAllWindowsDrawn(Runnable callback, long timeout) { synchronized (mWindowMap) { mWaitingForDrawnCallback = callback; -- 2.11.0