From eed9e92b6569d0d7db3fb5f2a752b7b7fbcd0216 Mon Sep 17 00:00:00 2001 From: Robert Horvath Date: Wed, 19 May 2021 17:47:58 +0200 Subject: [PATCH] Acquire Booting SuspendBlocker during boot With quiescent boot, the display stays off during boot, so the Display SuspendBlocker will not keep the device awake during boot. To make sure that the device does not suspend during boot, acquire a SuspendBlocker that is held while the device is booting. Bug: 180866475 Test: atest PowerManagerServiceTest Change-Id: Iba93ed3b7fd957820ce15d336514dfce8f5a54fa --- .../server/power/PowerManagerService.java | 20 ++++++++++++++ .../server/power/PowerManagerServiceTest.java | 27 +++++++++++++++++++ 2 files changed, 47 insertions(+) diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java index 9638255dfc799..c39b5da514862 100644 --- a/services/core/java/com/android/server/power/PowerManagerService.java +++ b/services/core/java/com/android/server/power/PowerManagerService.java @@ -352,6 +352,12 @@ public final class PowerManagerService extends SystemService // requested because it is updated asynchronously by the display power controller. private DisplayGroupPowerStateMapper mDisplayGroupPowerStateMapper; + // The suspend blocker used to keep the CPU alive while the device is booting. + private final SuspendBlocker mBootingSuspendBlocker; + + // True if the wake lock suspend blocker has been acquired. + private boolean mHoldingBootingSuspendBlocker; + // The suspend blocker used to keep the CPU alive when an application has acquired // a wake lock. private final SuspendBlocker mWakeLockSuspendBlocker; @@ -1036,10 +1042,16 @@ public final class PowerManagerService extends SystemService } synchronized (mLock) { + mBootingSuspendBlocker = + mInjector.createSuspendBlocker(this, "PowerManagerService.Booting"); mWakeLockSuspendBlocker = mInjector.createSuspendBlocker(this, "PowerManagerService.WakeLocks"); mDisplaySuspendBlocker = mInjector.createSuspendBlocker(this, "PowerManagerService.Display"); + if (mBootingSuspendBlocker != null) { + mBootingSuspendBlocker.acquire(); + mHoldingBootingSuspendBlocker = true; + } if (mDisplaySuspendBlocker != null) { mDisplaySuspendBlocker.acquire(); mHoldingDisplaySuspendBlocker = true; @@ -3385,6 +3397,10 @@ public final class PowerManagerService extends SystemService } // First acquire suspend blockers if needed. + if (!mBootCompleted && !mHoldingBootingSuspendBlocker) { + mBootingSuspendBlocker.acquire(); + mHoldingBootingSuspendBlocker = true; + } if (needWakeLockSuspendBlocker && !mHoldingWakeLockSuspendBlocker) { mWakeLockSuspendBlocker.acquire(); mHoldingWakeLockSuspendBlocker = true; @@ -3411,6 +3427,10 @@ public final class PowerManagerService extends SystemService } // Then release suspend blockers if needed. + if (mBootCompleted && mHoldingBootingSuspendBlocker) { + mBootingSuspendBlocker.release(); + mHoldingBootingSuspendBlocker = false; + } if (!needWakeLockSuspendBlocker && mHoldingWakeLockSuspendBlocker) { mWakeLockSuspendBlocker.release(); mHoldingWakeLockSuspendBlocker = false; diff --git a/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java index 5eabc1bea1484..b43161408b1c7 100644 --- a/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java @@ -740,6 +740,33 @@ public class PowerManagerServiceTest { assertTrue(isAcquired[0]); } + @Test + public void testSuspendBlockerHeldDuringBoot() throws Exception { + final String suspendBlockerName = "PowerManagerService.Booting"; + + final boolean[] isAcquired = new boolean[1]; + doAnswer(inv -> { + isAcquired[0] = false; + return null; + }).when(mNativeWrapperMock).nativeReleaseSuspendBlocker(eq(suspendBlockerName)); + + doAnswer(inv -> { + isAcquired[0] = true; + return null; + }).when(mNativeWrapperMock).nativeAcquireSuspendBlocker(eq(suspendBlockerName)); + + // Need to create the service after we stub the mocks for this test because some of the + // mocks are used during the constructor. + createService(); + assertTrue(isAcquired[0]); + + mService.systemReady(null); + assertTrue(isAcquired[0]); + + mService.onBootPhase(SystemService.PHASE_BOOT_COMPLETED); + assertFalse(isAcquired[0]); + } + @Test public void testInattentiveSleep_hideWarningIfStayOnIsEnabledAndPluggedIn() throws Exception { setMinimumScreenOffTimeoutConfig(5);