Don't allow unfocusable activity/stack to gain focus
Prevents them from being resumed since we always want to resumed
activity to be a focusable acitvity.
Bug: 26273032
Change-Id: Ied832e100d9a2d8915762db53c9230774be21d1c
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 8e64eeb..444450c 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -2748,6 +2748,12 @@
return false;
}
+ if (!r.isFocusable()) {
+ if (DEBUG_FOCUS) Slog.d(TAG_FOCUS,
+ "setFocusedActivityLocked: unfocusable r=" + r);
+ return false;
+ }
+
if (DEBUG_FOCUS) Slog.d(TAG_FOCUS, "setFocusedActivityLocked: r=" + r);
final ActivityRecord last = mFocusedActivity;
mFocusedActivity = r;
diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java
index 4d9120b..f0df0c4 100755
--- a/services/core/java/com/android/server/am/ActivityRecord.java
+++ b/services/core/java/com/android/server/am/ActivityRecord.java
@@ -16,6 +16,7 @@
package com.android.server.am;
+import static android.app.ActivityManager.StackId;
import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_CONFIGURATION;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_SAVED_STATE;
@@ -739,6 +740,10 @@
(intent.getFlags() & Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) == 0);
}
+ boolean isFocusable() {
+ return StackId.canReceiveKeys(task.stack.mStackId);
+ }
+
void makeFinishingLocked() {
if (!finishing) {
if (task != null && task.stack != null
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index b9ff32c..9a6a7f7 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -560,7 +560,7 @@
// TODO(multi-display): Needs to also work if focus is moving to the non-home display.
if (isOnHomeDisplay()) {
- mStackSupervisor.setFocusStack(reason, this);
+ mStackSupervisor.setFocusStackUnchecked(reason, this);
}
if (task != null) {
insertTaskAtTop(task, null);
@@ -573,7 +573,13 @@
}
boolean isFocusable() {
- return StackId.canReceiveKeys(mStackId);
+ if (StackId.canReceiveKeys(mStackId)) {
+ 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();
}
final boolean isAttached() {
@@ -1299,7 +1305,7 @@
return null;
}
- private ActivityStack getNextVisibleStackLocked() {
+ ActivityStack getNextFocusableStackLocked() {
ArrayList<ActivityStack> stacks = mStacks;
final ActivityRecord parent = mActivityContainer.mParentActivity;
if (parent != null) {
@@ -1308,7 +1314,7 @@
if (stacks != null) {
for (int i = stacks.size() - 1; i >= 0; --i) {
ActivityStack stack = stacks.get(i);
- if (stack != this && stack.isStackVisibleLocked()) {
+ if (stack != this && stack.isFocusable() && stack.isStackVisibleLocked()) {
return stack;
}
}
@@ -1836,14 +1842,13 @@
if (next == null) {
// There are no more activities!
final String reason = "noMoreActivities";
- if (!mFullscreen) {
+ if (!mFullscreen && adjustFocusToNextFocusableStackLocked(reason)) {
// Try to move focus to the next visible stack with a running activity if this
// stack is not covering the entire screen.
- final ActivityStack stack = getNextVisibleStackLocked();
- if (adjustFocusToNextVisibleStackLocked(stack, reason)) {
- return mStackSupervisor.resumeFocusedStackTopActivityLocked(stack, prev, null);
- }
+ return mStackSupervisor.resumeFocusedStackTopActivityLocked(
+ mStackSupervisor.getFocusedStack(), prev, null);
}
+
// Let's just start up the Launcher...
ActivityOptions.abort(options);
if (DEBUG_STATES) Slog.d(TAG_STATES,
@@ -2875,7 +2880,7 @@
final ActivityRecord next = topRunningActivityLocked();
final String myReason = reason + " adjustFocus";
if (next != r) {
- if (next != null && StackId.keepFocusInStackIfPossible(mStackId)) {
+ if (next != null && StackId.keepFocusInStackIfPossible(mStackId) && isFocusable()) {
// For freeform, docked, and pinned stacks we always keep the focus within the
// stack as long as there is a running activity in the stack that we can adjust
// focus to.
@@ -2887,8 +2892,7 @@
// For non-fullscreen stack, we want to move the focus to the next visible
// stack to prevent the home screen from moving to the top and obscuring
// other visible stacks.
- if (!mFullscreen
- && adjustFocusToNextVisibleStackLocked(null, myReason)) {
+ if (!mFullscreen && adjustFocusToNextFocusableStackLocked(myReason)) {
return;
}
// Move the home stack to the top if this stack is fullscreen or there is no
@@ -2905,9 +2909,9 @@
mService.setFocusedActivityLocked(mStackSupervisor.topRunningActivityLocked(), myReason);
}
- private boolean adjustFocusToNextVisibleStackLocked(ActivityStack inStack, String reason) {
- final ActivityStack stack = (inStack != null) ? inStack : getNextVisibleStackLocked();
- final String myReason = reason + " adjustFocusToNextVisibleStack";
+ private boolean adjustFocusToNextFocusableStackLocked(String reason) {
+ final ActivityStack stack = getNextFocusableStackLocked();
+ final String myReason = reason + " adjustFocusToNextFocusableStack";
if (stack == null) {
return false;
}
@@ -4658,7 +4662,7 @@
// We only need to adjust focused stack if this stack is in focus.
if (isOnHomeDisplay() && mStackSupervisor.isFocusedStack(this)) {
String myReason = reason + " leftTaskHistoryEmpty";
- if (mFullscreen || !adjustFocusToNextVisibleStackLocked(null, myReason)) {
+ if (mFullscreen || !adjustFocusToNextFocusableStackLocked(myReason)) {
mStackSupervisor.moveHomeStackToFront(myReason);
}
}
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index df1aa52..688243d 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -492,8 +492,8 @@
calculateDefaultMinimalSizeOfResizeableTasks(activityDisplay);
}
- createStackOnDisplay(HOME_STACK_ID, Display.DEFAULT_DISPLAY, true);
- mHomeStack = mFocusedStack = mLastFocusedStack = getStack(HOME_STACK_ID);
+ mHomeStack = mFocusedStack = mLastFocusedStack =
+ getStack(HOME_STACK_ID, CREATE_IF_NEEDED, ON_TOP);
mInputManagerInternal = LocalServices.getService(InputManagerInternal.class);
}
@@ -538,10 +538,15 @@
}
/** NOTE: Should only be called from {@link ActivityStack#moveToFront} */
- void setFocusStack(String reason, ActivityStack focusedStack) {
- if (focusedStack != mFocusedStack) {
+ void setFocusStackUnchecked(String reason, ActivityStack focusCandidate) {
+ if (!focusCandidate.isFocusable()) {
+ // The focus candidate isn't focusable. Move focus to the top stack that is focusable.
+ focusCandidate = focusCandidate.getNextFocusableStackLocked();
+ }
+
+ if (focusCandidate != mFocusedStack) {
mLastFocusedStack = mFocusedStack;
- mFocusedStack = focusedStack;
+ mFocusedStack = focusCandidate;
EventLogTags.writeAmFocusedStack(
mCurrentUser, mFocusedStack == null ? -1 : mFocusedStack.getStackId(),
@@ -904,7 +909,7 @@
final ArrayList<ActivityStack> stacks = mHomeStack.mStacks;
for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
final ActivityStack stack = stacks.get(stackNdx);
- if (stack != focusedStack && isFrontStack(stack)) {
+ if (stack != focusedStack && isFrontStack(stack) && stack.isFocusable()) {
r = stack.topRunningActivityLocked();
if (r != null) {
return r;