return STACK_INVISIBLE;
}
- final ActivityStack focusedStack = mStackSupervisor.getFocusedStack();
- final int focusedStackId = focusedStack.mStackId;
+ // Check position and visibility of this stack relative to the front stack on its display.
+ final ActivityStack topStack = getTopStackOnDisplay();
+ final int topStackId = topStack.mStackId;
if (StackId.isBackdropToTranslucentActivity(mStackId)
- && hasVisibleBehindActivity() && StackId.isHomeOrRecentsStack(focusedStackId)
- && !focusedStack.topActivity().fullscreen) {
+ && hasVisibleBehindActivity() && StackId.isHomeOrRecentsStack(topStackId)
+ && !topStack.topActivity().fullscreen) {
// The fullscreen or assistant stack should be visible if it has a visible behind
// activity behind the home or recents stack that is translucent.
return STACK_VISIBLE_ACTIVITY_BEHIND;
// Docked stack is always visible, except in the case where the top running activity
// task in the focus stack doesn't support any form of resizing but we show it for the
// home task even though it's not resizable.
- final ActivityRecord r = focusedStack.topRunningActivityLocked();
+ final ActivityRecord r = topStack.topRunningActivityLocked();
final TaskRecord task = r != null ? r.task : null;
return task == null || task.supportsSplitScreen() || task.isHomeTask() ? STACK_VISIBLE
: STACK_INVISIBLE;
}
- // Find the first stack behind focused stack that actually got something visible.
- int stackBehindFocusedIndex = mStacks.indexOf(focusedStack) - 1;
- while (stackBehindFocusedIndex >= 0 &&
- mStacks.get(stackBehindFocusedIndex).topRunningActivityLocked() == null) {
- stackBehindFocusedIndex--;
+ // Find the first stack behind front stack that actually got something visible.
+ int stackBehindTopIndex = mStacks.indexOf(topStack) - 1;
+ while (stackBehindTopIndex >= 0 &&
+ mStacks.get(stackBehindTopIndex).topRunningActivityLocked() == null) {
+ stackBehindTopIndex--;
}
- if ((focusedStackId == DOCKED_STACK_ID || focusedStackId == PINNED_STACK_ID)
- && stackIndex == stackBehindFocusedIndex) {
+ if ((topStackId == DOCKED_STACK_ID || topStackId == PINNED_STACK_ID)
+ && stackIndex == stackBehindTopIndex) {
// Stacks directly behind the docked or pinned stack are always visible.
return STACK_VISIBLE;
}
- final int stackBehindFocusedId = (stackBehindFocusedIndex >= 0)
- ? mStacks.get(stackBehindFocusedIndex).mStackId : INVALID_STACK_ID;
+ final int stackBehindTopId = (stackBehindTopIndex >= 0)
+ ? mStacks.get(stackBehindTopIndex).mStackId : INVALID_STACK_ID;
- if (StackId.isBackdropToTranslucentActivity(focusedStackId)
- && focusedStack.isStackTranslucent(starting, stackBehindFocusedId)) {
+ if (StackId.isBackdropToTranslucentActivity(topStackId)
+ && topStack.isStackTranslucent(starting, stackBehindTopId)) {
// Stacks behind the fullscreen or assistant stack with a translucent activity are
// always visible so they can act as a backdrop to the translucent activity.
// For example, dialog activities
- if (stackIndex == stackBehindFocusedIndex) {
+ if (stackIndex == stackBehindTopIndex) {
return STACK_VISIBLE;
}
- if (stackBehindFocusedIndex >= 0) {
- if ((stackBehindFocusedId == DOCKED_STACK_ID
- || stackBehindFocusedId == PINNED_STACK_ID)
- && stackIndex == (stackBehindFocusedIndex - 1)) {
+ if (stackBehindTopIndex >= 0) {
+ if ((stackBehindTopId == DOCKED_STACK_ID
+ || stackBehindTopId == PINNED_STACK_ID)
+ && stackIndex == (stackBehindTopIndex - 1)) {
// The stack behind the docked or pinned stack is also visible so we can have a
// complete backdrop to the translucent activity when the docked stack is up.
return STACK_VISIBLE;
AppTimeTracker timeTracker, String reason) {
if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "moveTaskToFront: " + tr);
- final ActivityRecord focusedTopActivity = mStackSupervisor.getFocusedStack() != null
- ? mStackSupervisor.getFocusedStack().topActivity() : null;
+ final ActivityStack topStack = getTopStackOnDisplay();
+ final ActivityRecord topActivity = topStack != null ? topStack.topActivity() : null;
final int numTasks = mTaskHistory.size();
final int index = mTaskHistory.indexOf(tr);
if (numTasks == 0 || index < 0) {
insertTaskAtTop(tr, null);
// Don't refocus if invisible to current user
- ActivityRecord top = tr.getTopActivity();
+ final ActivityRecord top = tr.getTopActivity();
if (top == null || !top.okToShowLocked()) {
addRecentActivityLocked(top);
ActivityOptions.abort(options);
}
// Set focus to the top running activity of this stack.
- ActivityRecord r = topRunningActivityLocked();
+ final ActivityRecord r = topRunningActivityLocked();
mStackSupervisor.moveFocusableActivityStackToFrontLocked(r, reason);
if (DEBUG_TRANSITION) Slog.v(TAG_TRANSITION, "Prepare to front transition: task=" + tr);
}
// If a new task is moved to the front, then mark the existing top activity as supporting
// picture-in-picture while paused
- if (focusedTopActivity != null) {
- focusedTopActivity.supportsPictureInPictureWhilePausing = true;
+ if (topActivity != null) {
+ topActivity.supportsPictureInPictureWhilePausing = true;
}
mStackSupervisor.resumeFocusedStackTopActivityLocked();
return true;
}
+ /**
+ * Get the topmost stack on the current display. It may be different from focused stack, because
+ * focus may be on another display.
+ */
+ private ActivityStack getTopStackOnDisplay() {
+ final ArrayList<ActivityStack> stacks = mActivityContainer.mActivityDisplay.mStacks;
+ return stacks.isEmpty() ? null : stacks.get(stacks.size() - 1);
+ }
+
static void logStartActivity(int tag, ActivityRecord r, TaskRecord task) {
final Uri data = r.intent.getData();
final String strData = data != null ? data.toSafeString() : null;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
+import java.util.Objects;
import java.util.Set;
public class ActivityStackSupervisor extends ConfigurationContainer implements DisplayListener {
stack.prepareFreezingTaskBounds();
// Make sure the task has the appropriate bounds/size for the stack it is in.
- if (stackId == FULLSCREEN_WORKSPACE_STACK_ID && task.mBounds != null) {
+ if (stackId == FULLSCREEN_WORKSPACE_STACK_ID
+ && !Objects.equals(task.mBounds, stack.mBounds)) {
kept = task.resize(stack.mBounds, RESIZE_MODE_SYSTEM, !mightReplaceWindow,
deferResume);
} else if (stackId == FREEFORM_WORKSPACE_STACK_ID) {
mService.mTaskChangeNotificationController.notifyActivityPinned();
}
+ /** Move activity with its stack to front and make the stack focused. */
boolean moveFocusableActivityStackToFrontLocked(ActivityRecord r, String reason) {
if (r == null || !r.isFocusable()) {
if (DEBUG_FOCUS) Slog.d(TAG_FOCUS,
* @return a list of activities which are the top ones in each visible stack. The first
* entry will be the focused activity.
*/
- public List<IBinder> getTopVisibleActivities() {
- // TODO(multi-display): Get rid of DEFAULT_DISPLAY here. Used in
- // VoiceInteractionManagerServiceImpl#showSessionLocked.
- final ActivityDisplay display = mActivityDisplays.get(DEFAULT_DISPLAY);
- if (display == null) {
- return Collections.EMPTY_LIST;
- }
- ArrayList<IBinder> topActivityTokens = new ArrayList<>();
- final ArrayList<ActivityStack> stacks = display.mStacks;
- for (int i = stacks.size() - 1; i >= 0; i--) {
- ActivityStack stack = stacks.get(i);
- if (stack.getStackVisibilityLocked(null) == ActivityStack.STACK_VISIBLE) {
- ActivityRecord top = stack.topActivity();
- if (top != null) {
- if (stack == mFocusedStack) {
- topActivityTokens.add(0, top.appToken);
- } else {
- topActivityTokens.add(top.appToken);
+ List<IBinder> getTopVisibleActivities() {
+ final ArrayList<IBinder> topActivityTokens = new ArrayList<>();
+ // Traverse all displays.
+ for (int i = mActivityDisplays.size(); i >= 0; i--) {
+ final ActivityDisplay display = mActivityDisplays.valueAt(i);
+ // Traverse all stacks on a display.
+ for (int j = display.mStacks.size() - 1; j >= 0; j--) {
+ final ActivityStack stack = display.mStacks.get(j);
+ // Get top activity from a visible stack and add it to the list.
+ if (stack.getStackVisibilityLocked(null /* starting */)
+ == ActivityStack.STACK_VISIBLE) {
+ final ActivityRecord top = stack.topActivity();
+ if (top != null) {
+ if (stack == mFocusedStack) {
+ topActivityTokens.add(0, top.appToken);
+ } else {
+ topActivityTokens.add(top.appToken);
+ }
}
}
}