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);