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

Commit e2f209d2 authored by Sean Stout's avatar Sean Stout
Browse files

PM#goToSleep and PM#wakeUp only affects default display group

This CL changes the behavior of PM#goToSleep to instead turn off the
power for the default display group. PM#wakeUp turns on the default
display group.

If all display groups are turned off, the device will go to sleep. If
any display group is on, the device will remain interactive.

This results in no behavior change if there is a single display group.
However if there are multiple display groups then it will be possible to
interact with ones that are on while others are off.

Bug: 138328918
Bug: 170935083
Bug: 175919649
Test: atest PowerManagerServiceTest
Change-Id: I8b475c38886eda3e43d6e8da7e68102a25da1584
parent 4663bdc7
Loading
Loading
Loading
Loading
+52 −11
Original line number Diff line number Diff line
@@ -47,28 +47,40 @@ public abstract class DisplayManagerInternal {
     * begins adjusting the power state to match what was requested.
     * </p>
     *
     * @param groupId The identifier for the display group being requested to change power state
     * @param request The requested power state.
     * @param waitForNegativeProximity If true, issues a request to wait for
     * @param waitForNegativeProximity If {@code 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.
     * @return {@code true} if display group is ready, {@code 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. If the provided {@code groupId}
     * cannot be found then {@code true} will be returned.
     */
    public abstract boolean requestPowerState(DisplayPowerRequest request,
    public abstract boolean requestPowerState(int groupId, DisplayPowerRequest request,
            boolean waitForNegativeProximity);

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

    /**
     * Returns the id of the {@link com.android.server.display.DisplayGroup} to which the provided
     * display belongs.
     * Registers a display group listener which will be informed of the addition, removal, or change
     * of display groups.
     *
     * @param listener The listener to register.
     */
    public abstract int getDisplayGroupId(int displayId);
    public abstract void registerDisplayGroupListener(DisplayGroupListener listener);

    /**
     * Unregisters a display group listener which will be informed of the addition, removal, or
     * change of display groups.
     *
     * @param listener The listener to unregister.
     */
    public abstract void unregisterDisplayGroupListener(DisplayGroupListener listener);

    /**
     * Screenshot for internal system-only use such as rotation, etc.  This method includes
@@ -451,7 +463,7 @@ public abstract class DisplayManagerInternal {
        void onStateChanged();
        void onProximityPositive();
        void onProximityNegative();
        void onDisplayStateChange(int state); // one of the Display state constants
        void onDisplayStateChange(boolean allInactive, boolean allOff);

        void acquireSuspendBlocker();
        void releaseSuspendBlocker();
@@ -465,4 +477,33 @@ public abstract class DisplayManagerInternal {
    public interface DisplayTransactionListener {
        void onDisplayTransaction(Transaction t);
    }

    /**
     * Called when there are changes to {@link com.android.server.display.DisplayGroup
     * DisplayGroups}.
     */
    public interface DisplayGroupListener {
        /**
         * A new display group with the provided {@code groupId} was added.
         * This is guaranteed to be called <i>before</i> any corresponding calls to
         * {@link android.hardware.display.DisplayManager.DisplayListener} are made.
         */
        void onDisplayGroupAdded(int groupId);

        /**
         * The display group with the provided {@code groupId} was removed.
         *
         * This is guaranteed to be called <i>after</i> any corresponding calls to
         * {@link android.hardware.display.DisplayManager.DisplayListener} are made.
         */
        void onDisplayGroupRemoved(int groupId);

        /**
         * The display group with the provided {@code groupId} has changed.
         *
         * This is guaranteed to be called <i>after</i> any corresponding calls to
         * {@link android.hardware.display.DisplayManager.DisplayListener} are made.
         */
        void onDisplayGroupChanged(int groupId);
    }
}
+70 −10
Original line number Diff line number Diff line
@@ -416,9 +416,21 @@ public final class PowerManager {
    public static final int GO_TO_SLEEP_REASON_QUIESCENT = 10;

    /**
     * Go to sleep reason code: The last powered on display group has been removed.
     * @hide
     */
    public static final int GO_TO_SLEEP_REASON_MAX = GO_TO_SLEEP_REASON_QUIESCENT;
    public static final int GO_TO_SLEEP_REASON_DISPLAY_GROUP_REMOVED = 11;

    /**
     * Go to sleep reason code: Every display group has been turned off.
     * @hide
     */
    public static final int GO_TO_SLEEP_REASON_DISPLAY_GROUPS_TURNED_OFF = 12;

    /**
     * @hide
     */
    public static final int GO_TO_SLEEP_REASON_MAX = GO_TO_SLEEP_REASON_DISPLAY_GROUPS_TURNED_OFF;

    /**
     * @hide
@@ -435,6 +447,8 @@ public final class PowerManager {
            case GO_TO_SLEEP_REASON_ACCESSIBILITY: return "accessibility";
            case GO_TO_SLEEP_REASON_FORCE_SUSPEND: return "force_suspend";
            case GO_TO_SLEEP_REASON_INATTENTIVE: return "inattentive";
            case GO_TO_SLEEP_REASON_DISPLAY_GROUP_REMOVED: return "display_group_removed";
            case GO_TO_SLEEP_REASON_DISPLAY_GROUPS_TURNED_OFF: return "display_groups_turned_off";
            default: return Integer.toString(sleepReason);
        }
    }
@@ -521,6 +535,8 @@ public final class PowerManager {
            WAKE_REASON_WAKE_KEY,
            WAKE_REASON_WAKE_MOTION,
            WAKE_REASON_HDMI,
            WAKE_REASON_DISPLAY_GROUP_ADDED,
            WAKE_REASON_DISPLAY_GROUP_TURNED_ON,
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface WakeReason{}
@@ -588,6 +604,18 @@ public final class PowerManager {
     */
    public static final int WAKE_REASON_LID = 9;

    /**
     * Wake up reason code: Waking due to display group being added.
     * @hide
     */
    public static final int WAKE_REASON_DISPLAY_GROUP_ADDED = 10;

    /**
     * Wake up reason code: Waking due to display group being powered on.
     * @hide
     */
    public static final int WAKE_REASON_DISPLAY_GROUP_TURNED_ON = 11;

    /**
     * Convert the wake reason to a string for debugging purposes.
     * @hide
@@ -604,6 +632,8 @@ public final class PowerManager {
            case WAKE_REASON_WAKE_MOTION: return "WAKE_REASON_WAKE_MOTION";
            case WAKE_REASON_HDMI: return "WAKE_REASON_HDMI";
            case WAKE_REASON_LID: return "WAKE_REASON_LID";
            case WAKE_REASON_DISPLAY_GROUP_ADDED: return "WAKE_REASON_DISPLAY_GROUP_ADDED";
            case WAKE_REASON_DISPLAY_GROUP_TURNED_ON: return "WAKE_REASON_DISPLAY_GROUP_TURNED_ON";
            default: return Integer.toString(wakeReason);
        }
    }
@@ -1194,7 +1224,14 @@ public final class PowerManager {
    }

    /**
     * Forces the device to go to sleep.
     * Forces the {@link com.android.server.display.DisplayGroup#DEFAULT default display group}
     * to turn off.
     *
     * <p>If the {@link com.android.server.display.DisplayGroup#DEFAULT default display group} is
     * turned on it will be turned off. If all displays are off as a result of this action the
     * device will be put to sleep. If the {@link com.android.server.display.DisplayGroup#DEFAULT
     * default display group} is already off then nothing will happen.
     *
     * <p>
     * Overrides all the wake locks that are held.
     * This is what happens when the power key is pressed to turn off the screen.
@@ -1217,7 +1254,14 @@ public final class PowerManager {
    }

    /**
     * Forces the device to go to sleep.
     * Forces the {@link com.android.server.display.DisplayGroup#DEFAULT default display group}
     * to turn off.
     *
     * <p>If the {@link com.android.server.display.DisplayGroup#DEFAULT default display group} is
     * turned on it will be turned off. If all displays are off as a result of this action the
     * device will be put to sleep. If the {@link com.android.server.display.DisplayGroup#DEFAULT
     * default display group} is already off then nothing will happen.
     *
     * <p>
     * Overrides all the wake locks that are held.
     * This is what happens when the power key is pressed to turn off the screen.
@@ -1247,9 +1291,15 @@ public final class PowerManager {
    }

    /**
     * Forces the device to wake up from sleep.
     * Forces the {@link com.android.server.display.DisplayGroup#DEFAULT default display group}
     * to turn on.
     *
     * <p>If the {@link com.android.server.display.DisplayGroup#DEFAULT default display group} is
     * turned off it will be turned on. Additionally, if the device is asleep it will be awoken. If
     * the {@link com.android.server.display.DisplayGroup#DEFAULT default display group} is already
     * on then nothing will happen.
     *
     * <p>
     * If the device is currently asleep, wakes it up, otherwise does nothing.
     * This is what happens when the power key is pressed to turn on the screen.
     * </p><p>
     * Requires the {@link android.Manifest.permission#DEVICE_POWER} permission.
@@ -1272,9 +1322,15 @@ public final class PowerManager {
    }

    /**
     * Forces the device to wake up from sleep.
     * Forces the {@link com.android.server.display.DisplayGroup#DEFAULT default display group}
     * to turn on.
     *
     * <p>If the {@link com.android.server.display.DisplayGroup#DEFAULT default display group} is
     * turned off it will be turned on. Additionally, if the device is asleep it will be awoken. If
     * the {@link com.android.server.display.DisplayGroup#DEFAULT default display group} is already
     * on then nothing will happen.
     *
     * <p>
     * If the device is currently asleep, wakes it up, otherwise does nothing.
     * This is what happens when the power key is pressed to turn on the screen.
     * </p><p>
     * Requires the {@link android.Manifest.permission#DEVICE_POWER} permission.
@@ -1301,9 +1357,13 @@ public final class PowerManager {
    }

    /**
     * Forces the device to wake up from sleep.
     * Forces the {@link android.view.Display#DEFAULT_DISPLAY default display} to turn on.
     *
     * <p>If the {@link android.view.Display#DEFAULT_DISPLAY default display} is turned off it will
     * be turned on. Additionally, if the device is asleep it will be awoken. If the {@link
     * android.view.Display#DEFAULT_DISPLAY default display} is already on then nothing will happen.
     *
     * <p>
     * If the device is currently asleep, wakes it up, otherwise does nothing.
     * This is what happens when the power key is pressed to turn on the screen.
     * </p><p>
     * Requires the {@link android.Manifest.permission#DEVICE_POWER} permission.
+31 −3
Original line number Diff line number Diff line
@@ -21,7 +21,8 @@ import java.util.List;

/**
 * Represents a collection of {@link LogicalDisplay}s which act in unison for certain behaviors and
 * operations.
 * operations; particularly display-state.
 *
 * @hide
 */
public class DisplayGroup {
@@ -35,17 +36,44 @@ public class DisplayGroup {
        mGroupId = groupId;
    }

    /** Returns the identifier for the Group. */
    int getGroupId() {
        return mGroupId;
    }

    void addDisplay(LogicalDisplay display) {
    /**
     * Adds the provided {@code display} to the Group
     *
     * @param display the {@link LogicalDisplay} to add to the Group
     */
    void addDisplayLocked(LogicalDisplay display) {
        if (!mDisplays.contains(display)) {
            mDisplays.add(display);
        }
    }

    boolean removeDisplay(LogicalDisplay display) {
    /**
     * Removes the provided {@code display} from the Group.
     *
     * @param display The {@link LogicalDisplay} to remove from the Group.
     * @return {@code true} if the {@code display} was removed; otherwise {@code false}
     */
    boolean removeDisplayLocked(LogicalDisplay display) {
        return mDisplays.remove(display);
    }

    /** Returns {@code true} if there are no {@link LogicalDisplay LogicalDisplays} in the Group. */
    boolean isEmptyLocked() {
        return mDisplays.isEmpty();
    }

    /** Returns the number of {@link LogicalDisplay LogicalDisplays} in the Group. */
    int getSizeLocked() {
        return mDisplays.size();
    }

    /** Returns the ID of the {@link LogicalDisplay} at the provided {@code index}. */
    int getIdLocked(int index) {
        return mDisplays.get(index).getDisplayIdLocked();
    }
}
+103 −22
Original line number Diff line number Diff line
@@ -56,6 +56,7 @@ import android.hardware.display.Curve;
import android.hardware.display.DisplayManager;
import android.hardware.display.DisplayManagerGlobal;
import android.hardware.display.DisplayManagerInternal;
import android.hardware.display.DisplayManagerInternal.DisplayGroupListener;
import android.hardware.display.DisplayManagerInternal.DisplayTransactionListener;
import android.hardware.display.DisplayViewport;
import android.hardware.display.DisplayedContentSample;
@@ -190,6 +191,7 @@ public final class DisplayManagerService extends SystemService {
    private static final int MSG_UPDATE_VIEWPORT = 5;
    private static final int MSG_LOAD_BRIGHTNESS_CONFIGURATION = 6;
    private static final int MSG_DELIVER_DISPLAY_EVENT_FRAME_RATE_OVERRIDE = 7;
    private static final int MSG_DELIVER_DISPLAY_GROUP_EVENT = 8;

    private final Context mContext;
    private final DisplayManagerHandler mHandler;
@@ -237,36 +239,54 @@ public final class DisplayManagerService extends SystemService {
    private final CopyOnWriteArrayList<DisplayTransactionListener> mDisplayTransactionListeners =
            new CopyOnWriteArrayList<DisplayTransactionListener>();

    /** List of all display group listeners. */
    private final CopyOnWriteArrayList<DisplayGroupListener> mDisplayGroupListeners =
            new CopyOnWriteArrayList<>();

    /** All {@link DisplayPowerController}s indexed by {@link LogicalDisplay} ID. */
    private final SparseArray<DisplayPowerController> mDisplayPowerControllers =
            new SparseArray<>();

    /** {@link DisplayBlanker} used by all {@link DisplayPowerController}s. */
    private final DisplayBlanker mDisplayBlanker = new DisplayBlanker() {
        // Synchronized to avoid race conditions when updating multiple display states.
        @Override
        public void requestDisplayState(int displayId, int state, float brightness) {
            // TODO (b/168210494): Stop applying default display state to all displays.
            if (displayId != Display.DEFAULT_DISPLAY) {
                return;
            }
            final int[] displayIds;
        public synchronized void requestDisplayState(int displayId, int state, float brightness) {
            boolean allInactive = true;
            boolean allOff = true;
            final boolean stateChanged;
            synchronized (mSyncRoot) {
                displayIds = mLogicalDisplayMapper.getDisplayIdsLocked();
                final int index = mDisplayStates.indexOfKey(displayId);
                final int newState = mDisplayStates.valueAt(index);
                stateChanged = index == -1 || state != newState;
                if (stateChanged) {
                    final int size = mDisplayStates.size();
                    for (int i = 0; i < size; i++) {
                        final int displayState = i == index ? newState : state;
                        if (displayState != Display.STATE_OFF) {
                            allOff = false;
                        }
                        if (Display.isActiveState(displayState)) {
                            allInactive = false;
                        }
                        if (!allOff && !allInactive) {
                            break;
                        }
                    }
                }
            }

            // The order of operations is important for legacy reasons.
            if (state == Display.STATE_OFF) {
                for (int id : displayIds) {
                    requestDisplayStateInternal(id, state, brightness);
                }
                requestDisplayStateInternal(displayId, state, brightness);
            }

            mDisplayPowerCallbacks.onDisplayStateChange(state);
            if (stateChanged) {
                mDisplayPowerCallbacks.onDisplayStateChange(allInactive, allOff);
            }

            if (state != Display.STATE_OFF) {
                for (int id : displayIds) {
                    requestDisplayStateInternal(id, state, brightness);
                }
                requestDisplayStateInternal(displayId, state, brightness);
            }
        }
    };
@@ -1151,7 +1171,7 @@ public final class DisplayManagerService extends SystemService {

    private void handleLogicalDisplayRemovedLocked(@NonNull LogicalDisplay display) {
        final int displayId = display.getDisplayIdLocked();
        mDisplayPowerControllers.delete(displayId);
        mDisplayPowerControllers.removeReturnOld(displayId).stop();
        mDisplayStates.delete(displayId);
        mDisplayBrightnesses.delete(displayId);
        DisplayManagerGlobal.invalidateLocalDisplayInfoCaches();
@@ -1668,6 +1688,11 @@ public final class DisplayManagerService extends SystemService {
        mHandler.sendMessage(msg);
    }

    private void sendDisplayGroupEvent(int groupId, int event) {
        Message msg = mHandler.obtainMessage(MSG_DELIVER_DISPLAY_GROUP_EVENT, groupId, event);
        mHandler.sendMessage(msg);
    }

    private void sendDisplayEventFrameRateOverrideLocked(int displayId) {
        Message msg = mHandler.obtainMessage(MSG_DELIVER_DISPLAY_EVENT_FRAME_RATE_OVERRIDE,
                displayId, DisplayManagerGlobal.EVENT_DISPLAY_CHANGED);
@@ -1712,6 +1737,35 @@ public final class DisplayManagerService extends SystemService {
        mTempCallbacks.clear();
    }

    // Runs on Handler thread.
    // Delivers display group event notifications to callbacks.
    private void deliverDisplayGroupEvent(int groupId, int event) {
        if (DEBUG) {
            Slog.d(TAG, "Delivering display group event: groupId=" + groupId + ", event="
                    + event);
        }

        switch (event) {
            case LogicalDisplayMapper.DISPLAY_GROUP_EVENT_ADDED:
                for (DisplayGroupListener listener : mDisplayGroupListeners) {
                    listener.onDisplayGroupAdded(groupId);
                }
                break;

            case LogicalDisplayMapper.DISPLAY_GROUP_EVENT_CHANGED:
                for (DisplayGroupListener listener : mDisplayGroupListeners) {
                    listener.onDisplayGroupChanged(groupId);
                }
                break;

            case LogicalDisplayMapper.DISPLAY_GROUP_EVENT_REMOVED:
                for (DisplayGroupListener listener : mDisplayGroupListeners) {
                    listener.onDisplayGroupRemoved(groupId);
                }
                break;
        }
    }

    private IMediaProjectionManager getProjectionService() {
        if (mProjectionService == null) {
            IBinder b = ServiceManager.getService(Context.MEDIA_PROJECTION_SERVICE);
@@ -1934,6 +1988,11 @@ public final class DisplayManagerService extends SystemService {
                    }
                    deliverDisplayEvent(msg.arg1, uids, msg.arg2);
                    break;

                case MSG_DELIVER_DISPLAY_GROUP_EVENT:
                    deliverDisplayGroupEvent(msg.arg1, msg.arg2);
                    break;

            }
        }
    }
@@ -1964,6 +2023,11 @@ public final class DisplayManagerService extends SystemService {
            }
        }

        @Override
        public void onDisplayGroupEventLocked(int groupId, int event) {
            sendDisplayGroupEvent(groupId, event);
        }

        @Override
        public void onTraversalRequested() {
            synchronized (mSyncRoot) {
@@ -2699,11 +2763,25 @@ public final class DisplayManagerService extends SystemService {
        }

        @Override
        public boolean requestPowerState(DisplayPowerRequest request,
        public boolean requestPowerState(int groupId, DisplayPowerRequest request,
                boolean waitForNegativeProximity) {
            synchronized (mSyncRoot) {
                return mDisplayPowerControllers.get(Display.DEFAULT_DISPLAY)
                        .requestPowerState(request, waitForNegativeProximity);
                final DisplayGroup displayGroup = mLogicalDisplayMapper.getDisplayGroupLocked(
                        groupId);
                if (displayGroup == null) {
                    return true;
                }

                final int size = displayGroup.getSizeLocked();
                boolean ready = true;
                for (int i = 0; i < size; i++) {
                    final DisplayPowerController displayPowerController =
                            mDisplayPowerControllers.get(displayGroup.getIdLocked(i));
                    ready &= displayPowerController.requestPowerState(request,
                            waitForNegativeProximity);
                }

                return ready;
            }
        }

@@ -2716,10 +2794,13 @@ public final class DisplayManagerService extends SystemService {
        }

        @Override
        public int getDisplayGroupId(int displayId) {
            synchronized (mSyncRoot) {
                return mLogicalDisplayMapper.getDisplayGroupIdLocked(displayId);
        public void registerDisplayGroupListener(DisplayGroupListener listener) {
            mDisplayGroupListeners.add(listener);
        }

        @Override
        public void unregisterDisplayGroupListener(DisplayGroupListener listener) {
            mDisplayGroupListeners.remove(listener);
        }

        @Override
+11 −0
Original line number Diff line number Diff line
@@ -683,6 +683,17 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
        // TODO: b/175821789 - Support high brightness on multiple (folding) displays
    }

    /**
     * Unregisters all listeners and interrupts all running threads; halting future work.
     *
     * This method should be called when the DisplayPowerController is no longer in use; i.e. when
     * the {@link #mDisplayId display} has been removed.
     */
    public void stop() {
        mContext.getContentResolver().unregisterContentObserver(mSettingsObserver);
        mPowerState.stop();
    }

    private void sendUpdatePowerState() {
        synchronized (mLock) {
            sendUpdatePowerStateLocked();
Loading