Loading services/core/java/com/android/server/am/ActivityStack.java +5 −1 Original line number Original line Diff line number Diff line Loading @@ -3802,7 +3802,11 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai // and the resumed activity is not yet visible, then hold off on // and the resumed activity is not yet visible, then hold off on // finishing until the resumed one becomes visible. // finishing until the resumed one becomes visible. final ActivityRecord next = mStackSupervisor.topRunningActivityLocked(); // The activity that we are finishing may be over the lock screen. In this case, we do not // want to consider activities that cannot be shown on the lock screen as running and should // proceed with finishing the activity if there is no valid next top running activity. final ActivityRecord next = mStackSupervisor.topRunningActivityLocked( true /* considerKeyguardState */); if (mode == FINISH_AFTER_VISIBLE && (r.visible || r.nowVisible) if (mode == FINISH_AFTER_VISIBLE && (r.visible || r.nowVisible) && next != null && !next.nowVisible) { && next != null && !next.nowVisible) { Loading services/core/java/com/android/server/am/ActivityStackSupervisor.java +37 −8 Original line number Original line Diff line number Diff line Loading @@ -1210,6 +1210,18 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D } } ActivityRecord topRunningActivityLocked() { ActivityRecord topRunningActivityLocked() { return topRunningActivityLocked(false /* considerKeyguardState */); } /** * Returns the top running activity in the focused stack. In the case the focused stack has no * such activity, the next focusable stack on top of a display is returned. * @param considerKeyguardState Indicates whether the locked state should be considered. if * {@code true} and the keyguard is locked, only activities that * can be shown on top of the keyguard will be considered. * @return The top running activity. {@code null} if none is available. */ ActivityRecord topRunningActivityLocked(boolean considerKeyguardState) { final ActivityStack focusedStack = mFocusedStack; final ActivityStack focusedStack = mFocusedStack; ActivityRecord r = focusedStack.topRunningActivityLocked(); ActivityRecord r = focusedStack.topRunningActivityLocked(); if (r != null) { if (r != null) { Loading @@ -1228,16 +1240,33 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D if (display == null) { if (display == null) { continue; continue; } } for (int j = display.getChildCount() - 1; j >= 0; --j) { final ActivityStack stack = display.getChildAt(j); // TODO: We probably want to consider the top fullscreen stack as we could have a pinned if (stack != focusedStack && stack.isTopStackOnDisplay() && stack.isFocusable()) { // stack on top. r = stack.topRunningActivityLocked(); final ActivityStack topStack = display.getTopStack(); if (r != null) { return r; // Only consider focusable top stacks other than the current focused one. if (topStack == null || !topStack.isFocusable() || topStack == focusedStack) { continue; } } final ActivityRecord topActivity = topStack.topRunningActivityLocked(); // Skip if no top activity. if (topActivity == null) { continue; } } final boolean keyguardLocked = getKeyguardController().isKeyguardLocked(); // This activity can be considered the top running activity if we are not // considering the locked state, the keyguard isn't locked, or we can show when // locked. if (!considerKeyguardState || !keyguardLocked || topActivity.canShowWhenLocked()) { return topActivity; } } } } return null; return null; } } Loading services/tests/servicestests/src/com/android/server/am/ActivityStackSupervisorTests.java +49 −0 Original line number Original line Diff line number Diff line Loading @@ -25,6 +25,7 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED; import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY; import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY; import static android.content.pm.ActivityInfo.FLAG_ALWAYS_FOCUSABLE; import static android.content.pm.ActivityInfo.FLAG_ALWAYS_FOCUSABLE; import static android.content.pm.ActivityInfo.FLAG_SHOW_WHEN_LOCKED; import static com.android.server.am.ActivityStack.REMOVE_TASK_MODE_DESTROYING; import static com.android.server.am.ActivityStack.REMOVE_TASK_MODE_DESTROYING; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertNull; Loading Loading @@ -329,4 +330,52 @@ public class ActivityStackSupervisorTests extends ActivityTestsBase { REMOVE_TASK_MODE_DESTROYING); REMOVE_TASK_MODE_DESTROYING); assertFalse(pinnedStack.isFocusable()); assertFalse(pinnedStack.isFocusable()); } } /** * Verifies the correct activity is returned when querying the top running activity with an * empty focused stack. */ @Test public void testNonFocusedTopRunningActivity() throws Exception { // Create stack to hold focus final ActivityStack focusedStack = mService.mStackSupervisor.getDefaultDisplay() .createStack(WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */); final KeyguardController keyguard = mSupervisor.getKeyguardController(); final ActivityStack stack = mService.mStackSupervisor.getDefaultDisplay().createStack( WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */); final ActivityRecord activity = new ActivityBuilder(mService).setCreateTask(true) .setStack(stack).build(); mSupervisor.mFocusedStack = focusedStack; doAnswer((InvocationOnMock invocationOnMock) -> { final SparseIntArray displayIds = invocationOnMock.<SparseIntArray>getArgument(0); displayIds.put(0, mSupervisor.getDefaultDisplay().mDisplayId); return null; }).when(mSupervisor.mWindowManager).getDisplaysInFocusOrder(any()); // Make sure the top running activity is not affected when keyguard is not locked assertEquals(activity, mService.mStackSupervisor.topRunningActivityLocked()); assertEquals(activity, mService.mStackSupervisor.topRunningActivityLocked( true /* considerKeyguardState */)); // Check to make sure activity not reported when it cannot show on lock and lock is on. doReturn(true).when(keyguard).isKeyguardLocked(); assertEquals(activity, mService.mStackSupervisor.topRunningActivityLocked()); assertEquals(null, mService.mStackSupervisor.topRunningActivityLocked( true /* considerKeyguardState */)); // Add activity that should be shown on the keyguard. final ActivityRecord showWhenLockedActivity = new ActivityBuilder(mService) .setCreateTask(true) .setStack(stack) .setActivityFlags(FLAG_SHOW_WHEN_LOCKED) .build(); // Ensure the show when locked activity is returned. assertEquals(showWhenLockedActivity, mService.mStackSupervisor.topRunningActivityLocked()); assertEquals(showWhenLockedActivity, mService.mStackSupervisor.topRunningActivityLocked( true /* considerKeyguardState */)); } } } services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java +8 −0 Original line number Original line Diff line number Diff line Loading @@ -132,6 +132,7 @@ public class ActivityTestsBase { private int mUid; private int mUid; private boolean mCreateTask; private boolean mCreateTask; private ActivityStack mStack; private ActivityStack mStack; private int mActivityFlags; ActivityBuilder(ActivityManagerService service) { ActivityBuilder(ActivityManagerService service) { mService = service; mService = service; Loading @@ -152,6 +153,11 @@ public class ActivityTestsBase { return this; return this; } } ActivityBuilder setActivityFlags(int flags) { mActivityFlags = flags; return this; } ActivityBuilder setStack(ActivityStack stack) { ActivityBuilder setStack(ActivityStack stack) { mStack = stack; mStack = stack; return this; return this; Loading Loading @@ -186,6 +192,8 @@ public class ActivityTestsBase { aInfo.applicationInfo = new ApplicationInfo(); aInfo.applicationInfo = new ApplicationInfo(); aInfo.applicationInfo.packageName = mComponent.getPackageName(); aInfo.applicationInfo.packageName = mComponent.getPackageName(); aInfo.applicationInfo.uid = mUid; aInfo.applicationInfo.uid = mUid; aInfo.flags |= mActivityFlags; final ActivityRecord activity = new ActivityRecord(mService, null /* caller */, final ActivityRecord activity = new ActivityRecord(mService, null /* caller */, 0 /* launchedFromPid */, 0, null, intent, null, 0 /* launchedFromPid */, 0, null, intent, null, aInfo /*aInfo*/, new Configuration(), null /* resultTo */, null /* resultWho */, aInfo /*aInfo*/, new Configuration(), null /* resultTo */, null /* resultWho */, Loading Loading
services/core/java/com/android/server/am/ActivityStack.java +5 −1 Original line number Original line Diff line number Diff line Loading @@ -3802,7 +3802,11 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai // and the resumed activity is not yet visible, then hold off on // and the resumed activity is not yet visible, then hold off on // finishing until the resumed one becomes visible. // finishing until the resumed one becomes visible. final ActivityRecord next = mStackSupervisor.topRunningActivityLocked(); // The activity that we are finishing may be over the lock screen. In this case, we do not // want to consider activities that cannot be shown on the lock screen as running and should // proceed with finishing the activity if there is no valid next top running activity. final ActivityRecord next = mStackSupervisor.topRunningActivityLocked( true /* considerKeyguardState */); if (mode == FINISH_AFTER_VISIBLE && (r.visible || r.nowVisible) if (mode == FINISH_AFTER_VISIBLE && (r.visible || r.nowVisible) && next != null && !next.nowVisible) { && next != null && !next.nowVisible) { Loading
services/core/java/com/android/server/am/ActivityStackSupervisor.java +37 −8 Original line number Original line Diff line number Diff line Loading @@ -1210,6 +1210,18 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D } } ActivityRecord topRunningActivityLocked() { ActivityRecord topRunningActivityLocked() { return topRunningActivityLocked(false /* considerKeyguardState */); } /** * Returns the top running activity in the focused stack. In the case the focused stack has no * such activity, the next focusable stack on top of a display is returned. * @param considerKeyguardState Indicates whether the locked state should be considered. if * {@code true} and the keyguard is locked, only activities that * can be shown on top of the keyguard will be considered. * @return The top running activity. {@code null} if none is available. */ ActivityRecord topRunningActivityLocked(boolean considerKeyguardState) { final ActivityStack focusedStack = mFocusedStack; final ActivityStack focusedStack = mFocusedStack; ActivityRecord r = focusedStack.topRunningActivityLocked(); ActivityRecord r = focusedStack.topRunningActivityLocked(); if (r != null) { if (r != null) { Loading @@ -1228,16 +1240,33 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D if (display == null) { if (display == null) { continue; continue; } } for (int j = display.getChildCount() - 1; j >= 0; --j) { final ActivityStack stack = display.getChildAt(j); // TODO: We probably want to consider the top fullscreen stack as we could have a pinned if (stack != focusedStack && stack.isTopStackOnDisplay() && stack.isFocusable()) { // stack on top. r = stack.topRunningActivityLocked(); final ActivityStack topStack = display.getTopStack(); if (r != null) { return r; // Only consider focusable top stacks other than the current focused one. if (topStack == null || !topStack.isFocusable() || topStack == focusedStack) { continue; } } final ActivityRecord topActivity = topStack.topRunningActivityLocked(); // Skip if no top activity. if (topActivity == null) { continue; } } final boolean keyguardLocked = getKeyguardController().isKeyguardLocked(); // This activity can be considered the top running activity if we are not // considering the locked state, the keyguard isn't locked, or we can show when // locked. if (!considerKeyguardState || !keyguardLocked || topActivity.canShowWhenLocked()) { return topActivity; } } } } return null; return null; } } Loading
services/tests/servicestests/src/com/android/server/am/ActivityStackSupervisorTests.java +49 −0 Original line number Original line Diff line number Diff line Loading @@ -25,6 +25,7 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED; import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY; import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY; import static android.content.pm.ActivityInfo.FLAG_ALWAYS_FOCUSABLE; import static android.content.pm.ActivityInfo.FLAG_ALWAYS_FOCUSABLE; import static android.content.pm.ActivityInfo.FLAG_SHOW_WHEN_LOCKED; import static com.android.server.am.ActivityStack.REMOVE_TASK_MODE_DESTROYING; import static com.android.server.am.ActivityStack.REMOVE_TASK_MODE_DESTROYING; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertNull; Loading Loading @@ -329,4 +330,52 @@ public class ActivityStackSupervisorTests extends ActivityTestsBase { REMOVE_TASK_MODE_DESTROYING); REMOVE_TASK_MODE_DESTROYING); assertFalse(pinnedStack.isFocusable()); assertFalse(pinnedStack.isFocusable()); } } /** * Verifies the correct activity is returned when querying the top running activity with an * empty focused stack. */ @Test public void testNonFocusedTopRunningActivity() throws Exception { // Create stack to hold focus final ActivityStack focusedStack = mService.mStackSupervisor.getDefaultDisplay() .createStack(WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */); final KeyguardController keyguard = mSupervisor.getKeyguardController(); final ActivityStack stack = mService.mStackSupervisor.getDefaultDisplay().createStack( WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */); final ActivityRecord activity = new ActivityBuilder(mService).setCreateTask(true) .setStack(stack).build(); mSupervisor.mFocusedStack = focusedStack; doAnswer((InvocationOnMock invocationOnMock) -> { final SparseIntArray displayIds = invocationOnMock.<SparseIntArray>getArgument(0); displayIds.put(0, mSupervisor.getDefaultDisplay().mDisplayId); return null; }).when(mSupervisor.mWindowManager).getDisplaysInFocusOrder(any()); // Make sure the top running activity is not affected when keyguard is not locked assertEquals(activity, mService.mStackSupervisor.topRunningActivityLocked()); assertEquals(activity, mService.mStackSupervisor.topRunningActivityLocked( true /* considerKeyguardState */)); // Check to make sure activity not reported when it cannot show on lock and lock is on. doReturn(true).when(keyguard).isKeyguardLocked(); assertEquals(activity, mService.mStackSupervisor.topRunningActivityLocked()); assertEquals(null, mService.mStackSupervisor.topRunningActivityLocked( true /* considerKeyguardState */)); // Add activity that should be shown on the keyguard. final ActivityRecord showWhenLockedActivity = new ActivityBuilder(mService) .setCreateTask(true) .setStack(stack) .setActivityFlags(FLAG_SHOW_WHEN_LOCKED) .build(); // Ensure the show when locked activity is returned. assertEquals(showWhenLockedActivity, mService.mStackSupervisor.topRunningActivityLocked()); assertEquals(showWhenLockedActivity, mService.mStackSupervisor.topRunningActivityLocked( true /* considerKeyguardState */)); } } }
services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java +8 −0 Original line number Original line Diff line number Diff line Loading @@ -132,6 +132,7 @@ public class ActivityTestsBase { private int mUid; private int mUid; private boolean mCreateTask; private boolean mCreateTask; private ActivityStack mStack; private ActivityStack mStack; private int mActivityFlags; ActivityBuilder(ActivityManagerService service) { ActivityBuilder(ActivityManagerService service) { mService = service; mService = service; Loading @@ -152,6 +153,11 @@ public class ActivityTestsBase { return this; return this; } } ActivityBuilder setActivityFlags(int flags) { mActivityFlags = flags; return this; } ActivityBuilder setStack(ActivityStack stack) { ActivityBuilder setStack(ActivityStack stack) { mStack = stack; mStack = stack; return this; return this; Loading Loading @@ -186,6 +192,8 @@ public class ActivityTestsBase { aInfo.applicationInfo = new ApplicationInfo(); aInfo.applicationInfo = new ApplicationInfo(); aInfo.applicationInfo.packageName = mComponent.getPackageName(); aInfo.applicationInfo.packageName = mComponent.getPackageName(); aInfo.applicationInfo.uid = mUid; aInfo.applicationInfo.uid = mUid; aInfo.flags |= mActivityFlags; final ActivityRecord activity = new ActivityRecord(mService, null /* caller */, final ActivityRecord activity = new ActivityRecord(mService, null /* caller */, 0 /* launchedFromPid */, 0, null, intent, null, 0 /* launchedFromPid */, 0, null, intent, null, aInfo /*aInfo*/, new Configuration(), null /* resultTo */, null /* resultWho */, aInfo /*aInfo*/, new Configuration(), null /* resultTo */, null /* resultWho */, Loading