diff options
6 files changed, 212 insertions, 33 deletions
diff --git a/core/java/android/hardware/display/DisplayManagerInternal.java b/core/java/android/hardware/display/DisplayManagerInternal.java index defcab7c3035..5a03adee4eab 100644 --- a/core/java/android/hardware/display/DisplayManagerInternal.java +++ b/core/java/android/hardware/display/DisplayManagerInternal.java @@ -65,6 +65,12 @@ public abstract class DisplayManagerInternal { public abstract boolean isProximitySensorAvailable(); /** + * Returns the id of the {@link com.android.server.display.DisplayGroup} to which the provided + * display belongs. + */ + public abstract int getDisplayGroupId(int displayId); + + /** * Screenshot for internal system-only use such as rotation, etc. This method includes * secure layers and the result should never be exposed to non-system applications. * This method does not apply any rotation and provides the output in natural orientation. diff --git a/services/core/java/com/android/server/display/DisplayGroup.java b/services/core/java/com/android/server/display/DisplayGroup.java index f2413edd1a3a..2ba875813734 100644 --- a/services/core/java/com/android/server/display/DisplayGroup.java +++ b/services/core/java/com/android/server/display/DisplayGroup.java @@ -22,10 +22,22 @@ import java.util.List; /** * Represents a collection of {@link LogicalDisplay}s which act in unison for certain behaviors and * operations. + * @hide */ public class DisplayGroup { - final List<LogicalDisplay> mDisplays = new ArrayList<>(); + public static final int DEFAULT = 0; + + private final List<LogicalDisplay> mDisplays = new ArrayList<>(); + private final int mGroupId; + + DisplayGroup(int groupId) { + mGroupId = groupId; + } + + int getGroupId() { + return mGroupId; + } void addDisplay(LogicalDisplay display) { if (!mDisplays.contains(display)) { diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java index 004e481354ec..4e60f1ff929e 100644 --- a/services/core/java/com/android/server/display/DisplayManagerService.java +++ b/services/core/java/com/android/server/display/DisplayManagerService.java @@ -2536,6 +2536,13 @@ public final class DisplayManagerService extends SystemService { } @Override + public int getDisplayGroupId(int displayId) { + synchronized (mSyncRoot) { + return mLogicalDisplayMapper.getDisplayGroupIdLocked(displayId); + } + } + + @Override public SurfaceControl.ScreenshotHardwareBuffer systemScreenshot(int displayId) { return systemScreenshotInternal(displayId); } diff --git a/services/core/java/com/android/server/display/LogicalDisplayMapper.java b/services/core/java/com/android/server/display/LogicalDisplayMapper.java index 45c38b456b0a..6b741709321c 100644 --- a/services/core/java/com/android/server/display/LogicalDisplayMapper.java +++ b/services/core/java/com/android/server/display/LogicalDisplayMapper.java @@ -94,6 +94,7 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener { private final SparseArray<LogicalDisplay> mLogicalDisplays = new SparseArray<LogicalDisplay>(); private int mNextNonDefaultDisplayId = Display.DEFAULT_DISPLAY + 1; + private int mNextNonDefaultGroupId = DisplayGroup.DEFAULT + 1; /** A mapping from logical display id to display group. */ private final SparseArray<DisplayGroup> mDisplayGroups = new SparseArray<>(); @@ -178,6 +179,15 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener { } } + public int getDisplayGroupIdLocked(int displayId) { + final DisplayGroup displayGroup = mDisplayGroups.get(displayId); + if (displayGroup != null) { + return displayGroup.getGroupId(); + } + + return -1; + } + public void dumpLocked(PrintWriter pw) { pw.println("LogicalDisplayMapper:"); IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " "); @@ -309,7 +319,8 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener { final DisplayGroup displayGroup; if (isDefault || (deviceInfo.flags & DisplayDeviceInfo.FLAG_OWN_DISPLAY_GROUP) != 0) { - displayGroup = new DisplayGroup(); + final int groupId = assignDisplayGroupIdLocked(isDefault); + displayGroup = new DisplayGroup(groupId); } else { displayGroup = mDisplayGroups.get(Display.DEFAULT_DISPLAY); } @@ -345,7 +356,8 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener { if ((flags & Display.FLAG_OWN_DISPLAY_GROUP) != 0) { // The display should have its own DisplayGroup. if (defaultDisplayGroup.removeDisplay(display)) { - final DisplayGroup displayGroup = new DisplayGroup(); + final int groupId = assignDisplayGroupIdLocked(false); + final DisplayGroup displayGroup = new DisplayGroup(groupId); displayGroup.addDisplay(display); mDisplayGroups.append(display.getDisplayIdLocked(), displayGroup); } @@ -381,6 +393,10 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener { return isDefault ? Display.DEFAULT_DISPLAY : mNextNonDefaultDisplayId++; } + private int assignDisplayGroupIdLocked(boolean isDefault) { + return isDefault ? DisplayGroup.DEFAULT : mNextNonDefaultGroupId++; + } + private int assignLayerStackLocked(int displayId) { // Currently layer stacks and display ids are the same. // This need not be the case. diff --git a/services/core/java/com/android/server/power/DisplayPowerRequestMapper.java b/services/core/java/com/android/server/power/DisplayPowerRequestMapper.java new file mode 100644 index 000000000000..6477552eb550 --- /dev/null +++ b/services/core/java/com/android/server/power/DisplayPowerRequestMapper.java @@ -0,0 +1,122 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.power; + +import android.hardware.display.DisplayManager; +import android.hardware.display.DisplayManagerInternal; +import android.hardware.display.DisplayManagerInternal.DisplayPowerRequest; +import android.os.Handler; +import android.util.SparseArray; +import android.util.SparseIntArray; +import android.view.Display; + +import com.android.internal.annotations.GuardedBy; +import com.android.server.display.DisplayGroup; + +/** + * Responsible for creating {@link DisplayPowerRequest}s and associating them with + * {@link com.android.server.display.DisplayGroup}s. + * + * Each {@link com.android.server.display.DisplayGroup} has a single {@link DisplayPowerRequest} + * which is used to request power state changes to every display in the group. + */ +class DisplayPowerRequestMapper { + + private final Object mLock = new Object(); + + /** A mapping from LogicalDisplay Id to DisplayGroup Id. */ + @GuardedBy("mLock") + private final SparseIntArray mDisplayGroupIds = new SparseIntArray(); + + /** A mapping from DisplayGroup Id to DisplayPowerRequest. */ + @GuardedBy("mLock") + private final SparseArray<DisplayPowerRequest> mDisplayPowerRequests = new SparseArray<>(); + + private final DisplayManagerInternal mDisplayManagerInternal; + + private final DisplayManager.DisplayListener mDisplayListener = + new DisplayManager.DisplayListener() { + + @Override + public void onDisplayAdded(int displayId) { + synchronized (mLock) { + if (mDisplayGroupIds.indexOfKey(displayId) >= 0) { + return; + } + final int displayGroupId = mDisplayManagerInternal.getDisplayGroupId( + displayId); + if (!mDisplayPowerRequests.contains(displayGroupId)) { + // A new DisplayGroup was created; create a new DisplayPowerRequest. + mDisplayPowerRequests.append(displayGroupId, new DisplayPowerRequest()); + } + mDisplayGroupIds.append(displayId, displayGroupId); + } + } + + @Override + public void onDisplayRemoved(int displayId) { + synchronized (mLock) { + final int index = mDisplayGroupIds.indexOfKey(displayId); + if (index < 0) { + return; + } + final int displayGroupId = mDisplayGroupIds.valueAt(index); + mDisplayGroupIds.removeAt(index); + + if (mDisplayGroupIds.indexOfValue(displayGroupId) < 0) { + // The DisplayGroup no longer exists; delete the DisplayPowerRequest. + mDisplayPowerRequests.delete(displayGroupId); + } + } + } + + @Override + public void onDisplayChanged(int displayId) { + synchronized (mLock) { + final int newDisplayGroupId = mDisplayManagerInternal.getDisplayGroupId( + displayId); + final int oldDisplayGroupId = mDisplayGroupIds.get(displayId); + + if (!mDisplayPowerRequests.contains(newDisplayGroupId)) { + // A new DisplayGroup was created; create a new DisplayPowerRequest. + mDisplayPowerRequests.append(newDisplayGroupId, + new DisplayPowerRequest()); + } + mDisplayGroupIds.put(displayId, newDisplayGroupId); + + if (mDisplayGroupIds.indexOfValue(oldDisplayGroupId) < 0) { + // The DisplayGroup no longer exists; delete the DisplayPowerRequest. + mDisplayPowerRequests.delete(oldDisplayGroupId); + } + } + } + }; + + DisplayPowerRequestMapper(DisplayManager displayManager, + DisplayManagerInternal displayManagerInternal, Handler handler) { + mDisplayManagerInternal = displayManagerInternal; + displayManager.registerDisplayListener(mDisplayListener, handler); + mDisplayPowerRequests.append(DisplayGroup.DEFAULT, new DisplayPowerRequest()); + mDisplayGroupIds.append(Display.DEFAULT_DISPLAY, DisplayGroup.DEFAULT); + } + + DisplayPowerRequest get(int displayId) { + synchronized (mLock) { + return mDisplayPowerRequests.get(mDisplayGroupIds.get(displayId)); + } + } +} diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java index ccd659dcf5a4..955e1cdfeaaa 100644 --- a/services/core/java/com/android/server/power/PowerManagerService.java +++ b/services/core/java/com/android/server/power/PowerManagerService.java @@ -42,6 +42,7 @@ import android.database.ContentObserver; import android.hardware.SensorManager; import android.hardware.SystemSensorManager; import android.hardware.display.AmbientDisplayConfiguration; +import android.hardware.display.DisplayManager; import android.hardware.display.DisplayManagerInternal; import android.hardware.display.DisplayManagerInternal.DisplayPowerRequest; import android.hardware.power.Boost; @@ -348,9 +349,9 @@ public final class PowerManagerService extends SystemService // A bitfield that summarizes the effect of the user activity timer. private int mUserActivitySummary; - // The desired display power state. The actual state may lag behind the + // Manages the desired power state of displays. The actual state may lag behind the // requested because it is updated asynchronously by the display power controller. - private final DisplayPowerRequest mDisplayPowerRequest = new DisplayPowerRequest(); + private DisplayPowerRequestMapper mDisplayPowerRequestMapper; // True if the display power state has been fully applied, which means the display // is actually on or actually off or whatever was requested. @@ -1054,6 +1055,8 @@ public final class PowerManagerService extends SystemService mPolicy = getLocalService(WindowManagerPolicy.class); mBatteryManagerInternal = getLocalService(BatteryManagerInternal.class); mAttentionDetector.systemReady(mContext); + mDisplayPowerRequestMapper = new DisplayPowerRequestMapper(mContext.getSystemService( + DisplayManager.class), mDisplayManagerInternal, mHandler); SensorManager sensorManager = new SystemSensorManager(mContext, mHandler.getLooper()); @@ -2296,10 +2299,12 @@ public final class PowerManagerService extends SystemService && mLastUserActivityTimeNoChangeLights >= mLastWakeTime) { nextTimeout = mLastUserActivityTimeNoChangeLights + screenOffTimeout; if (now < nextTimeout) { - if (mDisplayPowerRequest.policy == DisplayPowerRequest.POLICY_BRIGHT - || mDisplayPowerRequest.policy == DisplayPowerRequest.POLICY_VR) { + final DisplayPowerRequest displayPowerRequest = + mDisplayPowerRequestMapper.get(Display.DEFAULT_DISPLAY); + if (displayPowerRequest.policy == DisplayPowerRequest.POLICY_BRIGHT + || displayPowerRequest.policy == DisplayPowerRequest.POLICY_VR) { mUserActivitySummary = USER_ACTIVITY_SCREEN_BRIGHT; - } else if (mDisplayPowerRequest.policy == DisplayPowerRequest.POLICY_DIM) { + } else if (displayPowerRequest.policy == DisplayPowerRequest.POLICY_DIM) { mUserActivitySummary = USER_ACTIVITY_SCREEN_DIM; } } @@ -2771,11 +2776,13 @@ public final class PowerManagerService extends SystemService * Returns true if the device is allowed to dream in its current state. */ private boolean canDreamLocked() { + final DisplayPowerRequest displayPowerRequest = + mDisplayPowerRequestMapper.get(Display.DEFAULT_DISPLAY); if (getWakefulnessLocked() != WAKEFULNESS_DREAMING || !mDreamsSupportedConfig || !mDreamsEnabledSetting - || !mDisplayPowerRequest.isBrightOrDim() - || mDisplayPowerRequest.isVr() + || !displayPowerRequest.isBrightOrDim() + || displayPowerRequest.isVr() || (mUserActivitySummary & (USER_ACTIVITY_SCREEN_BRIGHT | USER_ACTIVITY_SCREEN_DIM | USER_ACTIVITY_SCREEN_DREAM)) == 0 || !mBootCompleted) { @@ -2826,7 +2833,9 @@ public final class PowerManagerService extends SystemService sQuiescent = false; } - mDisplayPowerRequest.policy = getDesiredScreenPolicyLocked(); + final DisplayPowerRequest displayPowerRequest = mDisplayPowerRequestMapper.get( + Display.DEFAULT_DISPLAY); + displayPowerRequest.policy = getDesiredScreenPolicyLocked(); // Determine appropriate screen brightness and auto-brightness adjustments. final boolean autoBrightness; @@ -2846,39 +2855,39 @@ public final class PowerManagerService extends SystemService } // Update display power request. - mDisplayPowerRequest.screenBrightnessOverride = screenBrightnessOverride; - mDisplayPowerRequest.useAutoBrightness = autoBrightness; - mDisplayPowerRequest.useProximitySensor = shouldUseProximitySensorLocked(); - mDisplayPowerRequest.boostScreenBrightness = shouldBoostScreenBrightness(); + displayPowerRequest.screenBrightnessOverride = screenBrightnessOverride; + displayPowerRequest.useAutoBrightness = autoBrightness; + displayPowerRequest.useProximitySensor = shouldUseProximitySensorLocked(); + displayPowerRequest.boostScreenBrightness = shouldBoostScreenBrightness(); - updatePowerRequestFromBatterySaverPolicy(mDisplayPowerRequest); + updatePowerRequestFromBatterySaverPolicy(displayPowerRequest); - if (mDisplayPowerRequest.policy == DisplayPowerRequest.POLICY_DOZE) { - mDisplayPowerRequest.dozeScreenState = mDozeScreenStateOverrideFromDreamManager; + if (displayPowerRequest.policy == DisplayPowerRequest.POLICY_DOZE) { + displayPowerRequest.dozeScreenState = mDozeScreenStateOverrideFromDreamManager; if ((mWakeLockSummary & WAKE_LOCK_DRAW) != 0 && !mDrawWakeLockOverrideFromSidekick) { - if (mDisplayPowerRequest.dozeScreenState == Display.STATE_DOZE_SUSPEND) { - mDisplayPowerRequest.dozeScreenState = Display.STATE_DOZE; + if (displayPowerRequest.dozeScreenState == Display.STATE_DOZE_SUSPEND) { + displayPowerRequest.dozeScreenState = Display.STATE_DOZE; } - if (mDisplayPowerRequest.dozeScreenState == Display.STATE_ON_SUSPEND) { - mDisplayPowerRequest.dozeScreenState = Display.STATE_ON; + if (displayPowerRequest.dozeScreenState == Display.STATE_ON_SUSPEND) { + displayPowerRequest.dozeScreenState = Display.STATE_ON; } } - mDisplayPowerRequest.dozeScreenBrightness = + displayPowerRequest.dozeScreenBrightness = mDozeScreenBrightnessOverrideFromDreamManagerFloat; } else { - mDisplayPowerRequest.dozeScreenState = Display.STATE_UNKNOWN; - mDisplayPowerRequest.dozeScreenBrightness = + displayPowerRequest.dozeScreenState = Display.STATE_UNKNOWN; + displayPowerRequest.dozeScreenBrightness = PowerManager.BRIGHTNESS_INVALID_FLOAT; } - mDisplayReady = mDisplayManagerInternal.requestPowerState(mDisplayPowerRequest, + mDisplayReady = mDisplayManagerInternal.requestPowerState(displayPowerRequest, mRequestWaitForNegativeProximity); mRequestWaitForNegativeProximity = false; if (DEBUG_SPEW) { Slog.d(TAG, "updateDisplayPowerStateLocked: mDisplayReady=" + mDisplayReady - + ", policy=" + mDisplayPowerRequest.policy + + ", policy=" + displayPowerRequest.policy + ", mWakefulness=" + getWakefulnessLocked() + ", mWakeLockSummary=0x" + Integer.toHexString(mWakeLockSummary) + ", mUserActivitySummary=0x" + Integer.toHexString(mUserActivitySummary) @@ -3049,7 +3058,9 @@ public final class PowerManagerService extends SystemService final boolean needWakeLockSuspendBlocker = ((mWakeLockSummary & WAKE_LOCK_CPU) != 0); final boolean needDisplaySuspendBlocker = needDisplaySuspendBlockerLocked(); final boolean autoSuspend = !needDisplaySuspendBlocker; - final boolean interactive = mDisplayPowerRequest.isBrightOrDim(); + final DisplayPowerRequest displayPowerRequest = mDisplayPowerRequestMapper.get( + Display.DEFAULT_DISPLAY); + final boolean interactive = displayPowerRequest.isBrightOrDim(); // Disable auto-suspend if needed. // FIXME We should consider just leaving auto-suspend enabled forever since @@ -3108,19 +3119,21 @@ public final class PowerManagerService extends SystemService if (!mDisplayReady) { return true; } - if (mDisplayPowerRequest.isBrightOrDim()) { + final DisplayPowerRequest displayPowerRequest = mDisplayPowerRequestMapper.get( + Display.DEFAULT_DISPLAY); + if (displayPowerRequest.isBrightOrDim()) { // If we asked for the screen to be on but it is off due to the proximity // sensor then we may suspend but only if the configuration allows it. // On some hardware it may not be safe to suspend because the proximity // sensor may not be correctly configured as a wake-up source. - if (!mDisplayPowerRequest.useProximitySensor || !mProximityPositive + if (!displayPowerRequest.useProximitySensor || !mProximityPositive || !mSuspendWhenScreenOffDueToProximityConfig) { return true; } } - if (mDisplayPowerRequest.policy == DisplayPowerRequest.POLICY_DOZE - && mDisplayPowerRequest.dozeScreenState == Display.STATE_ON) { + if (displayPowerRequest.policy == DisplayPowerRequest.POLICY_DOZE + && displayPowerRequest.dozeScreenState == Display.STATE_ON) { // Although we are in DOZE and would normally allow the device to suspend, // the doze service has explicitly requested the display to remain in the ON // state which means we should hold the display suspend blocker. @@ -5575,7 +5588,10 @@ public final class PowerManagerService extends SystemService // DisplayPowerController only reports proximity positive (near) if it's // positive and the proximity wasn't already being ignored. So it reliably // also tells us that we're not already ignoring the proximity sensor. - if (mDisplayPowerRequest.useProximitySensor && mProximityPositive) { + + final DisplayPowerRequest displayPowerRequest = + mDisplayPowerRequestMapper.get(Display.DEFAULT_DISPLAY); + if (displayPowerRequest.useProximitySensor && mProximityPositive) { mDisplayManagerInternal.ignoreProximitySensorUntilChanged(); return true; } |
