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

Commit 8346e407 authored by Sean Stout's avatar Sean Stout
Browse files

Implement Phase 4 of per-display power states

Remove the concept of mGlobalDisplayState and instead track the state of
each display individually. The internal methods of DisplayManagerService
have been updated to allow for displays to update individually, however
for this phase there is temporary code which still makes every display
update when the default display state is updated.

Bug: 138328918
Test: manual
Change-Id: I3b3d8df1d0fc0cd7934474a3664a69bde585504f
parent efa2acc6
Loading
Loading
Loading
Loading
+81 −57
Original line number Original line Diff line number Diff line
@@ -88,6 +88,7 @@ import android.util.IntArray;
import android.util.Pair;
import android.util.Pair;
import android.util.Slog;
import android.util.Slog;
import android.util.SparseArray;
import android.util.SparseArray;
import android.util.SparseIntArray;
import android.util.Spline;
import android.util.Spline;
import android.view.Display;
import android.view.Display;
import android.view.DisplayInfo;
import android.view.DisplayInfo;
@@ -95,6 +96,7 @@ import android.view.IDisplayFoldListener;
import android.view.Surface;
import android.view.Surface;
import android.view.SurfaceControl;
import android.view.SurfaceControl;


import com.android.internal.BrightnessSynchronizer;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.DumpUtils;
import com.android.internal.util.DumpUtils;
@@ -111,7 +113,6 @@ import com.android.server.wm.WindowManagerInternal;
import java.io.FileDescriptor;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.Optional;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.function.Consumer;
import java.util.function.Consumer;
@@ -234,15 +235,28 @@ public final class DisplayManagerService extends SystemService {
    private final DisplayBlanker mDisplayBlanker = new DisplayBlanker() {
    private final DisplayBlanker mDisplayBlanker = new DisplayBlanker() {
        @Override
        @Override
        public void requestDisplayState(int displayId, int state, float brightness) {
        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;
            synchronized (mSyncRoot) {
                displayIds = mLogicalDisplayMapper.getDisplayIdsLocked();
            }

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


            mDisplayPowerCallbacks.onDisplayStateChange(state);
            mDisplayPowerCallbacks.onDisplayStateChange(state);


            if (state != Display.STATE_OFF) {
            if (state != Display.STATE_OFF) {
                requestGlobalDisplayStateInternal(state, brightness);
                for (int id : displayIds) {
                    requestDisplayStateInternal(id, state, brightness);
                }
            }
            }
        }
        }
    };
    };
