From 271617af8300fcc481e83070d0ed874ac5b89692 Mon Sep 17 00:00:00 2001 From: Bryce Lee Date: Thu, 15 Mar 2018 10:39:12 -0700 Subject: [PATCH] Do not sleep activities in focused stack when keyguard is going away ActivityStack#shouldSleepActivities reports back whether we should put activities in stack to sleep based on the display state. We should also consider the keyguard state, as it's possible for a stack to become visible as the keyguard is disappearing, but before the display has reported on, such as when we're unlocking by fingerprint. In this case, sleeping will lead to an extraneous and incorrect lifecycle shift to stop. Change-Id: I0f0c8bc90093bf636e5ba9ddce7046da631248b0 Fixes: 74603384 Test: atest FrameworksServicesTests:com.android.server.am.ActivityStackTests#testShouldSleepActivities --- .../com/android/server/am/ActivityStack.java | 8 +++++ .../android/server/am/KeyguardController.java | 8 +++++ .../android/server/am/ActivityStackTests.java | 36 +++++++++++++++++++ .../android/server/am/ActivityTestsBase.java | 2 ++ 4 files changed, 54 insertions(+) diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java index 2c4eac0e391b5..377d574c5febc 100644 --- a/services/core/java/com/android/server/am/ActivityStack.java +++ b/services/core/java/com/android/server/am/ActivityStack.java @@ -5283,6 +5283,14 @@ class ActivityStack extends ConfigurationContai boolean shouldSleepActivities() { final ActivityDisplay display = getDisplay(); + + // Do not sleep activities in this stack if we're marked as focused and the keyguard + // is in the process of going away. + if (mStackSupervisor.getFocusedStack() == this + && mStackSupervisor.getKeyguardController().isKeyguardGoingAway()) { + return false; + } + return display != null ? display.isSleeping() : mService.isSleepingLocked(); } diff --git a/services/core/java/com/android/server/am/KeyguardController.java b/services/core/java/com/android/server/am/KeyguardController.java index 72882de21e097..0d7eab626ff00 100644 --- a/services/core/java/com/android/server/am/KeyguardController.java +++ b/services/core/java/com/android/server/am/KeyguardController.java @@ -97,6 +97,14 @@ class KeyguardController { return mKeyguardShowing && !mKeyguardGoingAway; } + /** + * @return {@code true} if the keyguard is going away, {@code false} otherwise. + */ + boolean isKeyguardGoingAway() { + // Also check keyguard showing in case value is stale. + return mKeyguardGoingAway && mKeyguardShowing; + } + /** * Update the Keyguard showing state. */ diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityStackTests.java b/services/tests/servicestests/src/com/android/server/am/ActivityStackTests.java index f17bfa456c882..1a95fdd0b62c6 100644 --- a/services/tests/servicestests/src/com/android/server/am/ActivityStackTests.java +++ b/services/tests/servicestests/src/com/android/server/am/ActivityStackTests.java @@ -37,12 +37,15 @@ import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.anyInt; +import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import android.app.servertransaction.DestroyActivityItem; import android.content.pm.ActivityInfo; +import android.os.Debug; import android.os.UserHandle; import android.platform.test.annotations.Presubmit; import android.support.test.filters.SmallTest; @@ -518,4 +521,37 @@ public class ActivityStackTests extends ActivityTestsBase { assertTrue(mTask.mActivities.isEmpty()); assertTrue(mStack.getAllTasks().isEmpty()); } + + @Test + public void testShouldSleepActivities() throws Exception { + // When focused activity and keyguard is going away, we should not sleep regardless + // of the display state + verifyShouldSleepActivities(true /* focusedStack */, true /*keyguardGoingAway*/, + true /* displaySleeping */, false /* expected*/); + + // When not the focused stack, defer to display sleeping state. + verifyShouldSleepActivities(false /* focusedStack */, true /*keyguardGoingAway*/, + true /* displaySleeping */, true /* expected*/); + + // If keyguard is going away, defer to the display sleeping state. + verifyShouldSleepActivities(true /* focusedStack */, false /*keyguardGoingAway*/, + true /* displaySleeping */, true /* expected*/); + verifyShouldSleepActivities(true /* focusedStack */, false /*keyguardGoingAway*/, + false /* displaySleeping */, false /* expected*/); + } + + private void verifyShouldSleepActivities(boolean focusedStack, + boolean keyguardGoingAway, boolean displaySleeping, boolean expected) { + mSupervisor.mFocusedStack = focusedStack ? mStack : null; + + final ActivityDisplay display = mock(ActivityDisplay.class); + final KeyguardController keyguardController = mSupervisor.getKeyguardController(); + + doReturn(display).when(mSupervisor).getActivityDisplay(anyInt()); + doReturn(keyguardGoingAway).when(keyguardController).isKeyguardGoingAway(); + doReturn(displaySleeping).when(display).isSleeping(); + + assertEquals(expected, mStack.shouldSleepActivities()); + } + } diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java b/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java index 3041a5f2cd556..c130592b4cd35 100644 --- a/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java +++ b/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java @@ -316,6 +316,7 @@ public class ActivityTestsBase { @Override final protected ActivityStackSupervisor createStackSupervisor() { final ActivityStackSupervisor supervisor = spy(createTestSupervisor()); + final KeyguardController keyguardController = mock(KeyguardController.class); // No home stack is set. doNothing().when(supervisor).moveHomeStackToFront(any()); @@ -330,6 +331,7 @@ public class ActivityTestsBase { doNothing().when(supervisor).scheduleIdleTimeoutLocked(any()); // unit test version does not handle launch wake lock doNothing().when(supervisor).acquireLaunchWakelock(); + doReturn(keyguardController).when(supervisor).getKeyguardController(); supervisor.initialize();