Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 970d4132 authored by Jeff Brown's avatar Jeff Brown
Browse files

Allow dreams to control screen state and brightness.

Added setDozeScreenState() and setDozeScreenBrightness() methods to
DreamService.  The values specified here only take effect once
startDozing is called and can be changed while dozing.

This required some significant rework of the display power controller
but the result seems quite nice and better represents the policy
we want to apply.

Changed the test dream a little bit to make it flash the screen
every minute using the new functions.

Bug: 15903322
Change-Id: I83bcc34503f1b87727d2b2b3c0ef08507f9f0808
parent f89bff9e
Loading
Loading
Loading
Loading
+49 −28
Original line number Diff line number Diff line
@@ -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);
            }
        }
    }

+6 −0
Original line number Diff line number Diff line
@@ -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.

+13 −0
Original line number Diff line number Diff line
@@ -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);
+139 −11
Original line number Diff line number Diff line
@@ -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;
@@ -134,7 +138,10 @@ import com.android.internal.util.DumpUtils.Dump;
 *     android:icon="@drawable/my_icon"
 *     android:label="@string/my_dream_label"
 *     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) {
@@ -665,12 +680,117 @@ public class DreamService extends Service implements Window.Callback {
        return mDozeHardware;
    }

    /**
     * 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 {
+2 −2
Original line number Diff line number Diff line
@@ -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);
}
Loading