Loading core/java/android/os/PowerManager.java +8 −0 Original line number Diff line number Diff line Loading @@ -548,6 +548,7 @@ public final class PowerManager { WAKE_REASON_HDMI, WAKE_REASON_DISPLAY_GROUP_ADDED, WAKE_REASON_DISPLAY_GROUP_TURNED_ON, WAKE_REASON_UNFOLD_DEVICE }) @Retention(RetentionPolicy.SOURCE) public @interface WakeReason{} Loading Loading @@ -646,6 +647,12 @@ public final class PowerManager { */ public static final int WAKE_REASON_DISPLAY_GROUP_TURNED_ON = 11; /** * Wake up reason code: Waking the device due to unfolding of a foldable device. * @hide */ public static final int WAKE_REASON_UNFOLD_DEVICE = 12; /** * Convert the wake reason to a string for debugging purposes. * @hide Loading @@ -664,6 +671,7 @@ public final class PowerManager { case WAKE_REASON_LID: return "WAKE_REASON_LID"; case WAKE_REASON_DISPLAY_GROUP_ADDED: return "WAKE_REASON_DISPLAY_GROUP_ADDED"; case WAKE_REASON_DISPLAY_GROUP_TURNED_ON: return "WAKE_REASON_DISPLAY_GROUP_TURNED_ON"; case WAKE_REASON_UNFOLD_DEVICE: return "WAKE_REASON_UNFOLD_DEVICE"; default: return Integer.toString(wakeReason); } } Loading core/res/res/values/config.xml +5 −0 Original line number Diff line number Diff line Loading @@ -654,6 +654,11 @@ --> </integer-array> <!-- When entering this device state (defined in device_state_configuration.xml), we should wake the device. -1 to disable the feature (do not wake on any device-state transition). --> <integer name="config_deviceStateOnWhichToWakeUp">-1</integer> <!-- Indicate the display area rect for foldable devices in folded state. --> <string name="config_foldedArea"></string> Loading core/res/res/values/symbols.xml +1 −0 Original line number Diff line number Diff line Loading @@ -3846,6 +3846,7 @@ <!-- For Foldables --> <java-symbol type="array" name="config_foldedDeviceStates" /> <java-symbol type="integer" name="config_deviceStateOnWhichToWakeUp" /> <java-symbol type="string" name="config_foldedArea" /> <java-symbol type="bool" name="config_supportsConcurrentInternalDisplays" /> <java-symbol type="bool" name="config_unfoldTransitionEnabled" /> Loading services/core/java/com/android/server/display/DisplayPowerController.java +6 −6 Original line number Diff line number Diff line Loading @@ -721,13 +721,13 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call final IBinder token = device.getDisplayTokenLocked(); final DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked(); mHandler.post(() -> { if (mDisplayDevice == device) { return; } if (mDisplayDevice != device) { mDisplayDevice = device; mUniqueDisplayId = uniqueId; mDisplayDeviceConfig = config; loadFromDisplayDeviceConfig(token, info); updatePowerState(); } }); } Loading services/core/java/com/android/server/display/LogicalDisplayMapper.java +35 −7 Original line number Diff line number Diff line Loading @@ -22,6 +22,8 @@ import android.hardware.devicestate.DeviceStateManager; import android.os.Handler; import android.os.Looper; import android.os.Message; import android.os.PowerManager; import android.os.SystemClock; import android.os.SystemProperties; import android.text.TextUtils; import android.util.ArraySet; Loading Loading @@ -69,7 +71,7 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener { public static final int DISPLAY_GROUP_EVENT_CHANGED = 2; public static final int DISPLAY_GROUP_EVENT_REMOVED = 3; private static final int TIMEOUT_STATE_TRANSITION_MILLIS = 500; private static final int TIMEOUT_STATE_TRANSITION_MILLIS = 300; private static final int MSG_TRANSITION_TO_PENDING_DEVICE_STATE = 1; Loading Loading @@ -97,6 +99,11 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener { */ private final boolean mSupportsConcurrentInternalDisplays; /** * Wake the device when transitioning into this device state. */ private final int mDeviceStateOnWhichToWakeUp; /** * Map of all logical displays indexed by logical display id. * Any modification to mLogicalDisplays must invalidate the DisplayManagerGlobal cache. Loading @@ -113,6 +120,7 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener { private final Listener mListener; private final DisplayManagerService.SyncRoot mSyncRoot; private final LogicalDisplayMapperHandler mHandler; private final PowerManager mPowerManager; /** * Has an entry for every logical display that the rest of the system has been notified about. Loading Loading @@ -150,12 +158,15 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener { @NonNull Listener listener, @NonNull DisplayManagerService.SyncRoot syncRoot, @NonNull Handler handler) { mSyncRoot = syncRoot; mPowerManager = context.getSystemService(PowerManager.class); mHandler = new LogicalDisplayMapperHandler(handler.getLooper()); mDisplayDeviceRepo = repo; mListener = listener; mSingleDisplayDemoMode = SystemProperties.getBoolean("persist.demo.singledisplay", false); mSupportsConcurrentInternalDisplays = context.getResources().getBoolean( com.android.internal.R.bool.config_supportsConcurrentInternalDisplays); mDeviceStateOnWhichToWakeUp = context.getResources().getInteger( com.android.internal.R.integer.config_deviceStateOnWhichToWakeUp); mDisplayDeviceRepo.addListener(this); mDeviceStateToLayoutMap = new DeviceStateToLayoutMap(); } Loading Loading @@ -318,6 +329,7 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener { ipw.println("mSingleDisplayDemoMode=" + mSingleDisplayDemoMode); ipw.println("mCurrentLayout=" + mCurrentLayout); ipw.println("mDeviceStateOnWhichToWakeUp=" + mDeviceStateOnWhichToWakeUp); final int logicalDisplayCount = mLogicalDisplays.size(); ipw.println(); Loading @@ -335,7 +347,9 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener { } void setDeviceStateLocked(int state) { Slog.i(TAG, "Requesting Transition to state: " + state); final boolean isInteractive = mPowerManager.isInteractive(); Slog.i(TAG, "Requesting Transition to state: " + state + ", from state=" + mDeviceState + ", interactive=" + isInteractive); // As part of a state transition, we may need to turn off some displays temporarily so that // the transition is smooth. Plus, on some devices, only one internal displays can be // on at a time. We use DISPLAY_PHASE_LAYOUT_TRANSITION to mark a display that needs to be Loading @@ -344,8 +358,13 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener { resetLayoutLocked(mDeviceState, state, LogicalDisplay.DISPLAY_PHASE_LAYOUT_TRANSITION); } mPendingDeviceState = state; if (areAllTransitioningDisplaysOffLocked()) { // Nothing to wait on, we're good to go final boolean wakeDevice = mPendingDeviceState == mDeviceStateOnWhichToWakeUp && !isInteractive; // If all displays are off already, we can just transition here, unless the device is asleep // and we plan on waking it up. In that case, fall through to the call to wakeUp, and defer // the final transition until later once the device is awake. if (areAllTransitioningDisplaysOffLocked() && !wakeDevice) { transitionToPendingStateLocked(); return; } Loading @@ -356,6 +375,14 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener { // Send the transitioning phase updates to DisplayManager so that the displays can // start turning OFF in preparation for the new layout. updateLogicalDisplaysLocked(); if (wakeDevice) { // We already told the displays to turn off, now we need to wake the device as // we transition to this new state. We do it here so that the waking happens between the // transition from one layout to another. mPowerManager.wakeUp(SystemClock.uptimeMillis(), PowerManager.WAKE_REASON_UNFOLD_DEVICE, "server.display:unfold"); } mHandler.sendEmptyMessageDelayed(MSG_TRANSITION_TO_PENDING_DEVICE_STATE, TIMEOUT_STATE_TRANSITION_MILLIS); } Loading Loading @@ -482,6 +509,7 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener { assignDisplayGroupLocked(display); mLogicalDisplaysToUpdate.put(displayId, LOGICAL_DISPLAY_EVENT_CHANGED); // The display is involved in a display layout transition } else if (updateState == UPDATE_STATE_TRANSITION) { mLogicalDisplaysToUpdate.put(displayId, LOGICAL_DISPLAY_EVENT_DEVICE_STATE_TRANSITION); Loading Loading @@ -672,14 +700,14 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener { // We consider a display-device as changing/transition if // 1) It's already marked as transitioning // 2) It's going from enabled to disabled // 2) It's going from enabled to disabled, or vice versa // 3) It's enabled, but it's mapped to a new logical display ID. To the user this // would look like apps moving from one screen to another since task-stacks stay // with the logical display [ID]. final boolean isTransitioning = (logicalDisplay.getPhase() == LogicalDisplay.DISPLAY_PHASE_LAYOUT_TRANSITION) || (wasEnabled && !willBeEnabled) || (wasEnabled && deviceHasNewLogicalDisplayId); || (wasEnabled != willBeEnabled) || deviceHasNewLogicalDisplayId; if (isTransitioning) { setDisplayPhase(logicalDisplay, phase); Loading Loading
core/java/android/os/PowerManager.java +8 −0 Original line number Diff line number Diff line Loading @@ -548,6 +548,7 @@ public final class PowerManager { WAKE_REASON_HDMI, WAKE_REASON_DISPLAY_GROUP_ADDED, WAKE_REASON_DISPLAY_GROUP_TURNED_ON, WAKE_REASON_UNFOLD_DEVICE }) @Retention(RetentionPolicy.SOURCE) public @interface WakeReason{} Loading Loading @@ -646,6 +647,12 @@ public final class PowerManager { */ public static final int WAKE_REASON_DISPLAY_GROUP_TURNED_ON = 11; /** * Wake up reason code: Waking the device due to unfolding of a foldable device. * @hide */ public static final int WAKE_REASON_UNFOLD_DEVICE = 12; /** * Convert the wake reason to a string for debugging purposes. * @hide Loading @@ -664,6 +671,7 @@ public final class PowerManager { case WAKE_REASON_LID: return "WAKE_REASON_LID"; case WAKE_REASON_DISPLAY_GROUP_ADDED: return "WAKE_REASON_DISPLAY_GROUP_ADDED"; case WAKE_REASON_DISPLAY_GROUP_TURNED_ON: return "WAKE_REASON_DISPLAY_GROUP_TURNED_ON"; case WAKE_REASON_UNFOLD_DEVICE: return "WAKE_REASON_UNFOLD_DEVICE"; default: return Integer.toString(wakeReason); } } Loading
core/res/res/values/config.xml +5 −0 Original line number Diff line number Diff line Loading @@ -654,6 +654,11 @@ --> </integer-array> <!-- When entering this device state (defined in device_state_configuration.xml), we should wake the device. -1 to disable the feature (do not wake on any device-state transition). --> <integer name="config_deviceStateOnWhichToWakeUp">-1</integer> <!-- Indicate the display area rect for foldable devices in folded state. --> <string name="config_foldedArea"></string> Loading
core/res/res/values/symbols.xml +1 −0 Original line number Diff line number Diff line Loading @@ -3846,6 +3846,7 @@ <!-- For Foldables --> <java-symbol type="array" name="config_foldedDeviceStates" /> <java-symbol type="integer" name="config_deviceStateOnWhichToWakeUp" /> <java-symbol type="string" name="config_foldedArea" /> <java-symbol type="bool" name="config_supportsConcurrentInternalDisplays" /> <java-symbol type="bool" name="config_unfoldTransitionEnabled" /> Loading
services/core/java/com/android/server/display/DisplayPowerController.java +6 −6 Original line number Diff line number Diff line Loading @@ -721,13 +721,13 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call final IBinder token = device.getDisplayTokenLocked(); final DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked(); mHandler.post(() -> { if (mDisplayDevice == device) { return; } if (mDisplayDevice != device) { mDisplayDevice = device; mUniqueDisplayId = uniqueId; mDisplayDeviceConfig = config; loadFromDisplayDeviceConfig(token, info); updatePowerState(); } }); } Loading
services/core/java/com/android/server/display/LogicalDisplayMapper.java +35 −7 Original line number Diff line number Diff line Loading @@ -22,6 +22,8 @@ import android.hardware.devicestate.DeviceStateManager; import android.os.Handler; import android.os.Looper; import android.os.Message; import android.os.PowerManager; import android.os.SystemClock; import android.os.SystemProperties; import android.text.TextUtils; import android.util.ArraySet; Loading Loading @@ -69,7 +71,7 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener { public static final int DISPLAY_GROUP_EVENT_CHANGED = 2; public static final int DISPLAY_GROUP_EVENT_REMOVED = 3; private static final int TIMEOUT_STATE_TRANSITION_MILLIS = 500; private static final int TIMEOUT_STATE_TRANSITION_MILLIS = 300; private static final int MSG_TRANSITION_TO_PENDING_DEVICE_STATE = 1; Loading Loading @@ -97,6 +99,11 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener { */ private final boolean mSupportsConcurrentInternalDisplays; /** * Wake the device when transitioning into this device state. */ private final int mDeviceStateOnWhichToWakeUp; /** * Map of all logical displays indexed by logical display id. * Any modification to mLogicalDisplays must invalidate the DisplayManagerGlobal cache. Loading @@ -113,6 +120,7 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener { private final Listener mListener; private final DisplayManagerService.SyncRoot mSyncRoot; private final LogicalDisplayMapperHandler mHandler; private final PowerManager mPowerManager; /** * Has an entry for every logical display that the rest of the system has been notified about. Loading Loading @@ -150,12 +158,15 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener { @NonNull Listener listener, @NonNull DisplayManagerService.SyncRoot syncRoot, @NonNull Handler handler) { mSyncRoot = syncRoot; mPowerManager = context.getSystemService(PowerManager.class); mHandler = new LogicalDisplayMapperHandler(handler.getLooper()); mDisplayDeviceRepo = repo; mListener = listener; mSingleDisplayDemoMode = SystemProperties.getBoolean("persist.demo.singledisplay", false); mSupportsConcurrentInternalDisplays = context.getResources().getBoolean( com.android.internal.R.bool.config_supportsConcurrentInternalDisplays); mDeviceStateOnWhichToWakeUp = context.getResources().getInteger( com.android.internal.R.integer.config_deviceStateOnWhichToWakeUp); mDisplayDeviceRepo.addListener(this); mDeviceStateToLayoutMap = new DeviceStateToLayoutMap(); } Loading Loading @@ -318,6 +329,7 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener { ipw.println("mSingleDisplayDemoMode=" + mSingleDisplayDemoMode); ipw.println("mCurrentLayout=" + mCurrentLayout); ipw.println("mDeviceStateOnWhichToWakeUp=" + mDeviceStateOnWhichToWakeUp); final int logicalDisplayCount = mLogicalDisplays.size(); ipw.println(); Loading @@ -335,7 +347,9 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener { } void setDeviceStateLocked(int state) { Slog.i(TAG, "Requesting Transition to state: " + state); final boolean isInteractive = mPowerManager.isInteractive(); Slog.i(TAG, "Requesting Transition to state: " + state + ", from state=" + mDeviceState + ", interactive=" + isInteractive); // As part of a state transition, we may need to turn off some displays temporarily so that // the transition is smooth. Plus, on some devices, only one internal displays can be // on at a time. We use DISPLAY_PHASE_LAYOUT_TRANSITION to mark a display that needs to be Loading @@ -344,8 +358,13 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener { resetLayoutLocked(mDeviceState, state, LogicalDisplay.DISPLAY_PHASE_LAYOUT_TRANSITION); } mPendingDeviceState = state; if (areAllTransitioningDisplaysOffLocked()) { // Nothing to wait on, we're good to go final boolean wakeDevice = mPendingDeviceState == mDeviceStateOnWhichToWakeUp && !isInteractive; // If all displays are off already, we can just transition here, unless the device is asleep // and we plan on waking it up. In that case, fall through to the call to wakeUp, and defer // the final transition until later once the device is awake. if (areAllTransitioningDisplaysOffLocked() && !wakeDevice) { transitionToPendingStateLocked(); return; } Loading @@ -356,6 +375,14 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener { // Send the transitioning phase updates to DisplayManager so that the displays can // start turning OFF in preparation for the new layout. updateLogicalDisplaysLocked(); if (wakeDevice) { // We already told the displays to turn off, now we need to wake the device as // we transition to this new state. We do it here so that the waking happens between the // transition from one layout to another. mPowerManager.wakeUp(SystemClock.uptimeMillis(), PowerManager.WAKE_REASON_UNFOLD_DEVICE, "server.display:unfold"); } mHandler.sendEmptyMessageDelayed(MSG_TRANSITION_TO_PENDING_DEVICE_STATE, TIMEOUT_STATE_TRANSITION_MILLIS); } Loading Loading @@ -482,6 +509,7 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener { assignDisplayGroupLocked(display); mLogicalDisplaysToUpdate.put(displayId, LOGICAL_DISPLAY_EVENT_CHANGED); // The display is involved in a display layout transition } else if (updateState == UPDATE_STATE_TRANSITION) { mLogicalDisplaysToUpdate.put(displayId, LOGICAL_DISPLAY_EVENT_DEVICE_STATE_TRANSITION); Loading Loading @@ -672,14 +700,14 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener { // We consider a display-device as changing/transition if // 1) It's already marked as transitioning // 2) It's going from enabled to disabled // 2) It's going from enabled to disabled, or vice versa // 3) It's enabled, but it's mapped to a new logical display ID. To the user this // would look like apps moving from one screen to another since task-stacks stay // with the logical display [ID]. final boolean isTransitioning = (logicalDisplay.getPhase() == LogicalDisplay.DISPLAY_PHASE_LAYOUT_TRANSITION) || (wasEnabled && !willBeEnabled) || (wasEnabled && deviceHasNewLogicalDisplayId); || (wasEnabled != willBeEnabled) || deviceHasNewLogicalDisplayId; if (isTransitioning) { setDisplayPhase(logicalDisplay, phase); Loading