diff options
14 files changed, 519 insertions, 200 deletions
diff --git a/core/java/android/hardware/display/DisplayManagerInternal.java b/core/java/android/hardware/display/DisplayManagerInternal.java index e58c54d..99af2e7 100644 --- a/core/java/android/hardware/display/DisplayManagerInternal.java +++ b/core/java/android/hardware/display/DisplayManagerInternal.java @@ -19,6 +19,7 @@ package android.hardware.display; import android.hardware.SensorManager; import android.os.Handler; import android.os.PowerManager; +import android.view.Display; import android.view.DisplayInfo; /** @@ -132,13 +133,19 @@ public abstract class DisplayManagerInternal { * have to micro-manage screen off animations, auto-brightness and other effects. */ public static final class DisplayPowerRequest { - public static final int SCREEN_STATE_OFF = 0; - public static final int SCREEN_STATE_DOZE = 1; - public static final int SCREEN_STATE_DIM = 2; - public static final int SCREEN_STATE_BRIGHT = 3; - - // The requested minimum screen power state: off, doze, dim or bright. - public int screenState; + // Policy: Turn screen off as if the user pressed the power button + // including playing a screen off animation if applicable. + public static final int POLICY_OFF = 0; + // Policy: Enable dozing and always-on display functionality. + public static final int POLICY_DOZE = 1; + // Policy: Make the screen dim when the user activity timeout is + // about to expire. + public static final int POLICY_DIM = 2; + // Policy: Make the screen bright as usual. + public static final int POLICY_BRIGHT = 3; + + // The basic overall policy to apply: off, doze, dim or bright. + public int policy; // If true, the proximity sensor overrides the screen state when an object is // nearby, turning it off temporarily until the object is moved away. @@ -169,44 +176,39 @@ public abstract class DisplayManagerInternal { // visible to the user. public boolean blockScreenOn; + // Overrides the policy for adjusting screen brightness and state while dozing. + public int dozeScreenBrightness; + public int dozeScreenState; + public DisplayPowerRequest() { - screenState = SCREEN_STATE_BRIGHT; + policy = POLICY_BRIGHT; useProximitySensor = false; screenBrightness = PowerManager.BRIGHTNESS_ON; screenAutoBrightnessAdjustment = 0.0f; useAutoBrightness = false; blockScreenOn = false; + dozeScreenBrightness = PowerManager.BRIGHTNESS_DEFAULT; + dozeScreenState = Display.STATE_UNKNOWN; } public DisplayPowerRequest(DisplayPowerRequest other) { copyFrom(other); } - // Returns true if we want the screen on in any mode, including doze. - public boolean wantScreenOnAny() { - return screenState != SCREEN_STATE_OFF; - } - - // Returns true if we want the screen on in a normal mode, excluding doze. - // This is usually what we want to tell the rest of the system. For compatibility - // reasons, we pretend the screen is off when dozing. - public boolean wantScreenOnNormal() { - return screenState == SCREEN_STATE_DIM || screenState == SCREEN_STATE_BRIGHT; - } - - public boolean wantLightSensorEnabled() { - // Specifically, we don't want the light sensor while dozing. - return useAutoBrightness && wantScreenOnNormal(); + public boolean isBrightOrDim() { + return policy == POLICY_BRIGHT || policy == POLICY_DIM; } public void copyFrom(DisplayPowerRequest other) { - screenState = other.screenState; + policy = other.policy; useProximitySensor = other.useProximitySensor; screenBrightness = other.screenBrightness; screenAutoBrightnessAdjustment = other.screenAutoBrightnessAdjustment; useAutoBrightness = other.useAutoBrightness; blockScreenOn = other.blockScreenOn; lowPowerMode = other.lowPowerMode; + dozeScreenBrightness = other.dozeScreenBrightness; + dozeScreenState = other.dozeScreenState; } @Override @@ -217,13 +219,15 @@ public abstract class DisplayManagerInternal { public boolean equals(DisplayPowerRequest other) { return other != null - && screenState == other.screenState + && policy == other.policy && useProximitySensor == other.useProximitySensor && screenBrightness == other.screenBrightness && screenAutoBrightnessAdjustment == other.screenAutoBrightnessAdjustment && useAutoBrightness == other.useAutoBrightness && blockScreenOn == other.blockScreenOn - && lowPowerMode == other.lowPowerMode; + && lowPowerMode == other.lowPowerMode + && dozeScreenBrightness == other.dozeScreenBrightness + && dozeScreenState == other.dozeScreenState; } @Override @@ -233,13 +237,30 @@ public abstract class DisplayManagerInternal { @Override public String toString() { - return "screenState=" + screenState + return "policy=" + policyToString(policy) + ", useProximitySensor=" + useProximitySensor + ", screenBrightness=" + screenBrightness + ", screenAutoBrightnessAdjustment=" + screenAutoBrightnessAdjustment + ", useAutoBrightness=" + useAutoBrightness + ", blockScreenOn=" + blockScreenOn - + ", lowPowerMode=" + lowPowerMode; + + ", lowPowerMode=" + lowPowerMode + + ", dozeScreenBrightness=" + dozeScreenBrightness + + ", dozeScreenState=" + Display.stateToString(dozeScreenState); + } + + public static String policyToString(int policy) { + switch (policy) { + case POLICY_OFF: + return "OFF"; + case POLICY_DOZE: + return "DOZE"; + case POLICY_DIM: + return "DIM"; + case POLICY_BRIGHT: + return "BRIGHT"; + default: + return Integer.toString(policy); + } } } diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java index 92e80a5..dda6d27 100644 --- a/core/java/android/os/PowerManager.java +++ b/core/java/android/os/PowerManager.java @@ -263,6 +263,12 @@ public final class PowerManager { */ public static final int BRIGHTNESS_OFF = 0; + /** + * Brightness value for default policy handling by the system. + * @hide + */ + public static final int BRIGHTNESS_DEFAULT = -1; + // Note: Be sure to update android.os.BatteryStats and PowerManager.h // if adding or modifying user activity event constants. diff --git a/core/java/android/os/PowerManagerInternal.java b/core/java/android/os/PowerManagerInternal.java index 08a15eb..14f4a83 100644 --- a/core/java/android/os/PowerManagerInternal.java +++ b/core/java/android/os/PowerManagerInternal.java @@ -16,6 +16,8 @@ package android.os; +import android.view.Display; + /** * Power manager local system service interface. * @@ -53,6 +55,17 @@ public abstract class PowerManagerInternal { */ public abstract void setUserActivityTimeoutOverrideFromWindowManager(long timeoutMillis); + /** + * Used by the dream manager to override certain properties while dozing. + * + * @param screenState The overridden screen state, or {@link Display.STATE_UNKNOWN} + * to disable the override. + * @param screenBrightness The overridden screen brightness, or + * {@link PowerManager#BRIGHTNESS_DEFAULT} to disable the override. + */ + public abstract void setDozeOverrideFromDreamManager( + int screenState, int screenBrightness); + public abstract boolean getLowPowerModeEnabled(); public abstract void registerLowPowerModeObserver(LowPowerModeListener listener); diff --git a/core/java/android/service/dreams/DreamService.java b/core/java/android/service/dreams/DreamService.java index 5fa542a..5cf8aa6 100644 --- a/core/java/android/service/dreams/DreamService.java +++ b/core/java/android/service/dreams/DreamService.java @@ -27,10 +27,13 @@ import android.graphics.PixelFormat; import android.graphics.drawable.ColorDrawable; import android.os.Handler; import android.os.IBinder; +import android.os.PowerManager; +import android.os.RemoteException; import android.os.RemoteException; import android.os.ServiceManager; import android.util.Slog; import android.view.ActionMode; +import android.view.Display; import android.view.KeyEvent; import android.view.Menu; import android.view.MenuItem; @@ -42,6 +45,7 @@ import android.view.WindowManager; import android.view.WindowManagerGlobal; import android.view.WindowManager.LayoutParams; import android.view.accessibility.AccessibilityEvent; +import android.util.MathUtils; import com.android.internal.policy.PolicyManager; import com.android.internal.util.DumpUtils; @@ -133,8 +137,11 @@ import com.android.internal.util.DumpUtils.Dump; * android:exported="true" * android:icon="@drawable/my_icon" * android:label="@string/my_dream_label" - * android:permission="android.permission.BIND_DREAM_SERVICE" > - * ... + * android:permission="android.permission.BIND_DREAM_SERVICE"> + * <intent-filter> + * <action android:name=”android.service.dreams.DreamService” /> + * <category android:name=”android.intent.category.DEFAULT” /> + * </intent-filter> * </service> * </pre> */ @@ -177,6 +184,8 @@ public class DreamService extends Service implements Window.Callback { private boolean mDozing; private boolean mWindowless; private DozeHardware mDozeHardware; + private int mDozeScreenState = Display.STATE_UNKNOWN; + private int mDozeScreenBrightness = PowerManager.BRIGHTNESS_DEFAULT; private boolean mDebug = false; @@ -560,7 +569,7 @@ public class DreamService extends Service implements Window.Callback { * * @return True if this dream can doze. * @see #startDozing - * @hide experimental + * @hide For use by system UI components only. */ public boolean canDoze() { return mCanDoze; @@ -593,13 +602,19 @@ public class DreamService extends Service implements Window.Callback { * </p> * * @see #stopDozing - * @hide experimental + * @hide For use by system UI components only. */ public void startDozing() { if (mCanDoze && !mDozing) { mDozing = true; + updateDoze(); + } + } + + private void updateDoze() { + if (mDozing) { try { - mSandman.startDozing(mWindowToken); + mSandman.startDozing(mWindowToken, mDozeScreenState, mDozeScreenBrightness); } catch (RemoteException ex) { // system server died } @@ -615,7 +630,7 @@ public class DreamService extends Service implements Window.Callback { * </p> * * @see #startDozing - * @hide experimental + * @hide For use by system UI components only. */ public void stopDozing() { if (mDozing) { @@ -636,7 +651,7 @@ public class DreamService extends Service implements Window.Callback { * @return True if the dream is dozing. * * @see #setDozing(boolean) - * @hide experimental + * @hide For use by system UI components only. */ public boolean isDozing() { return mDozing; @@ -649,7 +664,7 @@ public class DreamService extends Service implements Window.Callback { * @return An instance of {@link DozeHardware} or null if this device does not offer * hardware support for dozing. * - * @hide experimental + * @hide For use by system UI components only. */ public DozeHardware getDozeHardware() { if (mCanDoze && mDozeHardware == null && mWindowToken != null) { @@ -666,11 +681,116 @@ public class DreamService extends Service implements Window.Callback { } /** + * Gets the screen state to use while dozing. + * + * @return 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. + * + * @see #setDozeScreenState + * @hide For use by system UI components only. + */ + public int getDozeScreenState() { + return mDozeScreenState; + } + + /** + * Sets the screen state to use while dozing. + * <p> + * 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. + * </p><p> + * 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. + * </p><p> + * 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. + * </p> + * + * @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. + * <p> + * 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. + * </p><p> + * 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. + * </p><p> + * 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. + * </p> + * + * @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 9608a4d..648426c 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 b17fa4a..154d227 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 4740cae..45d3771 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 a361e10..09221a3 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; } + if (mScreenOffBecauseOfProximity) { + state = Display.STATE_OFF; + } + + // 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; + } - // Turn on the light sensor if needed. + // Configure auto-brightness. + boolean autoBrightnessEnabled = false; if (mAutomaticBrightnessController != null) { - mAutomaticBrightnessController.updatePowerState(mPowerRequest); - } - - // 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; + 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; - } - 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); + mAppliedAutoBrightness = false; + } } 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 a5f8849..4821e74 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 4ccf73b..107a6f6 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 4b1e8eb..8c52fad 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 setUserActivityTimeoutOverrideFromWindowManager(long timeoutMillis) { - mContext.enforceCallingOrSelfPermission( - android.Manifest.permission.DEVICE_POWER, null); - - final long ident = Binder.clearCallingIdentity(); - try { - setUserActivityTimeoutOverrideFromWindowManagerInternal(timeoutMillis); - } finally { - Binder.restoreCallingIdentity(ident); + 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) { + setUserActivityTimeoutOverrideFromWindowManagerInternal(timeoutMillis); } @Override diff --git a/tests/DozeTest/AndroidManifest.xml b/tests/DozeTest/AndroidManifest.xml index c199f69..03778d6 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"> <!-- Commented out to prevent this dream from appearing in the list of dreams that the user can select via the Settings application. <intent-filter> diff --git a/tests/DozeTest/res/layout/dream.xml b/tests/DozeTest/res/layout/dream.xml index 1c8fd3f..bced230 100644 --- a/tests/DozeTest/res/layout/dream.xml +++ b/tests/DozeTest/res/layout/dream.xml @@ -18,7 +18,8 @@ android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center_vertical" - android:orientation="vertical"> + android:orientation="vertical" + android:background="#bb2288"> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" diff --git a/tests/DozeTest/src/com/android/dreams/dozetest/DozeTestDream.java b/tests/DozeTest/src/com/android/dreams/dozetest/DozeTestDream.java index a0b2d1a..f72e331 100644 --- a/tests/DozeTest/src/com/android/dreams/dozetest/DozeTestDream.java +++ b/tests/DozeTest/src/com/android/dreams/dozetest/DozeTestDream.java @@ -22,11 +22,13 @@ import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; +import android.os.Handler; import android.os.PowerManager; import android.service.dreams.DozeHardware; import android.service.dreams.DreamService; import android.text.format.DateFormat; import android.util.Log; +import android.view.Display; import android.widget.TextView; import java.util.Date; @@ -51,10 +53,16 @@ public class DozeTestDream extends DreamService { // Doesn't mean anything. Real hardware won't handle it. private static final String TEST_PING_MESSAGE = "test.ping"; + // Not all hardware supports dozing. We should use Display.STATE_DOZE but + // for testing purposes it is convenient to use Display.STATE_ON so the + // test still works on hardware that does not support dozing. + private static final int DISPLAY_STATE_WHEN_DOZING = Display.STATE_ON; + private PowerManager mPowerManager; private PowerManager.WakeLock mWakeLock; private AlarmManager mAlarmManager; private PendingIntent mAlarmIntent; + private Handler mHandler = new Handler(); private TextView mAlarmClock; @@ -64,6 +72,8 @@ public class DozeTestDream extends DreamService { private boolean mDreaming; private DozeHardware mDozeHardware; + private long mLastTime = Long.MIN_VALUE; + @Override public void onCreate() { super.onCreate(); @@ -80,6 +90,8 @@ public class DozeTestDream extends DreamService { registerReceiver(mAlarmReceiver, filter); mAlarmIntent = PendingIntent.getBroadcast(this, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT); + + setDozeScreenState(DISPLAY_STATE_WHEN_DOZING); } @Override @@ -143,13 +155,33 @@ public class DozeTestDream extends DreamService { if (mDreaming) { long now = System.currentTimeMillis(); now -= now % 60000; // back up to last minute boundary + if (mLastTime == now) { + return; + } + mLastTime = now; mTime.setTime(now); mAlarmClock.setText(mTimeFormat.format(mTime)); mAlarmManager.setExact(AlarmManager.RTC_WAKEUP, now + 60000, mAlarmIntent); - mWakeLock.acquire(UPDATE_TIME_TIMEOUT); + mWakeLock.acquire(UPDATE_TIME_TIMEOUT + 5000 /*for testing brightness*/); + + // flash the screen a bit to test these functions + setDozeScreenState(DISPLAY_STATE_WHEN_DOZING); + setDozeScreenBrightness(200); + mHandler.postDelayed(new Runnable() { + @Override + public void run() { + setDozeScreenBrightness(50); + } + }, 2000); + mHandler.postDelayed(new Runnable() { + @Override + public void run() { + setDozeScreenState(Display.STATE_OFF); + } + }, 5000); } } |