Loading services/core/java/com/android/server/policy/WindowWakeUpPolicy.java +8 −0 Original line number Diff line number Diff line Loading @@ -199,6 +199,14 @@ class WindowWakeUpPolicy { // If we're given an invalid display id to wake, fall back to waking default display final int displayIdToWake = displayId == Display.INVALID_DISPLAY ? Display.DEFAULT_DISPLAY : displayId; // When there is a request to wakeup a default display, we would want to wakeup the displays // in the default and the adjacent groups if (com.android.server.display.feature.flags.Flags.separateTimeouts() && com.android.server.power.feature.flags.Flags.wakeAdjacentDisplaysOnWakeupCall() && displayIdToWake == Display.DEFAULT_DISPLAY) { wakeUp(wakeTime, reason, details); return; } mPowerManager.wakeUp(wakeTime, reason, "android.policy:" + details, displayIdToWake); } } services/core/java/com/android/server/power/PowerManagerService.java +61 −29 Original line number Diff line number Diff line Loading @@ -6437,45 +6437,45 @@ public final class PowerManagerService extends SystemService @Override // Binder call public void wakeUp(long eventTime, @WakeReason int reason, String details, String opPackageName) { wakeUpWithDisplayId(eventTime, reason, details, opPackageName, Display.DEFAULT_DISPLAY); validateWakeupIsEligible(eventTime); final int uid = Binder.getCallingUid(); final long ident = Binder.clearCallingIdentity(); try { synchronized (mLock) { IntArray groupIds = new IntArray(); if (com.android.server.display.feature.flags.Flags.separateTimeouts() && mFeatureFlags.isWakeAdjacentDisplaysOnWakeupCallEnabled()) { for (int idx = 0; idx < mPowerGroups.size(); idx++) { PowerGroup powerGroup = mPowerGroups.valueAt(idx); if (powerGroup.isDefaultOrAdjacentGroup()) { groupIds.add(powerGroup.getGroupId()); } } } else { groupIds.add(Display.DEFAULT_DISPLAY_GROUP); } wakeupDisplayGroupsLocked(groupIds, eventTime, reason, details, opPackageName, uid); } } finally { Binder.restoreCallingIdentity(ident); } } @Override // Binder call public void wakeUpWithDisplayId(long eventTime, @WakeReason int reason, String details, String opPackageName, int displayId) { final long now = mClock.uptimeMillis(); if (eventTime > now) { Slog.e(TAG, "Event time " + eventTime + " cannot be newer than " + now); throw new IllegalArgumentException("event time must not be in the future"); } int displayGroupId = getDisplayGroupId(displayId); wakeupDisplayGroups(IntArray.wrap(new int[]{displayGroupId}), eventTime, reason, details, opPackageName); } private void wakeupDisplayGroups(IntArray groupIds, long eventTime, @WakeReason int reason, String details, String opPackageName) { mContext.enforceCallingOrSelfPermission( android.Manifest.permission.DEVICE_POWER, null); validateWakeupIsEligible(eventTime); int displayGroupId = getDisplayGroupId(displayId); final int uid = Binder.getCallingUid(); final long ident = Binder.clearCallingIdentity(); try { synchronized (mLock) { if (!mBootCompleted && sQuiescent) { mDirty |= DIRTY_QUIESCENT; updatePowerStateLocked(); return; } int size = groupIds.size(); for (int i = 0; i < size; i++) { int groupId = groupIds.get(i); PowerGroup powerGroup = mPowerGroups.get(groupId); if (powerGroup != null) { wakePowerGroupLocked(mPowerGroups.get(groupId), eventTime, reason, details, uid, opPackageName, uid); } } wakeupDisplayGroupsLocked(IntArray.wrap(new int[]{displayGroupId}), eventTime, reason, details, opPackageName, uid); } } finally { Binder.restoreCallingIdentity(ident); Loading Loading @@ -7539,6 +7539,38 @@ public final class PowerManagerService extends SystemService return false; } private void validateWakeupIsEligible(long eventTime) { final long now = mClock.uptimeMillis(); if (eventTime > now) { Slog.e(TAG, "Event time " + eventTime + " cannot be newer than " + now); throw new IllegalArgumentException("event time must not be in the future"); } mContext.enforceCallingOrSelfPermission( android.Manifest.permission.DEVICE_POWER, null); } /** * This will not wakeup the power groups if the device is in the quiescent mode or is still * booting up */ private void wakeupDisplayGroupsLocked(IntArray groupIds, long eventTime, @WakeReason int reason, String details, String opPackageName, int uid) { if (!mBootCompleted && sQuiescent) { mDirty |= DIRTY_QUIESCENT; updatePowerStateLocked(); return; } int size = groupIds.size(); for (int i = 0; i < size; i++) { int groupId = groupIds.get(i); PowerGroup powerGroup = mPowerGroups.get(groupId); if (powerGroup != null) { wakePowerGroupLocked(mPowerGroups.get(groupId), eventTime, reason, details, uid, opPackageName, uid); } } } @RequiresPermission(android.Manifest.permission.DEVICE_POWER) private void goToSleepInternal(IntArray groupIds, long eventTime, int reason, int flags) { final long now = mClock.uptimeMillis(); Loading services/core/java/com/android/server/power/feature/PowerManagerFlags.java +13 −0 Original line number Diff line number Diff line Loading @@ -89,6 +89,11 @@ public class PowerManagerFlags { Flags::separateTimeoutsFlicker ); private final FlagState mWakeAdjacentDisplaysOnWakeupCall = new FlagState( Flags.FLAG_WAKE_ADJACENT_DISPLAYS_ON_WAKEUP_CALL, Flags::wakeAdjacentDisplaysOnWakeupCall ); /** Returns whether early-screen-timeout-detector is enabled on not. */ public boolean isEarlyScreenTimeoutDetectorEnabled() { return mEarlyScreenTimeoutDetectorFlagState.isEnabled(); Loading Loading @@ -178,6 +183,13 @@ public class PowerManagerFlags { return mPartialSleepWakelocks.isEnabled(); } /** * @return Whether the system should wakeup the adjacent displays too on a wakeup call */ public boolean isWakeAdjacentDisplaysOnWakeupCallEnabled() { return mWakeAdjacentDisplaysOnWakeupCall.isEnabled(); } /** * dumps all flagstates * @param pw printWriter Loading @@ -195,6 +207,7 @@ public class PowerManagerFlags { pw.println(" " + mEnableAppWakelockDataSource); pw.println(" " + mPartialSleepWakelocks); pw.println(" " + mSeparateTimeoutsFlicker); pw.println(" " + mWakeAdjacentDisplaysOnWakeupCall); } private static class FlagState { Loading services/core/java/com/android/server/power/feature/power_flags.aconfig +10 −0 Original line number Diff line number Diff line Loading @@ -129,3 +129,13 @@ flag { purpose: PURPOSE_BUGFIX } } flag { name: "wake_adjacent_displays_on_wakeup_call" namespace: "lse_desktop_experience" description: "Wakes up the displays from default and default adjacent group" bug: "428848574" metadata { purpose: PURPOSE_BUGFIX } } services/tests/powerservicetests/src/com/android/server/power/PowerManagerServiceTest.java +69 −0 Original line number Diff line number Diff line Loading @@ -923,6 +923,75 @@ public class PowerManagerServiceTest { mService.getBinderServiceInstance().releaseWakeLock(token, /* flags= */ 0); } @RequiresFlagsEnabled({com.android.server.display.feature.flags.Flags.FLAG_SEPARATE_TIMEOUTS, Flags.FLAG_WAKE_ADJACENT_DISPLAYS_ON_WAKEUP_CALL}) @Test public void testWakeup_multiplePowerGroups_wakesupAdjacentGroups() { // setup final int nonDefaultAdjacentPowerGroup = Display.DEFAULT_DISPLAY_GROUP + 1; final int nonDefaultNonAdjacentPowerGroup = Display.DEFAULT_DISPLAY_GROUP + 2; final AtomicReference<DisplayManagerInternal.DisplayGroupListener> listener = new AtomicReference<>(); long eventTime1 = 10; final DisplayInfo info = new DisplayInfo(); info.displayGroupId = Display.DEFAULT_DISPLAY_GROUP; when(mDisplayManagerInternalMock.getDisplayInfo(Display.DEFAULT_DISPLAY)).thenReturn(info); doAnswer((Answer<Void>) invocation -> { listener.set(invocation.getArgument(0)); return null; }).when(mDisplayManagerInternalMock).registerDisplayGroupListener(any()); when(mDisplayManagerInternalMock.getDisplayGroupFlags(nonDefaultAdjacentPowerGroup)) .thenReturn(DisplayGroup.FLAG_DEFAULT_GROUP_ADJACENT); createService(); startSystem(); listener.get().onDisplayGroupAdded(nonDefaultAdjacentPowerGroup); listener.get().onDisplayGroupAdded(nonDefaultNonAdjacentPowerGroup); // Verify all displays are awake. assertThat(mService.getGlobalWakefulnessLocked()) .isEqualTo(WAKEFULNESS_AWAKE); assertThat(mService.getWakefulnessLocked(Display.DEFAULT_DISPLAY_GROUP)) .isEqualTo(WAKEFULNESS_AWAKE); assertThat(mService.getWakefulnessLocked(nonDefaultAdjacentPowerGroup)) .isEqualTo(WAKEFULNESS_AWAKE); assertThat(mService.getWakefulnessLocked(nonDefaultNonAdjacentPowerGroup)) .isEqualTo(WAKEFULNESS_AWAKE); // Transition all the groups to sleep, and verify the global wakefulness mService.setWakefulnessLocked(Display.DEFAULT_DISPLAY_GROUP, WAKEFULNESS_ASLEEP, eventTime1, 0, PowerManager.GO_TO_SLEEP_REASON_INATTENTIVE, 0, null, null); mService.setWakefulnessLocked(nonDefaultAdjacentPowerGroup, WAKEFULNESS_ASLEEP, eventTime1, 0, PowerManager.GO_TO_SLEEP_REASON_INATTENTIVE, 0, null, null); mService.setWakefulnessLocked(nonDefaultNonAdjacentPowerGroup, WAKEFULNESS_ASLEEP, eventTime1, 0, PowerManager.GO_TO_SLEEP_REASON_INATTENTIVE, 0, null, null); advanceTime(1000); // assert that default group is asleep assertWithMessage("Global wakefulness is not awake") .that(mService.getGlobalWakefulnessLocked()) .isEqualTo(WAKEFULNESS_ASLEEP); // Wake default and default adjacent mService.getBinderServiceInstance().wakeUp(mClock.now(), PowerManager.WAKE_REASON_WAKE_KEY, "", ""); advanceTime(1000); // verify default group is still asleep + secondary display is awake assertWithMessage("Default group is not asleep") .that(mService.getWakefulnessLocked(Display.DEFAULT_DISPLAY_GROUP)) .isEqualTo(WAKEFULNESS_AWAKE); assertWithMessage("Secondary group is not awake") .that(mService.getWakefulnessLocked(nonDefaultAdjacentPowerGroup)) .isEqualTo(WAKEFULNESS_AWAKE); assertWithMessage("Secondary group is not awake") .that(mService.getWakefulnessLocked(nonDefaultNonAdjacentPowerGroup)) .isEqualTo(WAKEFULNESS_ASLEEP); } @RequiresFlagsEnabled(Flags.FLAG_PARTIAL_SLEEP_WAKELOCKS) @Test public void testPartialSleepWakelock_multiplePowerGroups_sleepNonDefault() { Loading Loading
services/core/java/com/android/server/policy/WindowWakeUpPolicy.java +8 −0 Original line number Diff line number Diff line Loading @@ -199,6 +199,14 @@ class WindowWakeUpPolicy { // If we're given an invalid display id to wake, fall back to waking default display final int displayIdToWake = displayId == Display.INVALID_DISPLAY ? Display.DEFAULT_DISPLAY : displayId; // When there is a request to wakeup a default display, we would want to wakeup the displays // in the default and the adjacent groups if (com.android.server.display.feature.flags.Flags.separateTimeouts() && com.android.server.power.feature.flags.Flags.wakeAdjacentDisplaysOnWakeupCall() && displayIdToWake == Display.DEFAULT_DISPLAY) { wakeUp(wakeTime, reason, details); return; } mPowerManager.wakeUp(wakeTime, reason, "android.policy:" + details, displayIdToWake); } }
services/core/java/com/android/server/power/PowerManagerService.java +61 −29 Original line number Diff line number Diff line Loading @@ -6437,45 +6437,45 @@ public final class PowerManagerService extends SystemService @Override // Binder call public void wakeUp(long eventTime, @WakeReason int reason, String details, String opPackageName) { wakeUpWithDisplayId(eventTime, reason, details, opPackageName, Display.DEFAULT_DISPLAY); validateWakeupIsEligible(eventTime); final int uid = Binder.getCallingUid(); final long ident = Binder.clearCallingIdentity(); try { synchronized (mLock) { IntArray groupIds = new IntArray(); if (com.android.server.display.feature.flags.Flags.separateTimeouts() && mFeatureFlags.isWakeAdjacentDisplaysOnWakeupCallEnabled()) { for (int idx = 0; idx < mPowerGroups.size(); idx++) { PowerGroup powerGroup = mPowerGroups.valueAt(idx); if (powerGroup.isDefaultOrAdjacentGroup()) { groupIds.add(powerGroup.getGroupId()); } } } else { groupIds.add(Display.DEFAULT_DISPLAY_GROUP); } wakeupDisplayGroupsLocked(groupIds, eventTime, reason, details, opPackageName, uid); } } finally { Binder.restoreCallingIdentity(ident); } } @Override // Binder call public void wakeUpWithDisplayId(long eventTime, @WakeReason int reason, String details, String opPackageName, int displayId) { final long now = mClock.uptimeMillis(); if (eventTime > now) { Slog.e(TAG, "Event time " + eventTime + " cannot be newer than " + now); throw new IllegalArgumentException("event time must not be in the future"); } int displayGroupId = getDisplayGroupId(displayId); wakeupDisplayGroups(IntArray.wrap(new int[]{displayGroupId}), eventTime, reason, details, opPackageName); } private void wakeupDisplayGroups(IntArray groupIds, long eventTime, @WakeReason int reason, String details, String opPackageName) { mContext.enforceCallingOrSelfPermission( android.Manifest.permission.DEVICE_POWER, null); validateWakeupIsEligible(eventTime); int displayGroupId = getDisplayGroupId(displayId); final int uid = Binder.getCallingUid(); final long ident = Binder.clearCallingIdentity(); try { synchronized (mLock) { if (!mBootCompleted && sQuiescent) { mDirty |= DIRTY_QUIESCENT; updatePowerStateLocked(); return; } int size = groupIds.size(); for (int i = 0; i < size; i++) { int groupId = groupIds.get(i); PowerGroup powerGroup = mPowerGroups.get(groupId); if (powerGroup != null) { wakePowerGroupLocked(mPowerGroups.get(groupId), eventTime, reason, details, uid, opPackageName, uid); } } wakeupDisplayGroupsLocked(IntArray.wrap(new int[]{displayGroupId}), eventTime, reason, details, opPackageName, uid); } } finally { Binder.restoreCallingIdentity(ident); Loading Loading @@ -7539,6 +7539,38 @@ public final class PowerManagerService extends SystemService return false; } private void validateWakeupIsEligible(long eventTime) { final long now = mClock.uptimeMillis(); if (eventTime > now) { Slog.e(TAG, "Event time " + eventTime + " cannot be newer than " + now); throw new IllegalArgumentException("event time must not be in the future"); } mContext.enforceCallingOrSelfPermission( android.Manifest.permission.DEVICE_POWER, null); } /** * This will not wakeup the power groups if the device is in the quiescent mode or is still * booting up */ private void wakeupDisplayGroupsLocked(IntArray groupIds, long eventTime, @WakeReason int reason, String details, String opPackageName, int uid) { if (!mBootCompleted && sQuiescent) { mDirty |= DIRTY_QUIESCENT; updatePowerStateLocked(); return; } int size = groupIds.size(); for (int i = 0; i < size; i++) { int groupId = groupIds.get(i); PowerGroup powerGroup = mPowerGroups.get(groupId); if (powerGroup != null) { wakePowerGroupLocked(mPowerGroups.get(groupId), eventTime, reason, details, uid, opPackageName, uid); } } } @RequiresPermission(android.Manifest.permission.DEVICE_POWER) private void goToSleepInternal(IntArray groupIds, long eventTime, int reason, int flags) { final long now = mClock.uptimeMillis(); Loading
services/core/java/com/android/server/power/feature/PowerManagerFlags.java +13 −0 Original line number Diff line number Diff line Loading @@ -89,6 +89,11 @@ public class PowerManagerFlags { Flags::separateTimeoutsFlicker ); private final FlagState mWakeAdjacentDisplaysOnWakeupCall = new FlagState( Flags.FLAG_WAKE_ADJACENT_DISPLAYS_ON_WAKEUP_CALL, Flags::wakeAdjacentDisplaysOnWakeupCall ); /** Returns whether early-screen-timeout-detector is enabled on not. */ public boolean isEarlyScreenTimeoutDetectorEnabled() { return mEarlyScreenTimeoutDetectorFlagState.isEnabled(); Loading Loading @@ -178,6 +183,13 @@ public class PowerManagerFlags { return mPartialSleepWakelocks.isEnabled(); } /** * @return Whether the system should wakeup the adjacent displays too on a wakeup call */ public boolean isWakeAdjacentDisplaysOnWakeupCallEnabled() { return mWakeAdjacentDisplaysOnWakeupCall.isEnabled(); } /** * dumps all flagstates * @param pw printWriter Loading @@ -195,6 +207,7 @@ public class PowerManagerFlags { pw.println(" " + mEnableAppWakelockDataSource); pw.println(" " + mPartialSleepWakelocks); pw.println(" " + mSeparateTimeoutsFlicker); pw.println(" " + mWakeAdjacentDisplaysOnWakeupCall); } private static class FlagState { Loading
services/core/java/com/android/server/power/feature/power_flags.aconfig +10 −0 Original line number Diff line number Diff line Loading @@ -129,3 +129,13 @@ flag { purpose: PURPOSE_BUGFIX } } flag { name: "wake_adjacent_displays_on_wakeup_call" namespace: "lse_desktop_experience" description: "Wakes up the displays from default and default adjacent group" bug: "428848574" metadata { purpose: PURPOSE_BUGFIX } }
services/tests/powerservicetests/src/com/android/server/power/PowerManagerServiceTest.java +69 −0 Original line number Diff line number Diff line Loading @@ -923,6 +923,75 @@ public class PowerManagerServiceTest { mService.getBinderServiceInstance().releaseWakeLock(token, /* flags= */ 0); } @RequiresFlagsEnabled({com.android.server.display.feature.flags.Flags.FLAG_SEPARATE_TIMEOUTS, Flags.FLAG_WAKE_ADJACENT_DISPLAYS_ON_WAKEUP_CALL}) @Test public void testWakeup_multiplePowerGroups_wakesupAdjacentGroups() { // setup final int nonDefaultAdjacentPowerGroup = Display.DEFAULT_DISPLAY_GROUP + 1; final int nonDefaultNonAdjacentPowerGroup = Display.DEFAULT_DISPLAY_GROUP + 2; final AtomicReference<DisplayManagerInternal.DisplayGroupListener> listener = new AtomicReference<>(); long eventTime1 = 10; final DisplayInfo info = new DisplayInfo(); info.displayGroupId = Display.DEFAULT_DISPLAY_GROUP; when(mDisplayManagerInternalMock.getDisplayInfo(Display.DEFAULT_DISPLAY)).thenReturn(info); doAnswer((Answer<Void>) invocation -> { listener.set(invocation.getArgument(0)); return null; }).when(mDisplayManagerInternalMock).registerDisplayGroupListener(any()); when(mDisplayManagerInternalMock.getDisplayGroupFlags(nonDefaultAdjacentPowerGroup)) .thenReturn(DisplayGroup.FLAG_DEFAULT_GROUP_ADJACENT); createService(); startSystem(); listener.get().onDisplayGroupAdded(nonDefaultAdjacentPowerGroup); listener.get().onDisplayGroupAdded(nonDefaultNonAdjacentPowerGroup); // Verify all displays are awake. assertThat(mService.getGlobalWakefulnessLocked()) .isEqualTo(WAKEFULNESS_AWAKE); assertThat(mService.getWakefulnessLocked(Display.DEFAULT_DISPLAY_GROUP)) .isEqualTo(WAKEFULNESS_AWAKE); assertThat(mService.getWakefulnessLocked(nonDefaultAdjacentPowerGroup)) .isEqualTo(WAKEFULNESS_AWAKE); assertThat(mService.getWakefulnessLocked(nonDefaultNonAdjacentPowerGroup)) .isEqualTo(WAKEFULNESS_AWAKE); // Transition all the groups to sleep, and verify the global wakefulness mService.setWakefulnessLocked(Display.DEFAULT_DISPLAY_GROUP, WAKEFULNESS_ASLEEP, eventTime1, 0, PowerManager.GO_TO_SLEEP_REASON_INATTENTIVE, 0, null, null); mService.setWakefulnessLocked(nonDefaultAdjacentPowerGroup, WAKEFULNESS_ASLEEP, eventTime1, 0, PowerManager.GO_TO_SLEEP_REASON_INATTENTIVE, 0, null, null); mService.setWakefulnessLocked(nonDefaultNonAdjacentPowerGroup, WAKEFULNESS_ASLEEP, eventTime1, 0, PowerManager.GO_TO_SLEEP_REASON_INATTENTIVE, 0, null, null); advanceTime(1000); // assert that default group is asleep assertWithMessage("Global wakefulness is not awake") .that(mService.getGlobalWakefulnessLocked()) .isEqualTo(WAKEFULNESS_ASLEEP); // Wake default and default adjacent mService.getBinderServiceInstance().wakeUp(mClock.now(), PowerManager.WAKE_REASON_WAKE_KEY, "", ""); advanceTime(1000); // verify default group is still asleep + secondary display is awake assertWithMessage("Default group is not asleep") .that(mService.getWakefulnessLocked(Display.DEFAULT_DISPLAY_GROUP)) .isEqualTo(WAKEFULNESS_AWAKE); assertWithMessage("Secondary group is not awake") .that(mService.getWakefulnessLocked(nonDefaultAdjacentPowerGroup)) .isEqualTo(WAKEFULNESS_AWAKE); assertWithMessage("Secondary group is not awake") .that(mService.getWakefulnessLocked(nonDefaultNonAdjacentPowerGroup)) .isEqualTo(WAKEFULNESS_ASLEEP); } @RequiresFlagsEnabled(Flags.FLAG_PARTIAL_SLEEP_WAKELOCKS) @Test public void testPartialSleepWakelock_multiplePowerGroups_sleepNonDefault() { Loading