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

Commit ad9ef191 authored by Jeff Brown's avatar Jeff Brown
Browse files

Move display power controller to display manager service. (DO NOT MERGE)

This refactoring is in preparation for enabling the display manager
to have more control over the blanking state of individual displays.
There are no functional changes.  Some bits will be cleaned up in
a subsequent patch.

Bug: 13133142
Change-Id: Ib811835e8757449c7899ac61807029baaf998161
parent ce802f48
Loading
Loading
Loading
Loading
+164 −0
Original line number Diff line number Diff line
@@ -16,6 +16,9 @@

package android.hardware.display;

import android.hardware.SensorManager;
import android.os.Handler;
import android.os.PowerManager;
import android.view.DisplayInfo;

/**
@@ -24,6 +27,36 @@ import android.view.DisplayInfo;
 * @hide Only for use within the system server.
 */
public abstract class DisplayManagerInternal {
    /**
     * Called by the power manager to initialize power management facilities.
     */
    public abstract void initPowerManagement(DisplayPowerCallbacks callbacks,
            Handler handler, SensorManager sensorManager);

    /**
     * Called by the power manager to request a new power state.
     * <p>
     * The display power controller makes a copy of the provided object and then
     * begins adjusting the power state to match what was requested.
     * </p>
     *
     * @param request The requested power state.
     * @param waitForNegativeProximity If true, issues a request to wait for
     * negative proximity before turning the screen back on, assuming the screen
     * was turned off by the proximity sensor.
     * @return True if display is ready, false if there are important changes that must
     * be made asynchronously (such as turning the screen on), in which case the caller
     * should grab a wake lock, watch for {@link DisplayPowerCallbacks#onStateChanged()}
     * then try the request again later until the state converges.
     */
    public abstract boolean requestPowerState(DisplayPowerRequest request,
            boolean waitForNegativeProximity);

    /**
     * Returns true if the proximity sensor screen-off function is available.
     */
    public abstract boolean isProximitySensorAvailable();