@@ -256,13 +270,16 @@ public final class DisplayManagerService extends SystemService {
    /** The {@link Handler} used by all {@link DisplayPowerController}s. */
    /** The {@link Handler} used by all {@link DisplayPowerController}s. */
    private Handler mPowerHandler;
    private Handler mPowerHandler;


    // The overall display state, independent of changes that might influence one
    // A map from LogicalDisplay ID to display power state.
    // display or another in particular.
    @GuardedBy("mSyncRoot")
    private int mGlobalDisplayState = Display.STATE_ON;
    private final SparseIntArray mDisplayStates = new SparseIntArray();

    // A map from LogicalDisplay ID to display brightness.
    @GuardedBy("mSyncRoot")
    private final SparseArray<Float> mDisplayBrightnesses = new SparseArray<>();


    // The overall display brightness.
    // The default brightness.
    // For now, this only applies to the default display but we may split it up eventually.
    private final float mDisplayDefaultBrightness;
    private float mGlobalDisplayBrightness;


    // Set to true when there are pending display changes that have yet to be applied
    // Set to true when there are pending display changes that have yet to be applied
    // to the surface flinger state.
    // to the surface flinger state.
@@ -316,11 +333,6 @@ public final class DisplayManagerService extends SystemService {
    // DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY flag set.
    // DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY flag set.
    private final int mDefaultDisplayDefaultColorMode;
    private final int mDefaultDisplayDefaultColorMode;


    // Temporary list of deferred work to perform when setting the display state.
    // Only used by requestDisplayState.  The field is self-synchronized and only
    // intended for use inside of the requestGlobalDisplayStateInternal function.
    private final ArrayList<Runnable> mTempDisplayStateWorkQueue = new ArrayList<Runnable>();

    // Lists of UIDs that are present on the displays. Maps displayId -> array of UIDs.
    // Lists of UIDs that are present on the displays. Maps displayId -> array of UIDs.
    private final SparseArray<IntArray> mDisplayAccessUIDs = new SparseArray<>();
    private final SparseArray<IntArray> mDisplayAccessUIDs = new SparseArray<>();


@@ -371,7 +383,7 @@ public final class DisplayManagerService extends SystemService {
        mMinimumBrightnessSpline = Spline.createSpline(lux, nits);
        mMinimumBrightnessSpline = Spline.createSpline(lux, nits);


        PowerManager pm = mContext.getSystemService(PowerManager.class);
        PowerManager pm = mContext.getSystemService(PowerManager.class);
        mGlobalDisplayBrightness = pm.getBrightnessConstraint(
        mDisplayDefaultBrightness = pm.getBrightnessConstraint(
                PowerManager.BRIGHTNESS_CONSTRAINT_TYPE_DEFAULT);
                PowerManager.BRIGHTNESS_CONSTRAINT_TYPE_DEFAULT);
        mCurrentUserId = UserHandle.USER_SYSTEM;
        mCurrentUserId = UserHandle.USER_SYSTEM;
        ColorSpace[] colorSpaces = SurfaceControl.getCompositionColorSpaces();
        ColorSpace[] colorSpaces = SurfaceControl.getCompositionColorSpaces();
@@ -588,7 +600,7 @@ public final class DisplayManagerService extends SystemService {
        }
        }
    }
    }


    private void requestGlobalDisplayStateInternal(int state, float brightnessState) {
    private void requestDisplayStateInternal(int displayId, int state, float brightnessState) {
        if (state == Display.STATE_UNKNOWN) {
        if (state == Display.STATE_UNKNOWN) {
            state = Display.STATE_ON;
            state = Display.STATE_ON;
        }
        }
@@ -601,38 +613,40 @@ public final class DisplayManagerService extends SystemService {
            brightnessState = PowerManager.BRIGHTNESS_MAX;
            brightnessState = PowerManager.BRIGHTNESS_MAX;
        }
        }


        synchronized (mTempDisplayStateWorkQueue) {
            try {
        // Update the display state within the lock.
        // Update the display state within the lock.
        // Note that we do not need to schedule traversals here although it
        // Note that we do not need to schedule traversals here although it
        // may happen as a side-effect of displays changing state.
        // may happen as a side-effect of displays changing state.
        final Runnable runnable;
        final String traceMessage;
        synchronized (mSyncRoot) {
        synchronized (mSyncRoot) {
                    if (mGlobalDisplayState == state
            final int index = mDisplayStates.indexOfKey(displayId);
                            && mGlobalDisplayBrightness == brightnessState) {

                        return; // no change
            if (index < 0 || (mDisplayStates.valueAt(index) == state
                    && BrightnessSynchronizer.floatEquals(mDisplayBrightnesses.valueAt(index),
                    brightnessState))) {
                return; // Display no longer exists or no change.
            }
            }


                    Trace.traceBegin(Trace.TRACE_TAG_POWER, "requestGlobalDisplayState("
            traceMessage = "requestDisplayStateInternal("
                    + displayId + ", "
                    + Display.stateToString(state)
                    + Display.stateToString(state)
                            + ", brightness=" + brightnessState + ")");
                    + ", brightness=" + brightnessState + ")";
            Trace.asyncTraceBegin(Trace.TRACE_TAG_POWER, traceMessage, displayId);


                    mGlobalDisplayState = state;
            mDisplayStates.setValueAt(index, state);
                    mGlobalDisplayBrightness = brightnessState;
            mDisplayBrightnesses.setValueAt(index, brightnessState);
                    applyGlobalDisplayStateLocked(mTempDisplayStateWorkQueue);
            runnable = updateDisplayStateLocked(
                    mLogicalDisplayMapper.getLocked(displayId).getPrimaryDisplayDeviceLocked());
        }
        }


        // Setting the display power state can take hundreds of milliseconds
        // Setting the display power state can take hundreds of milliseconds
        // to complete so we defer the most expensive part of the work until
        // to complete so we defer the most expensive part of the work until
        // after we have exited the critical section to avoid blocking other
        // after we have exited the critical section to avoid blocking other
        // threads for a long time.
        // threads for a long time.
                for (int i = 0; i < mTempDisplayStateWorkQueue.size(); i++) {
        if (runnable != null) {
                    mTempDisplayStateWorkQueue.get(i).run();
            runnable.run();
                }
                Trace.traceEnd(Trace.TRACE_TAG_POWER);
            } finally {
                mTempDisplayStateWorkQueue.clear();
            }
        }
        }
        Trace.asyncTraceEnd(Trace.TRACE_TAG_POWER, traceMessage, displayId);
    }
    }


    private class SettingsObserver extends ContentObserver {
    private class SettingsObserver extends ContentObserver {
@@ -986,6 +1000,8 @@ public final class DisplayManagerService extends SystemService {
            recordTopInsetLocked(display);
            recordTopInsetLocked(display);
        }
        }
        addDisplayPowerControllerLocked(displayId);
        addDisplayPowerControllerLocked(displayId);
        mDisplayStates.append(displayId, Display.STATE_OFF);
        mDisplayBrightnesses.append(displayId, mDisplayDefaultBrightness);


        DisplayManagerGlobal.invalidateLocalDisplayInfoCaches();
        DisplayManagerGlobal.invalidateLocalDisplayInfoCaches();


@@ -1020,6 +1036,8 @@ public final class DisplayManagerService extends SystemService {
    private void handleLogicalDisplayRemovedLocked(@NonNull LogicalDisplay display) {
    private void handleLogicalDisplayRemovedLocked(@NonNull LogicalDisplay display) {
        final int displayId = display.getDisplayIdLocked();
        final int displayId = display.getDisplayIdLocked();
        mDisplayPowerControllers.delete(displayId);
        mDisplayPowerControllers.delete(displayId);
        mDisplayStates.delete(displayId);
        mDisplayBrightnesses.delete(displayId);
        DisplayManagerGlobal.invalidateLocalDisplayInfoCaches();
        DisplayManagerGlobal.invalidateLocalDisplayInfoCaches();
        sendDisplayEventLocked(displayId, DisplayManagerGlobal.EVENT_DISPLAY_REMOVED);
        sendDisplayEventLocked(displayId, DisplayManagerGlobal.EVENT_DISPLAY_REMOVED);
        scheduleTraversalLocked(false);
        scheduleTraversalLocked(false);
@@ -1034,15 +1052,6 @@ public final class DisplayManagerService extends SystemService {
        handleLogicalDisplayChangedLocked(display);
        handleLogicalDisplayChangedLocked(display);
    }
    }


    private void applyGlobalDisplayStateLocked(List<Runnable> workQueue) {
        mDisplayDeviceRepo.forEachLocked((DisplayDevice device) -> {
            Runnable runnable = updateDisplayStateLocked(device);
            if (runnable != null) {
                workQueue.add(runnable);
            }
        });
    }

    private Runnable updateDisplayStateLocked(DisplayDevice device) {
    private Runnable updateDisplayStateLocked(DisplayDevice device) {
        // Blank or unblank the display immediately to match the state requested
        // Blank or unblank the display immediately to match the state requested
        // by the display power controller (if known).
        // by the display power controller (if known).
@@ -1051,12 +1060,16 @@ public final class DisplayManagerService extends SystemService {
            // TODO - b/170498827 The rules regarding what display state to apply to each
            // TODO - b/170498827 The rules regarding what display state to apply to each
            // display will depend on the configuration/mapping of logical displays.
            // display will depend on the configuration/mapping of logical displays.
            // Clean up LogicalDisplay.isEnabled() mechanism once this is fixed.
            // Clean up LogicalDisplay.isEnabled() mechanism once this is fixed.
            int state = mGlobalDisplayState;
            final LogicalDisplay display = mLogicalDisplayMapper.getLocked(device);
            final LogicalDisplay display = mLogicalDisplayMapper.getLocked(device);
            if (display != null && !display.isEnabled()) {
            final int state;
            final int displayId = display.getDisplayIdLocked();
            if (display.isEnabled()) {
                state = mDisplayStates.get(displayId);
            } else {
                state = Display.STATE_OFF;
                state = Display.STATE_OFF;
            }
            }
            return device.requestDisplayStateLocked(state, mGlobalDisplayBrightness);
            final float brightness = mDisplayBrightnesses.get(displayId);
            return device.requestDisplayStateLocked(state, brightness);
        }
        }
        return null;
        return null;
    }
    }
@@ -1591,13 +1604,24 @@ public final class DisplayManagerService extends SystemService {
            pw.println("  mOnlyCode=" + mOnlyCore);
            pw.println("  mOnlyCode=" + mOnlyCore);
            pw.println("  mSafeMode=" + mSafeMode);
            pw.println("  mSafeMode=" + mSafeMode);
            pw.println("  mPendingTraversal=" + mPendingTraversal);
            pw.println("  mPendingTraversal=" + mPendingTraversal);
            pw.println("  mGlobalDisplayState=" + Display.stateToString(mGlobalDisplayState));
            pw.println("  mViewports=" + mViewports);
            pw.println("  mViewports=" + mViewports);
            pw.println("  mDefaultDisplayDefaultColorMode=" + mDefaultDisplayDefaultColorMode);
            pw.println("  mDefaultDisplayDefaultColorMode=" + mDefaultDisplayDefaultColorMode);
            pw.println("  mWifiDisplayScanRequestCount=" + mWifiDisplayScanRequestCount);
            pw.println("  mWifiDisplayScanRequestCount=" + mWifiDisplayScanRequestCount);
            pw.println("  mStableDisplaySize=" + mStableDisplaySize);
            pw.println("  mStableDisplaySize=" + mStableDisplaySize);
            pw.println("  mMinimumBrightnessCurve=" + mMinimumBrightnessCurve);
            pw.println("  mMinimumBrightnessCurve=" + mMinimumBrightnessCurve);


            pw.println();
            final int displayStateCount = mDisplayStates.size();
            pw.println("Display States: size=" + displayStateCount);
            for (int i = 0; i < displayStateCount; i++) {
                final int displayId = mDisplayStates.keyAt(i);
                final int displayState = mDisplayStates.valueAt(i);
                final float brightness = mDisplayBrightnesses.valueAt(i);
                pw.println("  Display Id=" + displayId);
                pw.println("  Display State=" + Display.stateToString(displayState));
                pw.println("  Display Brightness=" + brightness);
            }

            IndentingPrintWriter ipw = new IndentingPrintWriter(pw, "    ");
            IndentingPrintWriter ipw = new IndentingPrintWriter(pw, "    ");
            ipw.increaseIndent();
            ipw.increaseIndent();


+0 −2
Original line number Original line Diff line number Diff line
@@ -680,8 +680,6 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
    }
    }


    private void initialize() {
    private void initialize() {
        // Initialize the power state object for the default display.
        // In the future, we might manage multiple displays independently.
        mPowerState = new DisplayPowerState(mBlanker,
        mPowerState = new DisplayPowerState(mBlanker,
                mColorFadeEnabled ? new ColorFade(mDisplayId) : null, mDisplayId);
                mColorFadeEnabled ? new ColorFade(mDisplayId) : null, mDisplayId);


+1 −1
Original line number Original line Diff line number Diff line
@@ -585,7 +585,7 @@ final class LogicalDisplay {
    }
    }


    /**
    /**
     * Swap the underlying {@link DisplayDevice} with the specificed LogicalDisplay.
     * Swap the underlying {@link DisplayDevice} with the specified LogicalDisplay.
     *
     *
     * @param targetDisplay The display with which to swap display-devices.
     * @param targetDisplay The display with which to swap display-devices.
     * @return {@code true} if the displays were swapped, {@code false} otherwise.
     * @return {@code true} if the displays were swapped, {@code false} otherwise.
+5 −0
Original line number Original line Diff line number Diff line
@@ -17,6 +17,7 @@
package com.android.server.display;
package com.android.server.display;


import android.content.Context;
import android.content.Context;
import android.os.Process;
import android.os.SystemProperties;
import android.os.SystemProperties;
import android.text.TextUtils;
import android.text.TextUtils;
import android.util.Slog;
import android.util.Slog;
@@ -143,6 +144,10 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener {
        return null;
        return null;
    }
    }


    public int[] getDisplayIdsLocked() {
        return getDisplayIdsLocked(Process.SYSTEM_UID);
    }

    public int[] getDisplayIdsLocked(int callingUid) {
    public int[] getDisplayIdsLocked(int callingUid) {
        final int count = mLogicalDisplays.size();
        final int count = mLogicalDisplays.size();
        int[] displayIds = new int[count];
        int[] displayIds = new int[count];