Move container focusability logic to ActivityStackSupervisor.

A number of factors are considered across the container hierarchy
when determining whether the container can be focused. Previously,
windowing mode consideration was added to the activity record, but
not stack. This led to inconsistent behavior when queried.

This changelist combines the logic and moves it to
ActivityStackSupervisor, where it can be invoked by any container.

Change-Id: I0d16faa069fd05500d39cd1619de9f8c488daa25
Fixes: 77708107
Test: atest FrameworksServicesTests:com.android.server.am.ActivityStackSupervisorTests#testFocusability
Test: atest CtsActivityManagerDeviceTestCases:android.server.am.lifecycle.ActivityLifecycleTests#testPausedWhenRestartedFromInNonFocusedStack
This commit is contained in:
Bryce Lee
2018-04-10 14:53:13 -07:00
parent cfa439f02f
commit 7b851cc7ff
4 changed files with 52 additions and 10 deletions

View File

@@ -1198,10 +1198,7 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo
}
boolean isFocusable() {
if (inSplitScreenPrimaryWindowingMode() && mStackSupervisor.mIsDockMinimized) {
return false;
}
return getWindowConfiguration().canReceiveKeys() || isAlwaysFocusable();
return mStackSupervisor.isFocusable(this, isAlwaysFocusable());
}
boolean isResizeable() {

View File

@@ -1077,13 +1077,8 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
}
boolean isFocusable() {
if (getWindowConfiguration().canReceiveKeys()) {
return true;
}
// The stack isn't focusable. See if its top activity is focusable to force focus on the
// stack.
final ActivityRecord r = topRunningActivityLocked();
return r != null && r.isFocusable();
return mStackSupervisor.isFocusable(this, r != null && r.isFocusable());
}
final boolean isAttached() {

View File

@@ -667,6 +667,14 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
return mFocusedStack;
}
boolean isFocusable(ConfigurationContainer container, boolean alwaysFocusable) {
if (container.inSplitScreenPrimaryWindowingMode() && mIsDockMinimized) {
return false;
}
return container.getWindowConfiguration().canReceiveKeys() || alwaysFocusable;
}
ActivityStack getLastStack() {
return mLastFocusedStack;
}

View File

@@ -23,6 +23,9 @@ import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
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 com.android.server.am.ActivityStack.REMOVE_TASK_MODE_DESTROYING;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
@@ -287,4 +290,43 @@ public class ActivityStackSupervisorTests extends ActivityTestsBase {
// Verify that the stack was removed.
assertEquals(originalStackCount, defaultDisplay.getChildCount());
}
@Test
public void testFocusability() throws Exception {
final ActivityStack stack = mService.mStackSupervisor.getDefaultDisplay().createStack(
WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, ACTIVITY_TYPE_STANDARD, true /* onTop */);
final ActivityRecord activity = new ActivityBuilder(mService).setCreateTask(true)
.setStack(stack).build();
// Under split screen primary we should be focusable when not minimized
mService.mStackSupervisor.setDockedStackMinimized(false);
assertTrue(stack.isFocusable());
assertTrue(activity.isFocusable());
// Under split screen primary we should not be focusable when minimized
mService.mStackSupervisor.setDockedStackMinimized(true);
assertFalse(stack.isFocusable());
assertFalse(activity.isFocusable());
final ActivityStack pinnedStack = mService.mStackSupervisor.getDefaultDisplay().createStack(
WINDOWING_MODE_PINNED, ACTIVITY_TYPE_STANDARD, true /* onTop */);
final ActivityRecord pinnedActivity = new ActivityBuilder(mService).setCreateTask(true)
.setStack(pinnedStack).build();
// We should not be focusable when in pinned mode
assertFalse(pinnedStack.isFocusable());
assertFalse(pinnedActivity.isFocusable());
// Add flag forcing focusability.
pinnedActivity.info.flags |= FLAG_ALWAYS_FOCUSABLE;
// We should not be focusable when in pinned mode
assertTrue(pinnedStack.isFocusable());
assertTrue(pinnedActivity.isFocusable());
// Without the overridding activity, stack should not be focusable.
pinnedStack.removeTask(pinnedActivity.getTask(), "testFocusability",
REMOVE_TASK_MODE_DESTROYING);
assertFalse(pinnedStack.isFocusable());
}
}