Loading core/res/res/values/config.xml +6 −0 Original line number Diff line number Diff line Loading @@ -657,6 +657,12 @@ <!-- Indicate the display area rect for foldable devices in folded state. --> <string name="config_foldedArea"></string> <!-- Indicates that the device supports having more than one internal display on at the same time. Only applicable to devices with more than one internal display. If this option is set to false, DisplayManager will make additional effort to ensure no more than 1 internal display is powered on at the same time. --> <bool name="config_supportsConcurrentInternalDisplays">true</bool> <!-- Desk dock behavior --> <!-- The number of degrees to rotate the display when the device is in a desk dock. Loading core/res/res/values/symbols.xml +1 −0 Original line number Diff line number Diff line Loading @@ -3800,6 +3800,7 @@ <!-- For Foldables --> <java-symbol type="array" name="config_foldedDeviceStates" /> <java-symbol type="string" name="config_foldedArea" /> <java-symbol type="bool" name="config_supportsConcurrentInternalDisplays" /> <java-symbol type="array" name="config_disableApksUnlessMatchedSku_apk_list" /> <java-symbol type="array" name="config_disableApkUnlessMatchedSku_skus_list" /> Loading services/core/java/com/android/server/display/DisplayManagerService.java +24 −6 Original line number Diff line number Diff line Loading @@ -431,8 +431,8 @@ public final class DisplayManagerService extends SystemService { mHandler = new DisplayManagerHandler(DisplayThread.get().getLooper()); mUiHandler = UiThread.getHandler(); mDisplayDeviceRepo = new DisplayDeviceRepository(mSyncRoot, mPersistentDataStore); mLogicalDisplayMapper = new LogicalDisplayMapper(mDisplayDeviceRepo, new LogicalDisplayListener()); mLogicalDisplayMapper = new LogicalDisplayMapper(mContext, mDisplayDeviceRepo, new LogicalDisplayListener(), mSyncRoot, mHandler); mDisplayModeDirector = new DisplayModeDirector(context, mHandler); mBrightnessSynchronizer = new BrightnessSynchronizer(mContext); Resources resources = mContext.getResources(); Loading Loading @@ -1268,7 +1268,7 @@ public final class DisplayManagerService extends SystemService { DisplayPowerController dpc = mDisplayPowerControllers.get(displayId); if (dpc != null) { dpc.onDisplayChangedLocked(); dpc.onDisplayChanged(); } } Loading Loading @@ -1304,12 +1304,23 @@ public final class DisplayManagerService extends SystemService { handleLogicalDisplayChangedLocked(display); } private void handleLogicalDisplayDeviceStateTransitionLocked(@NonNull LogicalDisplay display) { final int displayId = display.getDisplayIdLocked(); final DisplayPowerController dpc = mDisplayPowerControllers.get(displayId); if (dpc != null) { dpc.onDeviceStateTransition(); } } private Runnable updateDisplayStateLocked(DisplayDevice device) { // Blank or unblank the display immediately to match the state requested // by the display power controller (if known). DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked(); if ((info.flags & DisplayDeviceInfo.FLAG_NEVER_BLANK) == 0) { final LogicalDisplay display = mLogicalDisplayMapper.getDisplayLocked(device); if (display == null) { return null; } final int displayId = display.getDisplayIdLocked(); final int state = mDisplayStates.get(displayId); Loading Loading @@ -1453,9 +1464,12 @@ public final class DisplayManagerService extends SystemService { clearViewportsLocked(); // Configure each display device. mDisplayDeviceRepo.forEachLocked((DisplayDevice device) -> { mLogicalDisplayMapper.forEachLocked((LogicalDisplay display) -> { final DisplayDevice device = display.getPrimaryDisplayDeviceLocked(); if (device != null) { configureDisplayLocked(t, device); device.performTraversalLocked(t); } }); // Tell the input system about these new viewports. Loading Loading @@ -2159,6 +2173,10 @@ public final class DisplayManagerService extends SystemService { case LogicalDisplayMapper.LOGICAL_DISPLAY_EVENT_FRAME_RATE_OVERRIDES_CHANGED: handleLogicalDisplayFrameRateOverridesChangedLocked(display); break; case LogicalDisplayMapper.LOGICAL_DISPLAY_EVENT_DEVICE_STATE_TRANSITION: handleLogicalDisplayDeviceStateTransitionLocked(display); break; } } Loading services/core/java/com/android/server/display/DisplayPowerController.java +13 −3 Original line number Diff line number Diff line Loading @@ -780,15 +780,23 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call * when displays get swapped on foldable devices. For example, different brightness properties * of each display need to be properly reflected in AutomaticBrightnessController. */ public void onDisplayChangedLocked() { public void onDisplayChanged() { // TODO: b/175821789 - Support high brightness on multiple (folding) displays mUniqueDisplayId = mLogicalDisplay.getPrimaryDisplayDeviceLocked().getUniqueId(); mDisplayDeviceConfig = mLogicalDisplay.getPrimaryDisplayDeviceLocked() .getDisplayDeviceConfig(); loadAmbientLightSensor(); } /** * Called when the displays are preparing to transition from one device state to another. * This process involves turning off some displays so we need updatePowerState() to run and * calculate the new state. */ public void onDeviceStateTransition() { sendUpdatePowerState(); } /** * Unregisters all listeners and interrupts all running threads; halting future work. * Loading Loading @@ -1024,7 +1032,9 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call mIgnoreProximityUntilChanged = false; } if (!mLogicalDisplay.isEnabled() || mScreenOffBecauseOfProximity) { if (!mLogicalDisplay.isEnabled() || mLogicalDisplay.getPhase() == LogicalDisplay.DISPLAY_PHASE_LAYOUT_TRANSITION || mScreenOffBecauseOfProximity) { state = Display.STATE_OFF; } Loading services/core/java/com/android/server/display/LogicalDisplay.java +48 −13 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ package com.android.server.display; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.graphics.Point; Loading Loading @@ -65,6 +66,33 @@ import java.util.Objects; final class LogicalDisplay { private static final String TAG = "LogicalDisplay"; /** * Phase indicating the logical display's existence is hidden from the rest of the framework. * This can happen if the current layout has specifically requested to keep this display * disabled. */ static final int DISPLAY_PHASE_DISABLED = -1; /** * Phase indicating that the logical display is going through a layout transition. * When in this phase, other systems can choose to special case power-state handling of a * display that might be in a transition. */ static final int DISPLAY_PHASE_LAYOUT_TRANSITION = 0; /** * The display is exposed to the rest of the system and its power state is determined by a * power-request from PowerManager. */ static final int DISPLAY_PHASE_ENABLED = 1; @IntDef(prefix = {"DISPLAY_PHASE" }, value = { DISPLAY_PHASE_DISABLED, DISPLAY_PHASE_LAYOUT_TRANSITION, DISPLAY_PHASE_ENABLED }) @interface DisplayPhase {} // The layer stack we use when the display has been blanked to prevent any // of its content from appearing. private static final int BLANK_LAYER_STACK = -1; Loading Loading @@ -129,10 +157,12 @@ final class LogicalDisplay { private final Rect mTempDisplayRect = new Rect(); /** * Indicates that the Logical display is enabled (default). See {@link #setEnabled} for * more information. * Indicates the current phase of the display. Generally, phases supersede any * requests from PowerManager in DPC's calculation for the display state. Only when the * phase is ENABLED does PowerManager's request for the display take effect. */ private boolean mIsEnabled = true; @DisplayPhase private int mPhase = DISPLAY_PHASE_ENABLED; /** * The UID mappings for refresh rate override Loading Loading @@ -721,27 +751,32 @@ final class LogicalDisplay { return old; } public void setPhase(@DisplayPhase int phase) { mPhase = phase; } /** * Sets the LogicalDisplay to be enabled or disabled. If the display is not enabled, * the system will always set the display to power off, regardless of the global state of the * device. * TODO: b/170498827 - Remove when updateDisplayStateLocked is updated. * Returns the currently set phase for this LogicalDisplay. Phases are used when transitioning * from one device state to another. {@see LogicalDisplayMapper}. */ public void setEnabled(boolean isEnabled) { mIsEnabled = isEnabled; @DisplayPhase public int getPhase() { return mPhase; } /** * @return {@code true} iff the LogicalDisplay is enabled or {@code false} * if disabled indicating that the display has been forced to be OFF. * @return {@code true} if the LogicalDisplay is enabled or {@code false} * if disabled indicating that the display should be hidden from the rest of the apps and * framework. */ public boolean isEnabled() { return mIsEnabled; // DISPLAY_PHASE_LAYOUT_TRANSITION is still considered an 'enabled' phase. return mPhase == DISPLAY_PHASE_ENABLED || mPhase == DISPLAY_PHASE_LAYOUT_TRANSITION; } public void dumpLocked(PrintWriter pw) { pw.println("mDisplayId=" + mDisplayId); pw.println("mIsEnabled=" + mIsEnabled); pw.println("mPhase=" + mPhase); pw.println("mLayerStack=" + mLayerStack); pw.println("mHasContent=" + mHasContent); pw.println("mDesiredDisplayModeSpecs={" + mDesiredDisplayModeSpecs + "}"); Loading Loading
core/res/res/values/config.xml +6 −0 Original line number Diff line number Diff line Loading @@ -657,6 +657,12 @@ <!-- Indicate the display area rect for foldable devices in folded state. --> <string name="config_foldedArea"></string> <!-- Indicates that the device supports having more than one internal display on at the same time. Only applicable to devices with more than one internal display. If this option is set to false, DisplayManager will make additional effort to ensure no more than 1 internal display is powered on at the same time. --> <bool name="config_supportsConcurrentInternalDisplays">true</bool> <!-- Desk dock behavior --> <!-- The number of degrees to rotate the display when the device is in a desk dock. Loading
core/res/res/values/symbols.xml +1 −0 Original line number Diff line number Diff line Loading @@ -3800,6 +3800,7 @@ <!-- For Foldables --> <java-symbol type="array" name="config_foldedDeviceStates" /> <java-symbol type="string" name="config_foldedArea" /> <java-symbol type="bool" name="config_supportsConcurrentInternalDisplays" /> <java-symbol type="array" name="config_disableApksUnlessMatchedSku_apk_list" /> <java-symbol type="array" name="config_disableApkUnlessMatchedSku_skus_list" /> Loading
services/core/java/com/android/server/display/DisplayManagerService.java +24 −6 Original line number Diff line number Diff line Loading @@ -431,8 +431,8 @@ public final class DisplayManagerService extends SystemService { mHandler = new DisplayManagerHandler(DisplayThread.get().getLooper()); mUiHandler = UiThread.getHandler(); mDisplayDeviceRepo = new DisplayDeviceRepository(mSyncRoot, mPersistentDataStore); mLogicalDisplayMapper = new LogicalDisplayMapper(mDisplayDeviceRepo, new LogicalDisplayListener()); mLogicalDisplayMapper = new LogicalDisplayMapper(mContext, mDisplayDeviceRepo, new LogicalDisplayListener(), mSyncRoot, mHandler); mDisplayModeDirector = new DisplayModeDirector(context, mHandler); mBrightnessSynchronizer = new BrightnessSynchronizer(mContext); Resources resources = mContext.getResources(); Loading Loading @@ -1268,7 +1268,7 @@ public final class DisplayManagerService extends SystemService { DisplayPowerController dpc = mDisplayPowerControllers.get(displayId); if (dpc != null) { dpc.onDisplayChangedLocked(); dpc.onDisplayChanged(); } } Loading Loading @@ -1304,12 +1304,23 @@ public final class DisplayManagerService extends SystemService { handleLogicalDisplayChangedLocked(display); } private void handleLogicalDisplayDeviceStateTransitionLocked(@NonNull LogicalDisplay display) { final int displayId = display.getDisplayIdLocked(); final DisplayPowerController dpc = mDisplayPowerControllers.get(displayId); if (dpc != null) { dpc.onDeviceStateTransition(); } } private Runnable updateDisplayStateLocked(DisplayDevice device) { // Blank or unblank the display immediately to match the state requested // by the display power controller (if known). DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked(); if ((info.flags & DisplayDeviceInfo.FLAG_NEVER_BLANK) == 0) { final LogicalDisplay display = mLogicalDisplayMapper.getDisplayLocked(device); if (display == null) { return null; } final int displayId = display.getDisplayIdLocked(); final int state = mDisplayStates.get(displayId); Loading Loading @@ -1453,9 +1464,12 @@ public final class DisplayManagerService extends SystemService { clearViewportsLocked(); // Configure each display device. mDisplayDeviceRepo.forEachLocked((DisplayDevice device) -> { mLogicalDisplayMapper.forEachLocked((LogicalDisplay display) -> { final DisplayDevice device = display.getPrimaryDisplayDeviceLocked(); if (device != null) { configureDisplayLocked(t, device); device.performTraversalLocked(t); } }); // Tell the input system about these new viewports. Loading Loading @@ -2159,6 +2173,10 @@ public final class DisplayManagerService extends SystemService { case LogicalDisplayMapper.LOGICAL_DISPLAY_EVENT_FRAME_RATE_OVERRIDES_CHANGED: handleLogicalDisplayFrameRateOverridesChangedLocked(display); break; case LogicalDisplayMapper.LOGICAL_DISPLAY_EVENT_DEVICE_STATE_TRANSITION: handleLogicalDisplayDeviceStateTransitionLocked(display); break; } } Loading
services/core/java/com/android/server/display/DisplayPowerController.java +13 −3 Original line number Diff line number Diff line Loading @@ -780,15 +780,23 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call * when displays get swapped on foldable devices. For example, different brightness properties * of each display need to be properly reflected in AutomaticBrightnessController. */ public void onDisplayChangedLocked() { public void onDisplayChanged() { // TODO: b/175821789 - Support high brightness on multiple (folding) displays mUniqueDisplayId = mLogicalDisplay.getPrimaryDisplayDeviceLocked().getUniqueId(); mDisplayDeviceConfig = mLogicalDisplay.getPrimaryDisplayDeviceLocked() .getDisplayDeviceConfig(); loadAmbientLightSensor(); } /** * Called when the displays are preparing to transition from one device state to another. * This process involves turning off some displays so we need updatePowerState() to run and * calculate the new state. */ public void onDeviceStateTransition() { sendUpdatePowerState(); } /** * Unregisters all listeners and interrupts all running threads; halting future work. * Loading Loading @@ -1024,7 +1032,9 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call mIgnoreProximityUntilChanged = false; } if (!mLogicalDisplay.isEnabled() || mScreenOffBecauseOfProximity) { if (!mLogicalDisplay.isEnabled() || mLogicalDisplay.getPhase() == LogicalDisplay.DISPLAY_PHASE_LAYOUT_TRANSITION || mScreenOffBecauseOfProximity) { state = Display.STATE_OFF; } Loading
services/core/java/com/android/server/display/LogicalDisplay.java +48 −13 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ package com.android.server.display; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.graphics.Point; Loading Loading @@ -65,6 +66,33 @@ import java.util.Objects; final class LogicalDisplay { private static final String TAG = "LogicalDisplay"; /** * Phase indicating the logical display's existence is hidden from the rest of the framework. * This can happen if the current layout has specifically requested to keep this display * disabled. */ static final int DISPLAY_PHASE_DISABLED = -1; /** * Phase indicating that the logical display is going through a layout transition. * When in this phase, other systems can choose to special case power-state handling of a * display that might be in a transition. */ static final int DISPLAY_PHASE_LAYOUT_TRANSITION = 0; /** * The display is exposed to the rest of the system and its power state is determined by a * power-request from PowerManager. */ static final int DISPLAY_PHASE_ENABLED = 1; @IntDef(prefix = {"DISPLAY_PHASE" }, value = { DISPLAY_PHASE_DISABLED, DISPLAY_PHASE_LAYOUT_TRANSITION, DISPLAY_PHASE_ENABLED }) @interface DisplayPhase {} // The layer stack we use when the display has been blanked to prevent any // of its content from appearing. private static final int BLANK_LAYER_STACK = -1; Loading Loading @@ -129,10 +157,12 @@ final class LogicalDisplay { private final Rect mTempDisplayRect = new Rect(); /** * Indicates that the Logical display is enabled (default). See {@link #setEnabled} for * more information. * Indicates the current phase of the display. Generally, phases supersede any * requests from PowerManager in DPC's calculation for the display state. Only when the * phase is ENABLED does PowerManager's request for the display take effect. */ private boolean mIsEnabled = true; @DisplayPhase private int mPhase = DISPLAY_PHASE_ENABLED; /** * The UID mappings for refresh rate override Loading Loading @@ -721,27 +751,32 @@ final class LogicalDisplay { return old; } public void setPhase(@DisplayPhase int phase) { mPhase = phase; } /** * Sets the LogicalDisplay to be enabled or disabled. If the display is not enabled, * the system will always set the display to power off, regardless of the global state of the * device. * TODO: b/170498827 - Remove when updateDisplayStateLocked is updated. * Returns the currently set phase for this LogicalDisplay. Phases are used when transitioning * from one device state to another. {@see LogicalDisplayMapper}. */ public void setEnabled(boolean isEnabled) { mIsEnabled = isEnabled; @DisplayPhase public int getPhase() { return mPhase; } /** * @return {@code true} iff the LogicalDisplay is enabled or {@code false} * if disabled indicating that the display has been forced to be OFF. * @return {@code true} if the LogicalDisplay is enabled or {@code false} * if disabled indicating that the display should be hidden from the rest of the apps and * framework. */ public boolean isEnabled() { return mIsEnabled; // DISPLAY_PHASE_LAYOUT_TRANSITION is still considered an 'enabled' phase. return mPhase == DISPLAY_PHASE_ENABLED || mPhase == DISPLAY_PHASE_LAYOUT_TRANSITION; } public void dumpLocked(PrintWriter pw) { pw.println("mDisplayId=" + mDisplayId); pw.println("mIsEnabled=" + mIsEnabled); pw.println("mPhase=" + mPhase); pw.println("mLayerStack=" + mLayerStack); pw.println("mHasContent=" + mHasContent); pw.println("mDesiredDisplayModeSpecs={" + mDesiredDisplayModeSpecs + "}"); Loading