diff options
| author | 2024-09-09 01:46:33 +0000 | |
|---|---|---|
| committer | 2024-09-09 01:46:33 +0000 | |
| commit | aa5dd68166062943a580fcb75b993c967b7643ac (patch) | |
| tree | 6b2ef2bc66b8c777b8c2123aa002bcad4d59940d | |
| parent | 784140a07354af24f4e8724cf68ce9530590d9fd (diff) | |
| parent | 85cc18447def03031850e3cc68659f1310ffe2b3 (diff) | |
Merge "Avoid race of checking screen states and sleep token" into main
11 files changed, 39 insertions, 102 deletions
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java index 1fcd7f1ef861..ed9dcfadab83 100644 --- a/services/core/java/com/android/server/policy/PhoneWindowManager.java +++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java @@ -535,7 +535,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { volatile boolean mRequestedOrSleepingDefaultDisplay; /** - * This is used to check whether to invoke {@link #updateScreenOffSleepToken} when screen is + * This is used to check whether to acquire screen-off sleep token when screen is * turned off. E.g. if it is false when screen is turned off and the display is swapping, it * is expected that the screen will be on in a short time. Then it is unnecessary to acquire * screen-off-sleep-token, so it can avoid intermediate visibility or lifecycle changes. @@ -610,7 +610,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { private boolean mPendingKeyguardOccluded; private boolean mKeyguardOccludedChanged; - private ActivityTaskManagerInternal.SleepTokenAcquirer mScreenOffSleepTokenAcquirer; Intent mHomeIntent; Intent mCarDockIntent; Intent mDeskDockIntent; @@ -2220,9 +2219,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { mLockPatternUtils = new LockPatternUtils(mContext); mLogger = new MetricsLogger(); - mScreenOffSleepTokenAcquirer = mActivityTaskManagerInternal - .createSleepTokenAcquirer("ScreenOff"); - Resources res = mContext.getResources(); mWakeOnDpadKeyPress = res.getBoolean(com.android.internal.R.bool.config_wakeOnDpadKeyPress); @@ -5521,13 +5517,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { mRequestedOrSleepingDefaultDisplay = true; mIsGoingToSleepDefaultDisplay = true; - // In case startedGoingToSleep is called after screenTurnedOff (the source caller is in - // order but the methods run on different threads) and updateScreenOffSleepToken was - // skipped. Then acquire sleep token if screen was off. - if (!mDefaultDisplayPolicy.isScreenOnFully() && !mDefaultDisplayPolicy.isScreenOnEarly()) { - updateScreenOffSleepToken(true /* acquire */); - } - if (mKeyguardDelegate != null) { mKeyguardDelegate.onStartedGoingToSleep(pmSleepReason); } @@ -5688,11 +5677,9 @@ public class PhoneWindowManager implements WindowManagerPolicy { if (DEBUG_WAKEUP) Slog.i(TAG, "Display" + displayId + " turned off..."); if (displayId == DEFAULT_DISPLAY) { - if (!isSwappingDisplay || mIsGoingToSleepDefaultDisplay) { - updateScreenOffSleepToken(true /* acquire */); - } + final boolean acquireSleepToken = !isSwappingDisplay || mIsGoingToSleepDefaultDisplay; mRequestedOrSleepingDefaultDisplay = false; - mDefaultDisplayPolicy.screenTurnedOff(); + mDefaultDisplayPolicy.screenTurnedOff(acquireSleepToken); synchronized (mLock) { if (mKeyguardDelegate != null) { mKeyguardDelegate.onScreenTurnedOff(); @@ -5748,7 +5735,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { if (displayId == DEFAULT_DISPLAY) { Trace.asyncTraceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "screenTurningOn", 0 /* cookie */); - updateScreenOffSleepToken(false /* acquire */); mDefaultDisplayPolicy.screenTurningOn(screenOnListener); mBootAnimationDismissable = false; @@ -6255,15 +6241,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { } } - // TODO (multidisplay): Support multiple displays in WindowManagerPolicy. - private void updateScreenOffSleepToken(boolean acquire) { - if (acquire) { - mScreenOffSleepTokenAcquirer.acquire(DEFAULT_DISPLAY); - } else { - mScreenOffSleepTokenAcquirer.release(DEFAULT_DISPLAY); - } - } - /** {@inheritDoc} */ @Override public void enableScreenAfterBoot() { diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java b/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java index b8ce02ed5937..3d6b64b2e536 100644 --- a/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java +++ b/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java @@ -130,35 +130,6 @@ public abstract class ActivityTaskManagerInternal { } /** - * Sleep tokens cause the activity manager to put the top activity to sleep. - * They are used by components such as dreams that may hide and block interaction - * with underlying activities. - * The Acquirer provides an interface that encapsulates the underlying work, so the user does - * not need to handle the token by him/herself. - */ - public interface SleepTokenAcquirer { - - /** - * Acquires a sleep token. - * @param displayId The display to apply to. - */ - void acquire(int displayId); - - /** - * Releases the sleep token. - * @param displayId The display to apply to. - */ - void release(int displayId); - } - - /** - * Creates a sleep token acquirer for the specified display with the specified tag. - * - * @param tag A string identifying the purpose (eg. "Dream"). - */ - public abstract SleepTokenAcquirer createSleepTokenAcquirer(@NonNull String tag); - - /** * Returns home activity for the specified user. * * @param userId ID of the user or {@link android.os.UserHandle#USER_ALL} diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java index e25d940d9781..49ca698e36e2 100644 --- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java +++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java @@ -4356,6 +4356,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { mTaskOrganizerController.dump(pw, " "); mVisibleActivityProcessTracker.dump(pw, " "); mActiveUids.dump(pw, " "); + pw.println(" SleepTokens=" + mRootWindowContainer.mSleepTokens); if (mDemoteTopAppReasons != 0) { pw.println(" mDemoteTopAppReasons=" + mDemoteTopAppReasons); } @@ -5071,17 +5072,16 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { EventLogTags.writeWmSetResumedActivity(r.mUserId, r.shortComponentName, reason); } - final class SleepTokenAcquirerImpl implements ActivityTaskManagerInternal.SleepTokenAcquirer { + final class SleepTokenAcquirer { private final String mTag; private final SparseArray<RootWindowContainer.SleepToken> mSleepTokens = new SparseArray<>(); - SleepTokenAcquirerImpl(@NonNull String tag) { + SleepTokenAcquirer(@NonNull String tag) { mTag = tag; } - @Override - public void acquire(int displayId) { + void acquire(int displayId) { synchronized (mGlobalLock) { if (!mSleepTokens.contains(displayId)) { mSleepTokens.append(displayId, @@ -5091,8 +5091,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { } } - @Override - public void release(int displayId) { + void release(int displayId) { synchronized (mGlobalLock) { final RootWindowContainer.SleepToken token = mSleepTokens.get(displayId); if (token != null) { @@ -5955,11 +5954,6 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { } final class LocalService extends ActivityTaskManagerInternal { - @Override - public SleepTokenAcquirer createSleepTokenAcquirer(@NonNull String tag) { - Objects.requireNonNull(tag); - return new SleepTokenAcquirerImpl(tag); - } @Override public ComponentName getHomeActivityForUser(int userId) { diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java index e8a3951a93d4..10e0641b0582 100644 --- a/services/core/java/com/android/server/wm/DisplayContent.java +++ b/services/core/java/com/android/server/wm/DisplayContent.java @@ -735,8 +735,6 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp /** All tokens used to put activities on this root task to sleep (including mOffToken) */ final ArrayList<RootWindowContainer.SleepToken> mAllSleepTokens = new ArrayList<>(); - /** The token acquirer to put root tasks on the display to sleep */ - private final ActivityTaskManagerInternal.SleepTokenAcquirer mOffTokenAcquirer; private boolean mSleeping; @@ -1131,7 +1129,6 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp mDisplay = display; mDisplayId = display.getDisplayId(); mCurrentUniqueDisplayId = display.getUniqueId(); - mOffTokenAcquirer = mRootWindowContainer.mDisplayOffTokenAcquirer; mWallpaperController = new WallpaperController(mWmService, this); mWallpaperController.resetLargestDisplay(display); display.getDisplayInfo(mDisplayInfo); @@ -6157,9 +6154,9 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp final int displayState = mDisplayInfo.state; if (displayId != DEFAULT_DISPLAY) { if (displayState == Display.STATE_OFF) { - mOffTokenAcquirer.acquire(mDisplayId); + mRootWindowContainer.mDisplayOffTokenAcquirer.acquire(mDisplayId); } else if (displayState == Display.STATE_ON) { - mOffTokenAcquirer.release(mDisplayId); + mRootWindowContainer.mDisplayOffTokenAcquirer.release(mDisplayId); } ProtoLog.v(WM_DEBUG_CONTENT_RECORDING, "Content Recording: Display %d state was (%d), is now (%d), so update " diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java index 5c621208c4db..107d31e4e25c 100644 --- a/services/core/java/com/android/server/wm/DisplayPolicy.java +++ b/services/core/java/com/android/server/wm/DisplayPolicy.java @@ -804,6 +804,14 @@ public class DisplayPolicy { mAwake /* waiting */); if (!awake) { onDisplaySwitchFinished(); + // In case PhoneWindowManager's startedGoingToSleep is called after screenTurnedOff + // (the source caller is in order but the methods run on different threads) and + // updateScreenOffSleepToken was skipped by mIsGoingToSleepDefaultDisplay. Then + // acquire sleep token if screen is off. + if (!mScreenOnEarly && !mScreenOnFully && !mDisplayContent.isSleeping()) { + Slog.w(TAG, "Late acquire sleep token for " + mDisplayContent); + mService.mRoot.mDisplayOffTokenAcquirer.acquire(mDisplayContent.mDisplayId); + } } } } @@ -851,6 +859,7 @@ public class DisplayPolicy { public void screenTurningOn(ScreenOnListener screenOnListener) { WindowProcessController visibleDozeUiProcess = null; synchronized (mLock) { + mService.mRoot.mDisplayOffTokenAcquirer.release(mDisplayContent.mDisplayId); mScreenOnEarly = true; mScreenOnFully = false; mKeyguardDrawComplete = false; @@ -875,8 +884,12 @@ public class DisplayPolicy { onDisplaySwitchFinished(); } - public void screenTurnedOff() { + /** It is called after {@link #screenTurningOn}. This runs on PowerManager's thread. */ + public void screenTurnedOff(boolean acquireSleepToken) { synchronized (mLock) { + if (acquireSleepToken) { + mService.mRoot.mDisplayOffTokenAcquirer.acquire(mDisplayContent.mDisplayId); + } mScreenOnEarly = false; mScreenOnFully = false; mKeyguardDrawComplete = false; diff --git a/services/core/java/com/android/server/wm/KeyguardController.java b/services/core/java/com/android/server/wm/KeyguardController.java index 5d8a96c530ef..0c489d6207e9 100644 --- a/services/core/java/com/android/server/wm/KeyguardController.java +++ b/services/core/java/com/android/server/wm/KeyguardController.java @@ -87,7 +87,7 @@ class KeyguardController { private final SparseArray<KeyguardDisplayState> mDisplayStates = new SparseArray<>(); private final ActivityTaskManagerService mService; private RootWindowContainer mRootWindowContainer; - private final ActivityTaskManagerInternal.SleepTokenAcquirer mSleepTokenAcquirer; + private final ActivityTaskManagerService.SleepTokenAcquirer mSleepTokenAcquirer; private boolean mWaitingForWakeTransition; private Transition.ReadyCondition mWaitAodHide = null; @@ -95,7 +95,7 @@ class KeyguardController { ActivityTaskSupervisor taskSupervisor) { mService = service; mTaskSupervisor = taskSupervisor; - mSleepTokenAcquirer = mService.new SleepTokenAcquirerImpl(KEYGUARD_SLEEP_TOKEN_TAG); + mSleepTokenAcquirer = mService.new SleepTokenAcquirer(KEYGUARD_SLEEP_TOKEN_TAG); } void setWindowManager(WindowManagerService windowManager) { @@ -658,10 +658,10 @@ class KeyguardController { private boolean mRequestDismissKeyguard; private final ActivityTaskManagerService mService; - private final ActivityTaskManagerInternal.SleepTokenAcquirer mSleepTokenAcquirer; + private final ActivityTaskManagerService.SleepTokenAcquirer mSleepTokenAcquirer; KeyguardDisplayState(ActivityTaskManagerService service, int displayId, - ActivityTaskManagerInternal.SleepTokenAcquirer acquirer) { + ActivityTaskManagerService.SleepTokenAcquirer acquirer) { mService = service; mDisplayId = displayId; mSleepTokenAcquirer = acquirer; diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java index 866dcd56ea91..8f5612c61e1c 100644 --- a/services/core/java/com/android/server/wm/RootWindowContainer.java +++ b/services/core/java/com/android/server/wm/RootWindowContainer.java @@ -215,7 +215,7 @@ class RootWindowContainer extends WindowContainer<DisplayContent> private static final String DISPLAY_OFF_SLEEP_TOKEN_TAG = "Display-off"; /** The token acquirer to put root tasks on the displays to sleep */ - final ActivityTaskManagerInternal.SleepTokenAcquirer mDisplayOffTokenAcquirer; + final ActivityTaskManagerService.SleepTokenAcquirer mDisplayOffTokenAcquirer; /** * The modes which affect which tasks are returned when calling @@ -450,7 +450,7 @@ class RootWindowContainer extends WindowContainer<DisplayContent> mService = service.mAtmService; mTaskSupervisor = mService.mTaskSupervisor; mTaskSupervisor.mRootWindowContainer = this; - mDisplayOffTokenAcquirer = mService.new SleepTokenAcquirerImpl(DISPLAY_OFF_SLEEP_TOKEN_TAG); + mDisplayOffTokenAcquirer = mService.new SleepTokenAcquirer(DISPLAY_OFF_SLEEP_TOKEN_TAG); mDeviceStateController = new DeviceStateController(service.mContext, service.mGlobalLock); mDisplayRotationCoordinator = new DisplayRotationCoordinator(); } diff --git a/services/tests/wmtests/src/com/android/server/policy/PhoneWindowManagerTests.java b/services/tests/wmtests/src/com/android/server/policy/PhoneWindowManagerTests.java index e694c0b4afc1..536dcfb3579c 100644 --- a/services/tests/wmtests/src/com/android/server/policy/PhoneWindowManagerTests.java +++ b/services/tests/wmtests/src/com/android/server/policy/PhoneWindowManagerTests.java @@ -42,7 +42,6 @@ import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.clearInvocations; import android.app.ActivityManager; import android.app.AppOpsManager; @@ -135,15 +134,13 @@ public class PhoneWindowManagerTests { doNothing().when(mPhoneWindowManager).initializeHdmiState(); final boolean[] isScreenTurnedOff = { false }; final DisplayPolicy displayPolicy = mock(DisplayPolicy.class); - doAnswer(invocation -> isScreenTurnedOff[0] = true).when(displayPolicy).screenTurnedOff(); + doAnswer(invocation -> isScreenTurnedOff[0] = true).when(displayPolicy).screenTurnedOff( + anyBoolean()); doAnswer(invocation -> !isScreenTurnedOff[0]).when(displayPolicy).isScreenOnEarly(); doAnswer(invocation -> !isScreenTurnedOff[0]).when(displayPolicy).isScreenOnFully(); mPhoneWindowManager.mDefaultDisplayPolicy = displayPolicy; mPhoneWindowManager.mDefaultDisplayRotation = mock(DisplayRotation.class); - final ActivityTaskManagerInternal.SleepTokenAcquirer tokenAcquirer = - mock(ActivityTaskManagerInternal.SleepTokenAcquirer.class); - doReturn(tokenAcquirer).when(mAtmInternal).createSleepTokenAcquirer(anyString()); final PowerManager pm = mock(PowerManager.class); doReturn(true).when(pm).isInteractive(); doReturn(pm).when(mContext).getSystemService(eq(Context.POWER_SERVICE)); @@ -155,9 +152,8 @@ public class PhoneWindowManagerTests { assertThat(mPhoneWindowManager.mIsGoingToSleepDefaultDisplay).isFalse(); // Skip sleep-token for non-sleep-screen-off. - clearInvocations(tokenAcquirer); mPhoneWindowManager.screenTurnedOff(DEFAULT_DISPLAY, true /* isSwappingDisplay */); - verify(tokenAcquirer, never()).acquire(anyInt()); + verify(displayPolicy).screenTurnedOff(false /* acquireSleepToken */); assertThat(isScreenTurnedOff[0]).isTrue(); // Apply sleep-token for sleep-screen-off. @@ -165,21 +161,10 @@ public class PhoneWindowManagerTests { mPhoneWindowManager.startedGoingToSleep(DEFAULT_DISPLAY, 0 /* reason */); assertThat(mPhoneWindowManager.mIsGoingToSleepDefaultDisplay).isTrue(); mPhoneWindowManager.screenTurnedOff(DEFAULT_DISPLAY, true /* isSwappingDisplay */); - verify(tokenAcquirer).acquire(eq(DEFAULT_DISPLAY)); + verify(displayPolicy).screenTurnedOff(true /* acquireSleepToken */); mPhoneWindowManager.finishedGoingToSleep(DEFAULT_DISPLAY, 0 /* reason */); assertThat(mPhoneWindowManager.mIsGoingToSleepDefaultDisplay).isFalse(); - - // Simulate unexpected reversed order: screenTurnedOff -> startedGoingToSleep. The sleep - // token can still be acquired. - isScreenTurnedOff[0] = false; - clearInvocations(tokenAcquirer); - mPhoneWindowManager.screenTurnedOff(DEFAULT_DISPLAY, true /* isSwappingDisplay */); - verify(tokenAcquirer, never()).acquire(anyInt()); - assertThat(displayPolicy.isScreenOnEarly()).isFalse(); - assertThat(displayPolicy.isScreenOnFully()).isFalse(); - mPhoneWindowManager.startedGoingToSleep(DEFAULT_DISPLAY, 0 /* reason */); - verify(tokenAcquirer).acquire(eq(DEFAULT_DISPLAY)); } @Test diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java index 1e035dab3c5e..e2e76d6ef4e5 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java @@ -3231,7 +3231,7 @@ public class ActivityRecordTests extends WindowTestsBase { mDisplayContent.mOpeningApps.remove(activity); mDisplayContent.mClosingApps.remove(activity); activity.commitVisibility(false /* visible */, false /* performLayout */); - mDisplayContent.getDisplayPolicy().screenTurnedOff(); + mDisplayContent.getDisplayPolicy().screenTurnedOff(false /* acquireSleepToken */); final KeyguardController controller = mSupervisor.getKeyguardController(); doReturn(true).when(controller).isKeyguardGoingAway(anyInt()); activity.setVisibility(true); diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java index caeb41c78967..f32a234f3e40 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java @@ -284,11 +284,11 @@ public class DisplayPolicyTests extends WindowTestsBase { final DisplayPolicy policy = mDisplayContent.getDisplayPolicy(); policy.addWindowLw(mNotificationShadeWindow, mNotificationShadeWindow.mAttrs); - policy.screenTurnedOff(); + policy.screenTurnedOff(false /* acquireSleepToken */); policy.setAwake(false); policy.screenTurningOn(null /* screenOnListener */); assertTrue(wpc.isShowingUiWhileDozing()); - policy.screenTurnedOff(); + policy.screenTurnedOff(false /* acquireSleepToken */); assertFalse(wpc.isShowingUiWhileDozing()); policy.screenTurningOn(null /* screenOnListener */); @@ -393,7 +393,7 @@ public class DisplayPolicyTests extends WindowTestsBase { info.logicalWidth, info.logicalHeight).mConfigFrame); // If screen is not fully turned on, then the cache should be preserved. - displayPolicy.screenTurnedOff(); + displayPolicy.screenTurnedOff(false /* acquireSleepToken */); final TransitionController transitionController = mDisplayContent.mTransitionController; spyOn(transitionController); doReturn(true).when(transitionController).isCollecting(); diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskFragmentTest.java b/services/tests/wmtests/src/com/android/server/wm/TaskFragmentTest.java index cc1805aa933c..fd959b950e16 100644 --- a/services/tests/wmtests/src/com/android/server/wm/TaskFragmentTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/TaskFragmentTest.java @@ -242,7 +242,7 @@ public class TaskFragmentTest extends WindowTestsBase { final Rect relStartBounds = new Rect(mTaskFragment.getRelativeEmbeddedBounds()); final DisplayPolicy displayPolicy = mDisplayContent.getDisplayPolicy(); - displayPolicy.screenTurnedOff(); + displayPolicy.screenTurnedOff(false /* acquireSleepToken */); assertFalse(mTaskFragment.okToAnimate()); |