Merge "Consider lock state when determining next activity to become visible." into pi-dev

am: 00f4a4bc74

Change-Id: Ied73f5090e5c790c884d817ac57399d70952ff6f
This commit is contained in:
Bryce Lee
2018-04-23 07:27:54 -07:00
committed by android-build-merger
4 changed files with 99 additions and 9 deletions

View File

@@ -3802,7 +3802,11 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
// and the resumed activity is not yet visible, then hold off on
// 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)
&& next != null && !next.nowVisible) {

View File

@@ -1210,6 +1210,18 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
}
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;
ActivityRecord r = focusedStack.topRunningActivityLocked();
if (r != null) {
@@ -1228,16 +1240,33 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
if (display == null) {
continue;
}
for (int j = display.getChildCount() - 1; j >= 0; --j) {
final ActivityStack stack = display.getChildAt(j);
if (stack != focusedStack && stack.isTopStackOnDisplay() && stack.isFocusable()) {
r = stack.topRunningActivityLocked();
if (r != null) {
return r;
}
}
// TODO: We probably want to consider the top fullscreen stack as we could have a pinned
// stack on top.
final ActivityStack topStack = display.getTopStack();
// 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;
}

View File

@@ -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.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 org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
@@ -329,4 +330,52 @@ public class ActivityStackSupervisorTests extends ActivityTestsBase {
REMOVE_TASK_MODE_DESTROYING);
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 */));
}
}

View File

@@ -132,6 +132,7 @@ public class ActivityTestsBase {
private int mUid;
private boolean mCreateTask;
private ActivityStack mStack;
private int mActivityFlags;
ActivityBuilder(ActivityManagerService service) {
mService = service;
@@ -152,6 +153,11 @@ public class ActivityTestsBase {
return this;
}
ActivityBuilder setActivityFlags(int flags) {
mActivityFlags = flags;
return this;
}
ActivityBuilder setStack(ActivityStack stack) {
mStack = stack;
return this;
@@ -186,6 +192,8 @@ public class ActivityTestsBase {
aInfo.applicationInfo = new ApplicationInfo();
aInfo.applicationInfo.packageName = mComponent.getPackageName();
aInfo.applicationInfo.uid = mUid;
aInfo.flags |= mActivityFlags;
final ActivityRecord activity = new ActivityRecord(mService, null /* caller */,
0 /* launchedFromPid */, 0, null, intent, null,
aInfo /*aInfo*/, new Configuration(), null /* resultTo */, null /* resultWho */,