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

Commit c64dd580 authored by Sean Stout's avatar Sean Stout Committed by Android (Google) Code Review
Browse files

Merge "Implement Phase 4 of per-display power states"

parents c234812e 8346e407
Loading
Loading
Loading
Loading
+81 −57
Original line number Diff line number Diff line
@@ -89,6 +89,7 @@ import android.util.IntArray;
import android.util.Pair;
import android.util.Slog;
import android.util.SparseArray;
import android.util.SparseIntArray;
import android.util.Spline;
import android.view.Display;
import android.view.DisplayInfo;
@@ -96,6 +97,7 @@ import android.view.IDisplayFoldListener;
import android.view.Surface;
import android.view.SurfaceControl;

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

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

            mDisplayPowerCallbacks.onDisplayStateChange(state);

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

    // The overall display state, independent of changes that might influence one
    // display or another in particular.
    private int mGlobalDisplayState = Display.STATE_ON;
    // A map from LogicalDisplay ID to display power state.
    @GuardedBy("mSyncRoot")
    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.
    // For now, this only applies to the default display but we may split it up eventually.
    private float mGlobalDisplayBrightness;
    // The default brightness.
    private final float mDisplayDefaultBrightness;

    // Set to true when there are pending display changes that have yet to be applied
    // to the surface flinger state.
@@ -317,11 +334,6 @@ public final class DisplayManagerService extends SystemService {
    // DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY flag set.
    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.
    private final SparseArray<IntArray> mDisplayAccessUIDs = new SparseArray<>();

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

        PowerManager pm = mContext.getSystemService(PowerManager.class);
        mGlobalDisplayBrightness = pm.getBrightnessConstraint(
        mDisplayDefaultBrightness = pm.getBrightnessConstraint(
                PowerManager.BRIGHTNESS_CONSTRAINT_TYPE_DEFAULT);
        mCurrentUserId = UserHandle.USER_SYSTEM;
        ColorSpace[] colorSpaces = SurfaceControl.getCompositionColorSpaces();
@@ -589,7 +601,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) {
            state = Display.STATE_ON;
        }
@@ -602,38 +614,40 @@ public final class DisplayManagerService extends SystemService {
            brightnessState = PowerManager.BRIGHTNESS_MAX;
        }

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

            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)
                            + ", brightness=" + brightnessState + ")");
                    + ", brightness=" + brightnessState + ")";
            Trace.asyncTraceBegin(Trace.TRACE_TAG_POWER, traceMessage, displayId);

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

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

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

        DisplayManagerGlobal.invalidateLocalDisplayInfoCaches();

@@ -1021,6 +1037,8 @@ public final class DisplayManagerService extends SystemService {
    private void handleLogicalDisplayRemovedLocked(@NonNull LogicalDisplay display) {
        final int displayId = display.getDisplayIdLocked();
        mDisplayPowerControllers.delete(displayId);
        mDisplayStates.delete(displayId);
        mDisplayBrightnesses.delete(displayId);
        DisplayManagerGlobal.invalidateLocalDisplayInfoCaches();
        sendDisplayEventLocked(displayId, DisplayManagerGlobal.EVENT_DISPLAY_REMOVED);
        scheduleTraversalLocked(false);
@@ -1035,15 +1053,6 @@ public final class DisplayManagerService extends SystemService {
        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) {
        // Blank or unblank the display immediately to match the state requested
        // by the display power controller (if known).
@@ -1052,12 +1061,16 @@ public final class DisplayManagerService extends SystemService {
            // TODO - b/170498827 The rules regarding what display state to apply to each
            // display will depend on the configuration/mapping of logical displays.
            // Clean up LogicalDisplay.isEnabled() mechanism once this is fixed.
            int state = mGlobalDisplayState;
            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;
            }
            return device.requestDisplayStateLocked(state, mGlobalDisplayBrightness);
            final float brightness = mDisplayBrightnesses.get(displayId);
            return device.requestDisplayStateLocked(state, brightness);
        }
        return null;
    }
@@ -1587,13 +1600,24 @@ public final class DisplayManagerService extends SystemService {
            pw.println("  mOnlyCode=" + mOnlyCore);
            pw.println("  mSafeMode=" + mSafeMode);
            pw.println("  mPendingTraversal=" + mPendingTraversal);
            pw.println("  mGlobalDisplayState=" + Display.stateToString(mGlobalDisplayState));
            pw.println("  mViewports=" + mViewports);
            pw.println("  mDefaultDisplayDefaultColorMode=" + mDefaultDisplayDefaultColorMode);
            pw.println("  mWifiDisplayScanRequestCount=" + mWifiDisplayScanRequestCount);
            pw.println("  mStableDisplaySize=" + mStableDisplaySize);
            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, "    ");
            ipw.increaseIndent();

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

    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,
                mColorFadeEnabled ? new ColorFade(mDisplayId) : null, mDisplayId);

+1 −1
Original line number Diff line number Diff line
@@ -588,7 +588,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.
     * @return {@code true} if the displays were swapped, {@code false} otherwise.
+5 −0
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
package com.android.server.display;

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

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

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