From 970d4132ea28e748c1010be39450a98bbf7466f3 Mon Sep 17 00:00:00 2001
From: Jeff Brown
+ * The value of this property determines the power state of the primary display + * once {@link #startDozing} has been called. The default value is + * {@link Display#STATE_UNKNOWN} which lets the system decide. + * The dream may set a different state before starting to doze and may + * perform transitions between states while dozing to conserve power and + * achieve various effects. + *
+ * It is recommended that the state be set to {@link Display#STATE_DOZE_SUSPEND} + * once the dream has completely finished drawing and before it releases its wakelock + * to allow the display hardware to be fully suspended. While suspended, the + * display will preserve its on-screen contents or hand off control to dedicated + * doze hardware if the devices supports it. If the doze suspend state is + * used, the dream must make sure to set the mode back + * to {@link Display#STATE_DOZE} or {@link Display#STATE_ON} before drawing again + * since the display updates may be ignored and not seen by the user otherwise. + *
+ * The set of available display power states and their behavior while dozing is + * hardware dependent and may vary across devices. The dream may therefore + * need to be modified or configured to correctly support the hardware. + *
+ * + * @param state The screen state to use while dozing, such as {@link Display#STATE_ON}, + * {@link Display#STATE_DOZE}, {@link Display#STATE_DOZE_SUSPEND}, + * or {@link Display#STATE_OFF}, or {@link Display#STATE_UNKNOWN} for the default + * behavior. + * + * @hide For use by system UI components only. + */ + public void setDozeScreenState(int state) { + if (mDozeScreenState != state) { + mDozeScreenState = state; + updateDoze(); + } + } + + /** + * Gets the screen brightness to use while dozing. + * + * @return The screen brightness while dozing as a value between + * {@link PowerManager#BRIGHTNESS_OFF} (0) and {@link PowerManager#BRIGHTNESS_ON} (255), + * or {@link PowerManager#BRIGHTNESS_DEFAULT} (-1) to ask the system to apply + * its default policy based on the screen state. + * + * @see #setDozeScreenBrightness + * @hide For use by system UI components only. + */ + public int getDozeScreenBrightness() { + return mDozeScreenBrightness; + } + + /** + * Sets the screen brightness to use while dozing. + *+ * The value of this property determines the power state of the primary display + * once {@link #startDozing} has been called. The default value is + * {@link PowerManager#BRIGHTNESS_DEFAULT} which lets the system decide. + * The dream may set a different brightness before starting to doze and may adjust + * the brightness while dozing to conserve power and achieve various effects. + *
+ * Note that dream may specify any brightness in the full 0-255 range, including + * values that are less than the minimum value for manual screen brightness + * adjustments by the user. In particular, the value may be set to 0 which may + * turn off the backlight entirely while still leaving the screen on although + * this behavior is device dependent and not guaranteed. + *
+ * The available range of display brightness values and their behavior while dozing is + * hardware dependent and may vary across devices. The dream may therefore + * need to be modified or configured to correctly support the hardware. + *
+ * + * @param brightness The screen brightness while dozing as a value between + * {@link PowerManager#BRIGHTNESS_OFF} (0) and {@link PowerManager#BRIGHTNESS_ON} (255), + * or {@link PowerManager#BRIGHTNESS_DEFAULT} (-1) to ask the system to apply + * its default policy based on the screen state. + * + * @hide For use by system UI components only. + */ + public void setDozeScreenBrightness(int brightness) { + if (brightness != PowerManager.BRIGHTNESS_DEFAULT) { + brightness = clampAbsoluteBrightness(brightness); + } + if (mDozeScreenBrightness != brightness) { + mDozeScreenBrightness = brightness; + updateDoze(); + } + } + /** * Called when this Dream is constructed. */ @Override public void onCreate() { - if (mDebug) Slog.v(TAG, "onCreate() on thread " + Thread.currentThread().getId()); + if (mDebug) Slog.v(TAG, "onCreate()"); super.onCreate(); } @@ -844,8 +964,6 @@ public class DreamService extends Service implements Window.Callback { return; } - if (mDebug) Slog.v(TAG, "Attached on thread " + Thread.currentThread().getId()); - mWindowToken = windowToken; mCanDoze = canDoze; if (mWindowless && !mCanDoze) { @@ -963,7 +1081,17 @@ public class DreamService extends Service implements Window.Callback { if (isScreenBright()) pw.print(" bright"); if (isWindowless()) pw.print(" windowless"); if (isDozing()) pw.print(" dozing"); + else if (canDoze()) pw.print(" candoze"); pw.println(); + if (canDoze()) { + pw.println(" doze hardware: " + mDozeHardware); + pw.println(" doze screen state: " + Display.stateToString(mDozeScreenState)); + pw.println(" doze screen brightness: " + mDozeScreenBrightness); + } + } + + private static int clampAbsoluteBrightness(int value) { + return MathUtils.constrain(value, PowerManager.BRIGHTNESS_OFF, PowerManager.BRIGHTNESS_ON); } private final class DreamServiceWrapper extends IDreamService.Stub { diff --git a/core/java/android/service/dreams/IDreamManager.aidl b/core/java/android/service/dreams/IDreamManager.aidl index 9608a4da3686e..648426cbce7df 100644 --- a/core/java/android/service/dreams/IDreamManager.aidl +++ b/core/java/android/service/dreams/IDreamManager.aidl @@ -32,7 +32,7 @@ interface IDreamManager { void testDream(in ComponentName componentName); boolean isDreaming(); void finishSelf(in IBinder token, boolean immediate); - void startDozing(in IBinder token); + void startDozing(in IBinder token, int screenState, int screenBrightness); void stopDozing(in IBinder token); IDozeHardware getDozeHardware(in IBinder token); -} \ No newline at end of file +} diff --git a/core/java/android/view/Display.java b/core/java/android/view/Display.java index b17fa4a8d4980..154d2277e3cda 100644 --- a/core/java/android/view/Display.java +++ b/core/java/android/view/Display.java @@ -831,4 +831,13 @@ public final class Display { return Integer.toString(state); } } + + /** + * Returns true if display updates may be suspended while in the specified + * display power state. + * @hide + */ + public static boolean isSuspendedState(int state) { + return state == STATE_OFF || state == STATE_DOZE_SUSPEND; + } } diff --git a/services/core/java/com/android/server/display/AutomaticBrightnessController.java b/services/core/java/com/android/server/display/AutomaticBrightnessController.java index 4740caee244a3..45d3771077686 100644 --- a/services/core/java/com/android/server/display/AutomaticBrightnessController.java +++ b/services/core/java/com/android/server/display/AutomaticBrightnessController.java @@ -26,7 +26,6 @@ import android.hardware.Sensor; import android.hardware.SensorEvent; import android.hardware.SensorEventListener; import android.hardware.SensorManager; -import android.hardware.display.DisplayManagerInternal; import android.os.Handler; import android.os.Looper; import android.os.Message; @@ -199,9 +198,10 @@ class AutomaticBrightnessController { return mScreenAutoBrightness; } - public void updatePowerState(DisplayManagerInternal.DisplayPowerRequest request) { - if (setScreenAutoBrightnessAdjustment(request.screenAutoBrightnessAdjustment) - | setLightSensorEnabled(request.wantLightSensorEnabled())) { + public void configure(boolean enable, float adjustment) { + boolean changed = setLightSensorEnabled(enable); + changed |= setScreenAutoBrightnessAdjustment(adjustment); + if (changed) { updateAutoBrightness(false /*sendUpdate*/); } } diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java index a361e1082f408..09221a3e9c1d0 100644 --- a/services/core/java/com/android/server/display/DisplayPowerController.java +++ b/services/core/java/com/android/server/display/DisplayPowerController.java @@ -213,9 +213,11 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call // The elapsed real time when the screen on was blocked. private long mScreenOnBlockStartRealTime; - // True if the screen auto-brightness value is actually being used to - // set the display brightness. - private boolean mUsingScreenAutoBrightness; + // Remembers whether certain kinds of brightness adjustments + // were recently applied so that we can decide how to transition. + private boolean mAppliedAutoBrightness; + private boolean mAppliedDimming; + private boolean mAppliedLowPower; // The controller for the automatic brightness level. private AutomaticBrightnessController mAutomaticBrightnessController; @@ -428,7 +430,6 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call // Update the power state request. final boolean mustNotify; boolean mustInitialize = false; - boolean wasDimOrDoze = false; boolean autoBrightnessAdjustmentChanged = false; synchronized (mLock) { @@ -444,8 +445,6 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call mPendingRequestChangedLocked = false; mustInitialize = true; } else if (mPendingRequestChangedLocked) { - wasDimOrDoze = (mPowerRequest.screenState == DisplayPowerRequest.SCREEN_STATE_DIM - || mPowerRequest.screenState == DisplayPowerRequest.SCREEN_STATE_DOZE); autoBrightnessAdjustmentChanged = (mPowerRequest.screenAutoBrightnessAdjustment != mPendingRequestLocked.screenAutoBrightnessAdjustment); mPowerRequest.copyFrom(mPendingRequestLocked); @@ -463,10 +462,32 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call initialize(); } + // Compute the basic display state using the policy. + // We might override this below based on other factors. + int state; + int brightness = PowerManager.BRIGHTNESS_DEFAULT; + switch (mPowerRequest.policy) { + case DisplayPowerRequest.POLICY_OFF: + state = Display.STATE_OFF; + break; + case DisplayPowerRequest.POLICY_DOZE: + if (mPowerRequest.dozeScreenState != Display.STATE_UNKNOWN) { + state = mPowerRequest.dozeScreenState; + } else { + state = Display.STATE_DOZE; + } + brightness = mPowerRequest.dozeScreenBrightness; + break; + case DisplayPowerRequest.POLICY_DIM: + case DisplayPowerRequest.POLICY_BRIGHT: + default: + state = Display.STATE_ON; + break; + } + // Apply the proximity sensor. if (mProximitySensor != null) { - if (mPowerRequest.useProximitySensor - && mPowerRequest.screenState != DisplayPowerRequest.SCREEN_STATE_OFF) { + if (mPowerRequest.useProximitySensor && state != Display.STATE_OFF) { setProximitySensorEnabled(true); if (!mScreenOffBecauseOfProximity && mProximity == PROXIMITY_POSITIVE) { @@ -476,7 +497,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call } else if (mWaitingForNegativeProximity && mScreenOffBecauseOfProximity && mProximity == PROXIMITY_POSITIVE - && mPowerRequest.screenState != DisplayPowerRequest.SCREEN_STATE_OFF) { + && state != Display.STATE_OFF) { setProximitySensorEnabled(true); } else { setProximitySensorEnabled(false); @@ -490,63 +511,89 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call } else { mWaitingForNegativeProximity = false; } - - // Turn on the light sensor if needed. - if (mAutomaticBrightnessController != null) { - mAutomaticBrightnessController.updatePowerState(mPowerRequest); + if (mScreenOffBecauseOfProximity) { + state = Display.STATE_OFF; } - // Set the screen brightness. - if (mPowerRequest.wantScreenOnAny()) { - int target; - boolean slow; - int screenAutoBrightness = mAutomaticBrightnessController != null ? - mAutomaticBrightnessController.getAutomaticScreenBrightness() : -1; - if (screenAutoBrightness >= 0 && mPowerRequest.useAutoBrightness) { - // Use current auto-brightness value. - target = screenAutoBrightness; - slow = mUsingScreenAutoBrightness && !autoBrightnessAdjustmentChanged; - mUsingScreenAutoBrightness = true; + // Use zero brightness when screen is off. + if (state == Display.STATE_OFF) { + brightness = PowerManager.BRIGHTNESS_OFF; + } + + // Use default brightness when dozing unless overridden. + if (brightness < 0 && (state == Display.STATE_DOZE + || state == Display.STATE_DOZE_SUSPEND)) { + brightness = mScreenBrightnessDozeConfig; + } + + // Configure auto-brightness. + boolean autoBrightnessEnabled = false; + if (mAutomaticBrightnessController != null) { + autoBrightnessEnabled = mPowerRequest.useAutoBrightness + && state == Display.STATE_ON && brightness < 0; + mAutomaticBrightnessController.configure(autoBrightnessEnabled, + mPowerRequest.screenAutoBrightnessAdjustment); + } + + // Apply auto-brightness. + boolean slowChange = false; + if (brightness < 0) { + if (autoBrightnessEnabled) { + brightness = mAutomaticBrightnessController.getAutomaticScreenBrightness(); + } + if (brightness >= 0) { + // Use current auto-brightness value and slowly adjust to changes. + brightness = clampScreenBrightness(brightness); + if (mAppliedAutoBrightness && !autoBrightnessAdjustmentChanged) { + slowChange = true; // slowly adapt to auto-brightness + } + mAppliedAutoBrightness = true; } else { - // Light sensor is disabled or not ready yet. - // Use the current brightness setting from the request, which is expected - // provide a nominal default value for the case where auto-brightness - // is not ready yet. - target = mPowerRequest.screenBrightness; - slow = false; - mUsingScreenAutoBrightness = false; + mAppliedAutoBrightness = false; } - if (mPowerRequest.screenState == DisplayPowerRequest.SCREEN_STATE_DOZE) { - // Dim quickly to the doze state. - target = mScreenBrightnessDozeConfig; - slow = false; - } else if (mPowerRequest.screenState == DisplayPowerRequest.SCREEN_STATE_DIM) { - // Dim quickly by at least some minimum amount. - target = Math.min(target - SCREEN_DIM_MINIMUM_REDUCTION, - mScreenBrightnessDimConfig); - slow = false; - } else if (wasDimOrDoze) { - // Brighten quickly. - slow = false; - } - // If low power mode is enabled, brightness level - // would be scaled down to half - if (mPowerRequest.lowPowerMode) { - target = target/2; - } - animateScreenBrightness(clampScreenBrightness(target), - slow ? BRIGHTNESS_RAMP_RATE_SLOW : BRIGHTNESS_RAMP_RATE_FAST); } else { - // Screen is off. Don't bother changing the brightness. - mUsingScreenAutoBrightness = false; + mAppliedAutoBrightness = false; + } + + // Apply manual brightness. + // Use the current brightness setting from the request, which is expected + // provide a nominal default value for the case where auto-brightness + // is not ready yet. + if (brightness < 0) { + brightness = clampScreenBrightness(mPowerRequest.screenBrightness); + } + + // Apply dimming by at least some minimum amount when user activity + // timeout is about to expire. + if (mPowerRequest.policy == DisplayPowerRequest.POLICY_DIM) { + brightness = Math.max(Math.min(brightness - SCREEN_DIM_MINIMUM_REDUCTION, + mScreenBrightnessDimConfig), mScreenBrightnessRangeMinimum); + if (!mAppliedDimming) { + slowChange = false; + } + mAppliedDimming = true; + } + + // If low power mode is enabled, cut the brightness level by half + // as long as it is above the minimum threshold. + if (mPowerRequest.lowPowerMode) { + if (brightness > mScreenBrightnessRangeMinimum) { + brightness = Math.max(brightness / 2, mScreenBrightnessRangeMinimum); + } + if (!mAppliedLowPower) { + slowChange = false; + } + mAppliedLowPower = true; + } + + // Animate the screen brightness when the screen is on. + if (state != Display.STATE_OFF) { + animateScreenBrightness(brightness, slowChange + ? BRIGHTNESS_RAMP_RATE_SLOW : BRIGHTNESS_RAMP_RATE_FAST); } // Animate the screen on or off unless blocked. - if (mScreenOffBecauseOfProximity) { - // Screen off due to proximity. - setScreenState(Display.STATE_OFF); - unblockScreenOn(); - } else if (mPowerRequest.wantScreenOnAny()) { + if (state == Display.STATE_ON) { // Want screen on. // Wait for previous off animation to complete beforehand. // It is relatively short but if we cancel it and switch to the @@ -555,21 +602,14 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call // Turn the screen on. The contents of the screen may not yet // be visible if the electron beam has not been dismissed because // its last frame of animation is solid black. - - if (mPowerRequest.screenState == DisplayPowerRequest.SCREEN_STATE_DOZE) { - if (!mScreenBrightnessRampAnimator.isAnimating()) { - setScreenState(Display.STATE_DOZE); - } - } else { - setScreenState(Display.STATE_ON); - } - + setScreenState(Display.STATE_ON); if (mPowerRequest.blockScreenOn && mPowerState.getElectronBeamLevel() == 0.0f) { blockScreenOn(); } else { unblockScreenOn(); - if (USE_ELECTRON_BEAM_ON_ANIMATION) { + if (USE_ELECTRON_BEAM_ON_ANIMATION && mPowerRequest.isBrightOrDim()) { + // Perform screen on animation. if (!mElectronBeamOnAnimator.isStarted()) { if (mPowerState.getElectronBeamLevel() == 1.0f) { mPowerState.dismissElectronBeam(); @@ -583,28 +623,59 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call } } } else { + // Skip screen on animation. mPowerState.setElectronBeamLevel(1.0f); mPowerState.dismissElectronBeam(); } } } + } else if (state == Display.STATE_DOZE) { + // Want screen dozing. + // Wait for brightness animation to complete beforehand when entering doze + // from screen on. + unblockScreenOn(); + if (!mScreenBrightnessRampAnimator.isAnimating() + || mPowerState.getScreenState() != Display.STATE_ON) { + // Set screen state and dismiss the black surface without fanfare. + setScreenState(state); + mPowerState.setElectronBeamLevel(1.0f); + mPowerState.dismissElectronBeam(); + } + } else if (state == Display.STATE_DOZE_SUSPEND) { + // Want screen dozing and suspended. + // Wait for brightness animation to complete beforehand unless already + // suspended because we may not be able to change it after suspension. + unblockScreenOn(); + if (!mScreenBrightnessRampAnimator.isAnimating() + || mPowerState.getScreenState() == Display.STATE_DOZE_SUSPEND) { + // Set screen state and dismiss the black surface without fanfare. + setScreenState(state); + mPowerState.setElectronBeamLevel(1.0f); + mPowerState.dismissElectronBeam(); + } } else { // Want screen off. // Wait for previous on animation to complete beforehand. unblockScreenOn(); if (!mElectronBeamOnAnimator.isStarted()) { - if (!mElectronBeamOffAnimator.isStarted()) { - if (mPowerState.getElectronBeamLevel() == 0.0f) { - setScreenState(Display.STATE_OFF); - } else if (mPowerState.prepareElectronBeam( - mElectronBeamFadesConfig ? - ElectronBeam.MODE_FADE : - ElectronBeam.MODE_COOL_DOWN) - && mPowerState.getScreenState() != Display.STATE_OFF) { - mElectronBeamOffAnimator.start(); - } else { - mElectronBeamOffAnimator.end(); + if (mPowerRequest.policy == DisplayPowerRequest.POLICY_OFF) { + // Perform screen off animation. + if (!mElectronBeamOffAnimator.isStarted()) { + if (mPowerState.getElectronBeamLevel() == 0.0f) { + setScreenState(Display.STATE_OFF); + } else if (mPowerState.prepareElectronBeam( + mElectronBeamFadesConfig ? + ElectronBeam.MODE_FADE : + ElectronBeam.MODE_COOL_DOWN) + && mPowerState.getScreenState() != Display.STATE_OFF) { + mElectronBeamOffAnimator.start(); + } else { + mElectronBeamOffAnimator.end(); + } } + } else { + // Skip screen off animation. + setScreenState(Display.STATE_OFF); } } } @@ -856,7 +927,9 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call pw.println(" mPendingProximityDebounceTime=" + TimeUtils.formatUptime(mPendingProximityDebounceTime)); pw.println(" mScreenOffBecauseOfProximity=" + mScreenOffBecauseOfProximity); - pw.println(" mUsingScreenAutoBrightness=" + mUsingScreenAutoBrightness); + pw.println(" mAppliedAutoBrightness=" + mAppliedAutoBrightness); + pw.println(" mAppliedDimming=" + mAppliedDimming); + pw.println(" mAppliedLowPower=" + mAppliedLowPower); pw.println(" mScreenBrightnessRampAnimator.isAnimating()=" + mScreenBrightnessRampAnimator.isAnimating()); diff --git a/services/core/java/com/android/server/display/DisplayPowerState.java b/services/core/java/com/android/server/display/DisplayPowerState.java index a5f884984037f..4821e746949b6 100644 --- a/services/core/java/com/android/server/display/DisplayPowerState.java +++ b/services/core/java/com/android/server/display/DisplayPowerState.java @@ -402,13 +402,14 @@ final class DisplayPowerState { Slog.d(TAG, "Updating screen state: state=" + Display.stateToString(state) + ", backlight=" + backlight); } - if (stateChanged && state != Display.STATE_OFF) { + boolean suspending = Display.isSuspendedState(state); + if (stateChanged && !suspending) { mBlanker.requestDisplayState(state); } if (backlightChanged) { mBacklight.setBrightness(backlight); } - if (stateChanged && state == Display.STATE_OFF) { + if (stateChanged && suspending) { mBlanker.requestDisplayState(state); } } diff --git a/services/core/java/com/android/server/dreams/DreamManagerService.java b/services/core/java/com/android/server/dreams/DreamManagerService.java index 4ccf73bd05eeb..107a6f6874061 100644 --- a/services/core/java/com/android/server/dreams/DreamManagerService.java +++ b/services/core/java/com/android/server/dreams/DreamManagerService.java @@ -38,6 +38,7 @@ import android.os.Handler; import android.os.IBinder; import android.os.Looper; import android.os.PowerManager; +import android.os.PowerManagerInternal; import android.os.SystemClock; import android.os.SystemProperties; import android.os.UserHandle; @@ -48,6 +49,7 @@ import android.service.dreams.IDozeHardware; import android.service.dreams.IDreamManager; import android.text.TextUtils; import android.util.Slog; +import android.view.Display; import java.io.FileDescriptor; import java.io.PrintWriter; @@ -71,6 +73,7 @@ public final class DreamManagerService extends SystemService { private final DreamHandler mHandler; private final DreamController mController; private final PowerManager mPowerManager; + private final PowerManagerInternal mPowerManagerInternal; private final PowerManager.WakeLock mDozeWakeLock; private final McuHal mMcuHal; // synchronized on self @@ -81,6 +84,8 @@ public final class DreamManagerService extends SystemService { private boolean mCurrentDreamCanDoze; private boolean mCurrentDreamIsDozing; private boolean mCurrentDreamIsWaking; + private int mCurrentDreamDozeScreenState = Display.STATE_UNKNOWN; + private int mCurrentDreamDozeScreenBrightness = PowerManager.BRIGHTNESS_DEFAULT; private DozeHardwareWrapper mCurrentDreamDozeHardware; public DreamManagerService(Context context) { @@ -90,6 +95,7 @@ public final class DreamManagerService extends SystemService { mController = new DreamController(context, mHandler, mControllerListener); mPowerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE); + mPowerManagerInternal = getLocalService(PowerManagerInternal.class); mDozeWakeLock = mPowerManager.newWakeLock(PowerManager.DOZE_WAKE_LOCK, TAG); mMcuHal = McuHal.open(); @@ -134,6 +140,9 @@ public final class DreamManagerService extends SystemService { pw.println("mCurrentDreamCanDoze=" + mCurrentDreamCanDoze); pw.println("mCurrentDreamIsDozing=" + mCurrentDreamIsDozing); pw.println("mCurrentDreamIsWaking=" + mCurrentDreamIsWaking); + pw.println("mCurrentDreamDozeScreenState=" + + Display.stateToString(mCurrentDreamDozeScreenState)); + pw.println("mCurrentDreamDozeScreenBrightness=" + mCurrentDreamDozeScreenBrightness); pw.println("mCurrentDreamDozeHardware=" + mCurrentDreamDozeHardware); pw.println("getDozeComponent()=" + getDozeComponent()); pw.println(); @@ -213,16 +222,24 @@ public final class DreamManagerService extends SystemService { } } - private void startDozingInternal(IBinder token) { + private void startDozingInternal(IBinder token, int screenState, + int screenBrightness) { if (DEBUG) { - Slog.d(TAG, "Dream requested to start dozing: " + token); + Slog.d(TAG, "Dream requested to start dozing: " + token + + ", screenState=" + screenState + + ", screenBrightness=" + screenBrightness); } synchronized (mLock) { - if (mCurrentDreamToken == token && mCurrentDreamCanDoze - && !mCurrentDreamIsDozing) { - mCurrentDreamIsDozing = true; - mDozeWakeLock.acquire(); + if (mCurrentDreamToken == token && mCurrentDreamCanDoze) { + mCurrentDreamDozeScreenState = screenState; + mCurrentDreamDozeScreenBrightness = screenBrightness; + mPowerManagerInternal.setDozeOverrideFromDreamManager( + screenState, screenBrightness); + if (!mCurrentDreamIsDozing) { + mCurrentDreamIsDozing = true; + mDozeWakeLock.acquire(); + } } } } @@ -236,6 +253,8 @@ public final class DreamManagerService extends SystemService { if (mCurrentDreamToken == token && mCurrentDreamIsDozing) { mCurrentDreamIsDozing = false; mDozeWakeLock.release(); + mPowerManagerInternal.setDozeOverrideFromDreamManager( + Display.STATE_UNKNOWN, PowerManager.BRIGHTNESS_DEFAULT); } } } @@ -399,6 +418,8 @@ public final class DreamManagerService extends SystemService { mCurrentDreamIsDozing = false; mDozeWakeLock.release(); } + mCurrentDreamDozeScreenState = Display.STATE_UNKNOWN; + mCurrentDreamDozeScreenBrightness = PowerManager.BRIGHTNESS_DEFAULT; if (mCurrentDreamDozeHardware != null) { mCurrentDreamDozeHardware.release(); mCurrentDreamDozeHardware = null; @@ -593,7 +614,7 @@ public final class DreamManagerService extends SystemService { } @Override // Binder call - public void startDozing(IBinder token) { + public void startDozing(IBinder token, int screenState, int screenBrightness) { // Requires no permission, called by Dream from an arbitrary process. if (token == null) { throw new IllegalArgumentException("token must not be null"); @@ -601,7 +622,7 @@ public final class DreamManagerService extends SystemService { final long ident = Binder.clearCallingIdentity(); try { - startDozingInternal(token); + startDozingInternal(token, screenState, screenBrightness); } finally { Binder.restoreCallingIdentity(ident); } diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java index 4b1e8ebe1303d..8c52fadb7fc8f 100644 --- a/services/core/java/com/android/server/power/PowerManagerService.java +++ b/services/core/java/com/android/server/power/PowerManagerService.java @@ -404,6 +404,12 @@ public final class PowerManagerService extends com.android.server.SystemService // Use NaN to disable. private float mTemporaryScreenAutoBrightnessAdjustmentSettingOverride = Float.NaN; + // The screen state to use while dozing. + private int mDozeScreenStateOverrideFromDreamManager = Display.STATE_UNKNOWN; + + // The screen brightness to use while dozing. + private int mDozeScreenBrightnessOverrideFromDreamManager = PowerManager.BRIGHTNESS_DEFAULT; + // Time when we last logged a warning about calling userActivity() without permission. private long mLastWarningAboutUserActivityPermission = Long.MIN_VALUE; @@ -1370,11 +1376,12 @@ public final class PowerManagerService extends com.android.server.SystemService if (mUserActivitySummary == 0 && mLastUserActivityTimeNoChangeLights >= mLastWakeTime) { nextTimeout = mLastUserActivityTimeNoChangeLights + screenOffTimeout; - if (now < nextTimeout - && mDisplayPowerRequest.wantScreenOnNormal()) { - mUserActivitySummary = mDisplayPowerRequest.screenState - == DisplayPowerRequest.SCREEN_STATE_BRIGHT ? - USER_ACTIVITY_SCREEN_BRIGHT : USER_ACTIVITY_SCREEN_DIM; + if (now < nextTimeout) { + if (mDisplayPowerRequest.policy == DisplayPowerRequest.POLICY_BRIGHT) { + mUserActivitySummary = USER_ACTIVITY_SCREEN_BRIGHT; + } else if (mDisplayPowerRequest.policy == DisplayPowerRequest.POLICY_DIM) { + mUserActivitySummary = USER_ACTIVITY_SCREEN_DIM; + } } } if (mUserActivitySummary != 0) { @@ -1631,7 +1638,7 @@ public final class PowerManagerService extends com.android.server.SystemService if (mWakefulness != WAKEFULNESS_DREAMING || !mDreamsSupportedConfig || !mDreamsEnabledSetting - || !mDisplayPowerRequest.wantScreenOnNormal() + || !mDisplayPowerRequest.isBrightOrDim() || !mBootCompleted) { return false; } @@ -1672,8 +1679,7 @@ public final class PowerManagerService extends com.android.server.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) { - final int newScreenState = getDesiredScreenPowerStateLocked(); - mDisplayPowerRequest.screenState = newScreenState; + mDisplayPowerRequest.policy = getDesiredScreenPolicyLocked(); int screenBrightness = mScreenBrightnessSettingDefault; float screenAutoBrightnessAdjustment = 0.0f; @@ -1713,13 +1719,22 @@ public final class PowerManagerService extends com.android.server.SystemService mDisplayPowerRequest.lowPowerMode = mLowPowerModeEnabled; + if (mDisplayPowerRequest.policy == DisplayPowerRequest.POLICY_DOZE) { + mDisplayPowerRequest.dozeScreenState = mDozeScreenStateOverrideFromDreamManager; + mDisplayPowerRequest.dozeScreenBrightness = + mDozeScreenBrightnessOverrideFromDreamManager; + } else { + mDisplayPowerRequest.dozeScreenState = Display.STATE_UNKNOWN; + mDisplayPowerRequest.dozeScreenBrightness = PowerManager.BRIGHTNESS_DEFAULT; + } + mDisplayReady = mDisplayManagerInternal.requestPowerState(mDisplayPowerRequest, mRequestWaitForNegativeProximity); mRequestWaitForNegativeProximity = false; if (DEBUG_SPEW) { Slog.d(TAG, "updateScreenStateLocked: mDisplayReady=" + mDisplayReady - + ", newScreenState=" + newScreenState + + ", policy=" + mDisplayPowerRequest.policy + ", mWakefulness=" + mWakefulness + ", mWakeLockSummary=0x" + Integer.toHexString(mWakeLockSummary) + ", mUserActivitySummary=0x" + Integer.toHexString(mUserActivitySummary) @@ -1737,22 +1752,22 @@ public final class PowerManagerService extends com.android.server.SystemService return value >= -1.0f && value <= 1.0f; } - private int getDesiredScreenPowerStateLocked() { + private int getDesiredScreenPolicyLocked() { if (mWakefulness == WAKEFULNESS_ASLEEP) { - return DisplayPowerRequest.SCREEN_STATE_OFF; + return DisplayPowerRequest.POLICY_OFF; } if ((mWakeLockSummary & WAKE_LOCK_DOZE) != 0) { - return DisplayPowerRequest.SCREEN_STATE_DOZE; + return DisplayPowerRequest.POLICY_DOZE; } if ((mWakeLockSummary & WAKE_LOCK_SCREEN_BRIGHT) != 0 || (mUserActivitySummary & USER_ACTIVITY_SCREEN_BRIGHT) != 0 || !mBootCompleted) { - return DisplayPowerRequest.SCREEN_STATE_BRIGHT; + return DisplayPowerRequest.POLICY_BRIGHT; } - return DisplayPowerRequest.SCREEN_STATE_DIM; + return DisplayPowerRequest.POLICY_DIM; } private final DisplayManagerInternal.DisplayPowerCallbacks mDisplayPowerCallbacks = @@ -1895,7 +1910,7 @@ public final class PowerManagerService extends com.android.server.SystemService if (!mDisplayReady) { return true; } - if (mDisplayPowerRequest.wantScreenOnNormal()) { + if (mDisplayPowerRequest.isBrightOrDim()) { // If we asked for the screen to be on but it is off due to the proximity // sensor then we may suspend but only if the configuration allows it. // On some hardware it may not be safe to suspend because the proximity @@ -2103,6 +2118,19 @@ public final class PowerManagerService extends com.android.server.SystemService } } + private void setDozeOverrideFromDreamManagerInternal( + int screenState, int screenBrightness) { + synchronized (mLock) { + if (mDozeScreenStateOverrideFromDreamManager != screenState + || mDozeScreenBrightnessOverrideFromDreamManager != screenBrightness) { + mDozeScreenStateOverrideFromDreamManager = screenState; + mDozeScreenBrightnessOverrideFromDreamManager = screenBrightness; + mDirty |= DIRTY_SETTINGS; + updatePowerStateLocked(); + } + } + } + private void powerHintInternal(int hintId, int data) { nativeSendPowerHint(hintId, data); } @@ -2257,6 +2285,10 @@ public final class PowerManagerService extends com.android.server.SystemService + mTemporaryScreenBrightnessSettingOverride); pw.println(" mTemporaryScreenAutoBrightnessAdjustmentSettingOverride=" + mTemporaryScreenAutoBrightnessAdjustmentSettingOverride); + pw.println(" mDozeScreenStateOverrideFromDreamManager=" + + mDozeScreenStateOverrideFromDreamManager); + pw.println(" mDozeScreenBrightnessOverrideFromDreamManager=" + + mDozeScreenBrightnessOverrideFromDreamManager); pw.println(" mScreenBrightnessSettingMinimum=" + mScreenBrightnessSettingMinimum); pw.println(" mScreenBrightnessSettingMaximum=" + mScreenBrightnessSettingMaximum); pw.println(" mScreenBrightnessSettingDefault=" + mScreenBrightnessSettingDefault); @@ -3026,63 +3058,44 @@ public final class PowerManagerService extends com.android.server.SystemService } private final class LocalService extends PowerManagerInternal { - /** - * Used by the window manager to override the screen brightness based on the - * current foreground activity. - * - * This method must only be called by the window manager. - * - * @param brightness The overridden brightness, or -1 to disable the override. - */ @Override - public void setScreenBrightnessOverrideFromWindowManager(int brightness) { - mContext.enforceCallingOrSelfPermission( - android.Manifest.permission.DEVICE_POWER, null); - - final long ident = Binder.clearCallingIdentity(); - try { - setScreenBrightnessOverrideFromWindowManagerInternal(brightness); - } finally { - Binder.restoreCallingIdentity(ident); + public void setScreenBrightnessOverrideFromWindowManager(int screenBrightness) { + if (screenBrightness < PowerManager.BRIGHTNESS_DEFAULT + || screenBrightness > PowerManager.BRIGHTNESS_ON) { + screenBrightness = PowerManager.BRIGHTNESS_DEFAULT; } + setScreenBrightnessOverrideFromWindowManagerInternal(screenBrightness); } - /** - * Used by the window manager to override the button brightness based on the - * current foreground activity. - * - * This method must only be called by the window manager. - * - * @param brightness The overridden brightness, or -1 to disable the override. - */ @Override - public void setButtonBrightnessOverrideFromWindowManager(int brightness) { + public void setButtonBrightnessOverrideFromWindowManager(int screenBrightness) { // Do nothing. // Button lights are not currently supported in the new implementation. - mContext.enforceCallingOrSelfPermission( - android.Manifest.permission.DEVICE_POWER, null); } - /** - * Used by the window manager to override the user activity timeout based on the - * current foreground activity. It can only be used to make the timeout shorter - * than usual, not longer. - * - * This method must only be called by the window manager. - * - * @param timeoutMillis The overridden timeout, or -1 to disable the override. - */ + @Override + public void setDozeOverrideFromDreamManager(int screenState, int screenBrightness) { + switch (screenState) { + case Display.STATE_UNKNOWN: + case Display.STATE_OFF: + case Display.STATE_DOZE: + case Display.STATE_DOZE_SUSPEND: + case Display.STATE_ON: + break; + default: + screenState = Display.STATE_UNKNOWN; + break; + } + if (screenBrightness < PowerManager.BRIGHTNESS_DEFAULT + || screenBrightness > PowerManager.BRIGHTNESS_ON) { + screenBrightness = PowerManager.BRIGHTNESS_DEFAULT; + } + setDozeOverrideFromDreamManagerInternal(screenState, screenBrightness); + } + @Override public void setUserActivityTimeoutOverrideFromWindowManager(long timeoutMillis) { - mContext.enforceCallingOrSelfPermission( - android.Manifest.permission.DEVICE_POWER, null); - - final long ident = Binder.clearCallingIdentity(); - try { - setUserActivityTimeoutOverrideFromWindowManagerInternal(timeoutMillis); - } finally { - Binder.restoreCallingIdentity(ident); - } + setUserActivityTimeoutOverrideFromWindowManagerInternal(timeoutMillis); } @Override diff --git a/tests/DozeTest/AndroidManifest.xml b/tests/DozeTest/AndroidManifest.xml index c199f69aeb1e7..03778d6fe4cc5 100644 --- a/tests/DozeTest/AndroidManifest.xml +++ b/tests/DozeTest/AndroidManifest.xml @@ -22,7 +22,8 @@ android:name="DozeTestDream" android:exported="true" android:icon="@drawable/ic_app" - android:label="@string/doze_dream_name"> + android:label="@string/doze_dream_name" + android:permission="android.permission.BIND_DREAM_SERVICE">