From 7b851cc7ff58ced18bc79d4ffc2e20d7e9964c41 Mon Sep 17 00:00:00 2001 From: Bryce Lee Date: Tue, 10 Apr 2018 14:53:13 -0700 Subject: [PATCH] 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 --- .../com/android/server/am/ActivityRecord.java | 5 +-- .../com/android/server/am/ActivityStack.java | 7 +--- .../server/am/ActivityStackSupervisor.java | 8 ++++ .../am/ActivityStackSupervisorTests.java | 42 +++++++++++++++++++ 4 files changed, 52 insertions(+), 10 deletions(-) diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java index e539bf8035424..eb7e9c8f6d424 100644 --- a/services/core/java/com/android/server/am/ActivityRecord.java +++ b/services/core/java/com/android/server/am/ActivityRecord.java @@ -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() { diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java index 649d5770f6a9b..d7136bf6017a7 100644 --- a/services/core/java/com/android/server/am/ActivityStack.java +++ b/services/core/java/com/android/server/am/ActivityStack.java @@ -1077,13 +1077,8 @@ class ActivityStack 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() { diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java index e9a13585d8fb5..52b0edc8de2d3 100644 --- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java +++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java @@ -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; } diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityStackSupervisorTests.java b/services/tests/servicestests/src/com/android/server/am/ActivityStackSupervisorTests.java index 9663a1b58686a..08b8af289bd82 100644 --- a/services/tests/servicestests/src/com/android/server/am/ActivityStackSupervisorTests.java +++ b/services/tests/servicestests/src/com/android/server/am/ActivityStackSupervisorTests.java @@ -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()); + } }