Merge "Implement Phase 4 of per-display power states"
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index 3ac2185..004e481 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -89,6 +89,7 @@
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.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 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 @@
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 @@
/** 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();
- // The overall display brightness.
- // For now, this only applies to the default display but we may split it up eventually.
- private float mGlobalDisplayBrightness;
+ // A map from LogicalDisplay ID to display brightness.
+ @GuardedBy("mSyncRoot")
+ private final SparseArray<Float> mDisplayBrightnesses = new SparseArray<>();
+
+ // 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 @@
// 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 @@
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 @@
}
}
- 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 @@
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.
- synchronized (mSyncRoot) {
- if (mGlobalDisplayState == state
- && mGlobalDisplayBrightness == brightnessState) {
- return; // no change
- }
+ // 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) {
+ final int index = mDisplayStates.indexOfKey(displayId);
- Trace.traceBegin(Trace.TRACE_TAG_POWER, "requestGlobalDisplayState("
- + Display.stateToString(state)
- + ", brightness=" + brightnessState + ")");
-
- mGlobalDisplayState = state;
- mGlobalDisplayBrightness = brightnessState;
- applyGlobalDisplayStateLocked(mTempDisplayStateWorkQueue);
- }
-
- // 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 (index < 0 || (mDisplayStates.valueAt(index) == state
+ && BrightnessSynchronizer.floatEquals(mDisplayBrightnesses.valueAt(index),
+ brightnessState))) {
+ return; // Display no longer exists or no change.
}
+
+ traceMessage = "requestDisplayStateInternal("
+ + displayId + ", "
+ + Display.stateToString(state)
+ + ", brightness=" + brightnessState + ")";
+ Trace.asyncTraceBegin(Trace.TRACE_TAG_POWER, traceMessage, displayId);
+
+ 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.
+ if (runnable != null) {
+ runnable.run();
+ }
+ Trace.asyncTraceEnd(Trace.TRACE_TAG_POWER, traceMessage, displayId);
}
private class SettingsObserver extends ContentObserver {
@@ -987,6 +1001,8 @@
recordTopInsetLocked(display);
}
addDisplayPowerControllerLocked(displayId);
+ mDisplayStates.append(displayId, Display.STATE_OFF);
+ mDisplayBrightnesses.append(displayId, mDisplayDefaultBrightness);
DisplayManagerGlobal.invalidateLocalDisplayInfoCaches();
@@ -1021,6 +1037,8 @@
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 @@
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 @@
// 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 @@
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();
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index 09c9aab..f488260 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -685,8 +685,6 @@
}
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);
diff --git a/services/core/java/com/android/server/display/LogicalDisplay.java b/services/core/java/com/android/server/display/LogicalDisplay.java
index e35becc..979c3b8 100644
--- a/services/core/java/com/android/server/display/LogicalDisplay.java
+++ b/services/core/java/com/android/server/display/LogicalDisplay.java
@@ -588,7 +588,7 @@
}
/**
- * 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.
diff --git a/services/core/java/com/android/server/display/LogicalDisplayMapper.java b/services/core/java/com/android/server/display/LogicalDisplayMapper.java
index a843af5..45c38b4 100644
--- a/services/core/java/com/android/server/display/LogicalDisplayMapper.java
+++ b/services/core/java/com/android/server/display/LogicalDisplayMapper.java
@@ -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 @@
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];