    /**
     * Called by the power manager to blank all displays.
     */
@@ -98,6 +131,137 @@ public abstract class DisplayManagerInternal {
    public abstract void setDisplayHasContent(int displayId, boolean hasContent,
            boolean inTraversal);

    /**
     * Describes the requested power state of the display.
     *
     * This object is intended to describe the general characteristics of the
     * power state, such as whether the screen should be on or off and the current
     * brightness controls leaving the DisplayPowerController to manage the
     * details of how the transitions between states should occur.  The goal is for
     * the PowerManagerService to focus on the global power state and not
     * 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;

        // If true, the proximity sensor overrides the screen state when an object is
        // nearby, turning it off temporarily until the object is moved away.
        public boolean useProximitySensor;

        // The desired screen brightness in the range 0 (minimum / off) to 255 (brightest).
        // The display power controller may choose to clamp the brightness.
        // When auto-brightness is enabled, this field should specify a nominal default
        // value to use while waiting for the light sensor to report enough data.
        public int screenBrightness;

        // The screen auto-brightness adjustment factor in the range -1 (dimmer) to 1 (brighter).
        public float screenAutoBrightnessAdjustment;

        // If true, enables automatic brightness control.
        public boolean useAutoBrightness;

        // If true, prevents the screen from completely turning on if it is currently off.
        // The display does not enter a "ready" state if this flag is true and screen on is
        // blocked.  The window manager policy blocks screen on while it prepares the keyguard to
        // prevent the user from seeing intermediate updates.
        //
        // Technically, we may not block the screen itself from turning on (because that introduces
        // extra unnecessary latency) but we do prevent content on screen from becoming
        // visible to the user.
        public boolean blockScreenOn;

        public DisplayPowerRequest() {
            screenState = SCREEN_STATE_BRIGHT;
            useProximitySensor = false;
            screenBrightness = PowerManager.BRIGHTNESS_ON;
            screenAutoBrightnessAdjustment = 0.0f;
            useAutoBrightness = false;
            blockScreenOn = false;
        }

        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 void copyFrom(DisplayPowerRequest other) {
            screenState = other.screenState;
            useProximitySensor = other.useProximitySensor;
            screenBrightness = other.screenBrightness;
            screenAutoBrightnessAdjustment = other.screenAutoBrightnessAdjustment;
            useAutoBrightness = other.useAutoBrightness;
            blockScreenOn = other.blockScreenOn;
        }

        @Override
        public boolean equals(Object o) {
            return o instanceof DisplayPowerRequest
                    && equals((DisplayPowerRequest)o);
        }

        public boolean equals(DisplayPowerRequest other) {
            return other != null
                    && screenState == other.screenState
                    && useProximitySensor == other.useProximitySensor
                    && screenBrightness == other.screenBrightness
                    && screenAutoBrightnessAdjustment == other.screenAutoBrightnessAdjustment
                    && useAutoBrightness == other.useAutoBrightness
                    && blockScreenOn == other.blockScreenOn;
        }

        @Override
        public int hashCode() {
            return 0; // don't care
        }

        @Override
        public String toString() {
            return "screenState=" + screenState
                    + ", useProximitySensor=" + useProximitySensor
                    + ", screenBrightness=" + screenBrightness
                    + ", screenAutoBrightnessAdjustment=" + screenAutoBrightnessAdjustment
                    + ", useAutoBrightness=" + useAutoBrightness
                    + ", blockScreenOn=" + blockScreenOn;
        }
    }

    /**
     * Asynchronous callbacks from the power controller to the power manager service.
     */
    public interface DisplayPowerCallbacks {
        void onStateChanged();
        void onProximityPositive();
        void onProximityNegative();

        void acquireSuspendBlocker();
        void releaseSuspendBlocker();

        void blankAllDisplays();
        void unblankAllDisplays();
    }

    /**
     * Called within a Surface transaction whenever the size or orientation of a
     * display may have changed.  Provides an opportunity for the client to
+29 −0
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ import com.android.internal.util.IndentingPrintWriter;
import android.Manifest;
import android.content.Context;
import android.content.pm.PackageManager;
import android.hardware.SensorManager;
import android.hardware.display.DisplayManager;
import android.hardware.display.DisplayManagerGlobal;
import android.hardware.display.DisplayManagerInternal;
@@ -172,6 +173,9 @@ public final class DisplayManagerService extends SystemService {
    private final CopyOnWriteArrayList<DisplayTransactionListener> mDisplayTransactionListeners =
            new CopyOnWriteArrayList<DisplayTransactionListener>();

    // Display power controller.
    private DisplayPowerController mDisplayPowerController;

    // Set to true if all displays have been blanked by the power manager.
    private int mAllDisplayBlankStateFromPowerManager = DISPLAY_BLANK_STATE_UNKNOWN;

@@ -936,6 +940,10 @@ public final class DisplayManagerService extends SystemService {
                pw.println("  " + i + ": mPid=" + callback.mPid
                        + ", mWifiDisplayScanRequested=" + callback.mWifiDisplayScanRequested);
            }

            if (mDisplayPowerController != null) {
                mDisplayPowerController.dump(pw);
            }
        }
    }

@@ -1313,6 +1321,27 @@ public final class DisplayManagerService extends SystemService {
    }

    private final class LocalService extends DisplayManagerInternal {
        @Override
        public void initPowerManagement(DisplayPowerCallbacks callbacks, Handler handler,
                SensorManager sensorManager) {
            synchronized (mSyncRoot) {
                mDisplayPowerController = new DisplayPowerController(
                        mContext, callbacks, handler, sensorManager);
            }
        }

        @Override
        public boolean requestPowerState(DisplayPowerRequest request,
                boolean waitForNegativeProximity) {
            return mDisplayPowerController.requestPowerState(request,
                    waitForNegativeProximity);
        }

        @Override
        public boolean isProximitySensorAvailable() {
            return mDisplayPowerController.isProximitySensorAvailable();
        }

        @Override
        public void blankAllDisplaysFromPowerManager() {
            blankAllDisplaysFromPowerManagerInternal();
+45 −53
Original line number Diff line number Diff line
@@ -14,8 +14,11 @@
 * limitations under the License.
 */

package com.android.server.power;
package com.android.server.display;

import com.android.internal.app.IBatteryStats;
import com.android.server.LocalServices;
import com.android.server.am.BatteryStatsService;
import com.android.server.lights.LightsManager;
import com.android.server.twilight.TwilightListener;
import com.android.server.twilight.TwilightManager;
@@ -29,10 +32,13 @@ import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.hardware.display.DisplayManagerInternal.DisplayPowerCallbacks;
import android.hardware.display.DisplayManagerInternal.DisplayPowerRequest;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.PowerManager;
import android.os.RemoteException;
import android.os.SystemClock;
import android.text.format.DateUtils;
import android.util.FloatMath;
@@ -160,23 +166,15 @@ final class DisplayPowerController {

    private final Object mLock = new Object();

    // Notifier for sending asynchronous notifications.
    private final Notifier mNotifier;

    // The display suspend blocker.
    // Held while there are pending state change notifications.
    private final SuspendBlocker mDisplaySuspendBlocker;

    // The display blanker.
    private final DisplayBlanker mDisplayBlanker;

    // Our handler.
    private final DisplayControllerHandler mHandler;

    // Asynchronous callbacks into the power manager service.
    // Only invoked from the handler thread while no locks are held.
    private final Callbacks mCallbacks;
    private Handler mCallbackHandler;
    private final DisplayPowerCallbacks mCallbacks;

    // Battery stats.
    private final IBatteryStats mBatteryStats;

    // The lights service.
    private final LightsManager mLights;
@@ -350,19 +348,14 @@ final class DisplayPowerController {
    /**
     * Creates the display power controller.
     */
    public DisplayPowerController(Looper looper, Context context, Notifier notifier,
            LightsManager lights, TwilightManager twilight, SensorManager sensorManager,
            SuspendBlocker displaySuspendBlocker, DisplayBlanker displayBlanker,
            Callbacks callbacks, Handler callbackHandler) {
        mHandler = new DisplayControllerHandler(looper);
        mNotifier = notifier;
        mDisplaySuspendBlocker = displaySuspendBlocker;
        mDisplayBlanker = displayBlanker;
    public DisplayPowerController(Context context,
            DisplayPowerCallbacks callbacks, Handler handler, SensorManager sensorManager) {
        mHandler = new DisplayControllerHandler(handler.getLooper());
        mCallbacks = callbacks;
        mCallbackHandler = callbackHandler;

        mLights = lights;
        mTwilight = twilight;
        mBatteryStats = BatteryStatsService.getService();
        mLights = LocalServices.getService(LightsManager.class);
        mTwilight = LocalServices.getService(TwilightManager.class);
        mSensorManager = sensorManager;

        final Resources resources = context.getResources();
@@ -527,7 +520,7 @@ final class DisplayPowerController {
    }

    private void initialize() {
        mPowerState = new DisplayPowerState(new ElectronBeam(), mDisplayBlanker,
        mPowerState = new DisplayPowerState(new ElectronBeam(), mCallbacks,
                mLights.getLight(LightsManager.LIGHT_ID_BACKLIGHT));

        mElectronBeamOnAnimator = ObjectAnimator.ofFloat(
@@ -779,10 +772,14 @@ final class DisplayPowerController {
    private void setScreenOn(boolean on) {
        if (mPowerState.isScreenOn() != on) {
            mPowerState.setScreenOn(on);
            try {
                if (on) {
                mNotifier.onScreenOn();
                    mBatteryStats.noteScreenOn();
                } else {
                mNotifier.onScreenOff();
                    mBatteryStats.noteScreenOff();
                }
            } catch (RemoteException ex) {
                // same process
            }
        }
    }
@@ -811,7 +808,11 @@ final class DisplayPowerController {

    private void animateScreenBrightness(int target, int rate) {
        if (mScreenBrightnessRampAnimator.animateTo(target, rate)) {
            mNotifier.onScreenBrightness(target);
            try {
                mBatteryStats.noteScreenBrightness(target);
            } catch (RemoteException ex) {
                // same process
            }
        }
    }

@@ -896,13 +897,13 @@ final class DisplayPowerController {
    private void clearPendingProximityDebounceTime() {
        if (mPendingProximityDebounceTime >= 0) {
            mPendingProximityDebounceTime = -1;
            mDisplaySuspendBlocker.release(); // release wake lock
            mCallbacks.releaseSuspendBlocker(); // release wake lock
        }
    }

    private void setPendingProximityDebounceTime(long debounceTime) {
        if (mPendingProximityDebounceTime < 0) {
            mDisplaySuspendBlocker.acquire(); // acquire wake lock
            mCallbacks.acquireSuspendBlocker(); // acquire wake lock
        }
        mPendingProximityDebounceTime = debounceTime;
    }
@@ -1172,48 +1173,48 @@ final class DisplayPowerController {
    }

    private void sendOnStateChangedWithWakelock() {
        mDisplaySuspendBlocker.acquire();
        mCallbackHandler.post(mOnStateChangedRunnable);
        mCallbacks.acquireSuspendBlocker();
        mHandler.post(mOnStateChangedRunnable);
    }

    private final Runnable mOnStateChangedRunnable = new Runnable() {
        @Override
        public void run() {
            mCallbacks.onStateChanged();
            mDisplaySuspendBlocker.release();
            mCallbacks.releaseSuspendBlocker();
        }
    };

    private void sendOnProximityPositiveWithWakelock() {
        mDisplaySuspendBlocker.acquire();
        mCallbackHandler.post(mOnProximityPositiveRunnable);
        mCallbacks.acquireSuspendBlocker();
        mHandler.post(mOnProximityPositiveRunnable);
    }

    private final Runnable mOnProximityPositiveRunnable = new Runnable() {
        @Override
        public void run() {
            mCallbacks.onProximityPositive();
            mDisplaySuspendBlocker.release();
            mCallbacks.releaseSuspendBlocker();
        }
    };

    private void sendOnProximityNegativeWithWakelock() {
        mDisplaySuspendBlocker.acquire();
        mCallbackHandler.post(mOnProximityNegativeRunnable);
        mCallbacks.acquireSuspendBlocker();
        mHandler.post(mOnProximityNegativeRunnable);
    }

    private final Runnable mOnProximityNegativeRunnable = new Runnable() {
        @Override
        public void run() {
            mCallbacks.onProximityNegative();
            mDisplaySuspendBlocker.release();
            mCallbacks.releaseSuspendBlocker();
        }
    };

    public void dump(final PrintWriter pw) {
        synchronized (mLock) {
            pw.println();
            pw.println("Display Controller Locked State:");
            pw.println("Display Power Controller Locked State:");
            pw.println("  mDisplayReadyLocked=" + mDisplayReadyLocked);
            pw.println("  mPendingRequestLocked=" + mPendingRequestLocked);
            pw.println("  mPendingRequestChangedLocked=" + mPendingRequestChangedLocked);
@@ -1223,7 +1224,7 @@ final class DisplayPowerController {
        }

        pw.println();
        pw.println("Display Controller Configuration:");
        pw.println("Display Power Controller Configuration:");
        pw.println("  mScreenBrightnessDozeConfig=" + mScreenBrightnessDozeConfig);
        pw.println("  mScreenBrightnessDimConfig=" + mScreenBrightnessDimConfig);
        pw.println("  mScreenBrightnessRangeMinimum=" + mScreenBrightnessRangeMinimum);
@@ -1243,7 +1244,7 @@ final class DisplayPowerController {

    private void dumpLocal(PrintWriter pw) {
        pw.println();
        pw.println("Display Controller Thread State:");
        pw.println("Display Power Controller Thread State:");
        pw.println("  mPowerRequest=" + mPowerRequest);
        pw.println("  mWaitingForNegativeProximity=" + mWaitingForNegativeProximity);

@@ -1302,15 +1303,6 @@ final class DisplayPowerController {
        }
    }

    /**
     * Asynchronous callbacks from the power controller to the power manager service.
     */
    public interface Callbacks {
        void onStateChanged();
        void onProximityPositive();
        void onProximityNegative();
    }

    private final class DisplayControllerHandler extends Handler {
        public DisplayControllerHandler(Looper looper) {
            super(looper, null, true /*async*/);
+10 −10
Original line number Diff line number Diff line
@@ -14,10 +14,11 @@
 * limitations under the License.
 */

package com.android.server.power;
package com.android.server.display;

import com.android.server.lights.Light;

import android.hardware.display.DisplayManagerInternal.DisplayPowerCallbacks;
import android.os.AsyncTask;
import android.os.Handler;
import android.os.Looper;
@@ -32,8 +33,8 @@ import java.io.PrintWriter;
/**
 * Controls the display power state.
 * <p>
 * This component is similar in nature to a {@link View} except that it describes
 * the properties of a display.  When properties are changed, the component
 * This component is similar in nature to a {@link android.view.View} except that it
 * describes the properties of a display.  When properties are changed, the component
 * invalidates itself and posts a callback to apply the changes in a consistent order.
 * This mechanism enables multiple properties of the display power state to be animated
 * together smoothly by the animation framework.  Some of the work to blank or unblank
@@ -43,8 +44,7 @@ import java.io.PrintWriter;
 * that belongs to the {@link DisplayPowerController}.
 * </p><p>
 * We don't need to worry about holding a suspend blocker here because the
 * {@link PowerManagerService} does that for us whenever there is a change
 * in progress.
 * power manager does that for us whenever there is a change in progress.
 * </p>
 */
final class DisplayPowerState {
@@ -55,7 +55,7 @@ final class DisplayPowerState {
    private final Handler mHandler;
    private final Choreographer mChoreographer;
    private final ElectronBeam mElectronBeam;
    private final DisplayBlanker mDisplayBlanker;
    private final DisplayPowerCallbacks mCallbacks;
    private final Light mBacklight;
    private final PhotonicModulator mPhotonicModulator;

@@ -72,11 +72,11 @@ final class DisplayPowerState {
    private Runnable mCleanListener;

    public DisplayPowerState(ElectronBeam electronBean,
            DisplayBlanker displayBlanker, Light backlight) {
            DisplayPowerCallbacks callbacks, Light backlight) {
        mHandler = new Handler(true /*async*/);
        mChoreographer = Choreographer.getInstance();
        mElectronBeam = electronBean;
        mDisplayBlanker = displayBlanker;
        mCallbacks = callbacks;
        mBacklight = backlight;
        mPhotonicModulator = new PhotonicModulator();

@@ -403,13 +403,13 @@ final class DisplayPowerState {
                                + ", backlight=" + backlight);
                    }
                    if (onChanged && on) {
                        mDisplayBlanker.unblankAllDisplays();
                        mCallbacks.unblankAllDisplays();
                    }
                    if (backlightChanged) {
                        mBacklight.setBrightness(backlight);
                    }
                    if (onChanged && !on) {
                        mDisplayBlanker.blankAllDisplays();
                        mCallbacks.blankAllDisplays();
                    }
                }

+1 −1
Original line number Diff line number Diff line
@@ -14,7 +14,7 @@
 * limitations under the License.
 */

package com.android.server.power;
package com.android.server.display;

import java.io.PrintWriter;
import java.nio.ByteBuffer;
Loading