diff options
author | 2015-10-28 13:36:10 -0700 | |
---|---|---|
committer | 2015-10-29 14:02:09 -0700 | |
commit | 1e60e0c61a3ec4b53aeae7fbe9c6da4d047a5d02 (patch) | |
tree | c309e761e079bcaa3c1b0327acf0eaf92815feae | |
parent | 4503d2f14aeadc6ae699ad35a19f80e3a2cc26bd (diff) |
Support for pinned stack to always be on-top of visible stacks
Bug: 25006507
Change-Id: I577e11224eead72dbb50def6be30b640707d2187
5 files changed, 92 insertions, 64 deletions
diff --git a/core/java/com/android/internal/policy/PhoneWindow.java b/core/java/com/android/internal/policy/PhoneWindow.java index afef7633bc69..7fab31f6f9ea 100644 --- a/core/java/com/android/internal/policy/PhoneWindow.java +++ b/core/java/com/android/internal/policy/PhoneWindow.java @@ -5409,7 +5409,7 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { * @Return Returns true if the window should show a non client decor. **/ private static boolean hasNonClientDecor(int workspaceId) { - return workspaceId == FREEFORM_WORKSPACE_STACK_ID || workspaceId == PINNED_STACK_ID; + return workspaceId == FREEFORM_WORKSPACE_STACK_ID; } /** diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java index 1cd375800afd..a6f0df037d32 100644 --- a/services/core/java/com/android/server/am/ActivityStack.java +++ b/services/core/java/com/android/server/am/ActivityStack.java @@ -530,26 +530,36 @@ final class ActivityStack { * @param task If non-null, the task will be moved to the top of the stack. * */ void moveToFront(String reason, TaskRecord task) { - if (isAttached()) { - final ActivityStack lastFocusStack = mStacks.get(mStacks.size() - 1); - // Need to move this stack to the front before calling - // {@link ActivityStackSupervisor#setFocusStack} below. - mStacks.remove(this); - mStacks.add(this); - - // TODO(multi-display): Needs to also work if focus is moving to the non-home display. - if (isOnHomeDisplay()) { - mStackSupervisor.setFocusStack(reason, lastFocusStack); - } - if (task != null) { - insertTaskAtTop(task, null); - } else { - task = topTask(); - } - if (task != null) { - mWindowManager.moveTaskToTop(task.taskId); + if (!isAttached()) { + return; + } + + mStacks.remove(this); + int addIndex = mStacks.size(); + + if (addIndex > 0) { + final ActivityStack topStack = mStacks.get(addIndex - 1); + if (topStack.mStackId == PINNED_STACK_ID && topStack != this) { + // The pinned stack is always the top most stack (always-on-top). + // So, stack is moved just below the pinned stack. + addIndex--; } } + + mStacks.add(addIndex, this); + + // TODO(multi-display): Needs to also work if focus is moving to the non-home display. + if (isOnHomeDisplay()) { + mStackSupervisor.setFocusStack(reason, this); + } + if (task != null) { + insertTaskAtTop(task, null); + } else { + task = topTask(); + } + if (task != null) { + mWindowManager.moveTaskToTop(task.taskId); + } } final boolean isAttached() { @@ -1304,12 +1314,7 @@ final class ActivityStack { return false; } - if (mStackSupervisor.isFrontStack(this)) { - return true; - } - - if (mStackId == PINNED_STACK_ID) { - // Pinned stack is always visible if it exist. + if (mStackSupervisor.isFrontStack(this) || mStackSupervisor.isFocusedStack(this)) { return true; } @@ -2041,7 +2046,7 @@ final class ActivityStack { // Have the window manager re-evaluate the orientation of // the screen based on the new activity order. boolean notUpdated = true; - if (mStackSupervisor.isFrontStack(this)) { + if (mStackSupervisor.isFocusedStack(this)) { Configuration config = mWindowManager.updateOrientationFromAppTokens( mService.mConfiguration, next.mayFreezeScreenLocked(next.app) ? next.appToken : null); @@ -2788,7 +2793,7 @@ final class ActivityStack { } private void adjustFocusedActivityLocked(ActivityRecord r, String reason) { - if (mStackSupervisor.isFrontStack(this) && mService.mFocusedActivity == r) { + if (mStackSupervisor.isFocusedStack(this) && mService.mFocusedActivity == r) { ActivityRecord next = topRunningActivityLocked(); final String myReason = reason + " adjustFocus"; if (next != r) { @@ -3395,7 +3400,7 @@ final class ActivityStack { if (task != null && task.removeActivity(r)) { if (DEBUG_STACK) Slog.i(TAG_STACK, "removeActivityFromHistoryLocked: last activity removed from " + this); - if (mStackSupervisor.isFrontStack(this) && task == topTask() && + if (mStackSupervisor.isFocusedStack(this) && task == topTask() && task.isOverHomeStack()) { mStackSupervisor.moveHomeStackTaskToTop(task.getTaskToReturnTo(), reason); } @@ -4569,7 +4574,7 @@ final class ActivityStack { if (mTaskHistory.isEmpty()) { if (DEBUG_STACK) Slog.i(TAG_STACK, "removeTask: removing stack=" + this); // We only need to adjust focused stack if this stack is in focus. - if (isOnHomeDisplay() && mStackSupervisor.isFrontStack(this)) { + if (isOnHomeDisplay() && mStackSupervisor.isFocusedStack(this)) { String myReason = reason + " leftTaskHistoryEmpty"; if (mFullscreen || !adjustFocusToNextVisibleStackLocked(null, myReason)) { mStackSupervisor.moveHomeStackToFront(myReason); @@ -4677,7 +4682,7 @@ final class ActivityStack { return; } - final boolean wasFocused = mStackSupervisor.isFrontStack(prevStack) + final boolean wasFocused = mStackSupervisor.isFocusedStack(prevStack) && (mStackSupervisor.topRunningActivityLocked() == r); final boolean wasResumed = wasFocused && (prevStack.mResumedActivity == r); diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java index 3bf87d870589..1cd71a1cb61a 100644 --- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java +++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java @@ -458,10 +458,7 @@ public final class ActivityStackSupervisor implements DisplayListener { return mLastFocusedStack; } - /** Top of all visible stacks is/should always be equal to the focused stack. - * Use {@link ActivityStack#isStackVisibleLocked} to determine if a specific - * stack is visible or not. */ - boolean isFrontStack(ActivityStack stack) { + boolean isFocusedStack(ActivityStack stack) { if (stack == null) { return false; } @@ -473,18 +470,22 @@ public final class ActivityStackSupervisor implements DisplayListener { return stack == mFocusedStack; } - void setFocusStack(String reason, ActivityStack lastFocusedStack) { - ArrayList<ActivityStack> stacks = mHomeStack.mStacks; - final int topNdx = stacks.size() - 1; - if (topNdx <= 0) { - return; + /** The top most stack. */ + boolean isFrontStack(ActivityStack stack) { + if (stack == null) { + return false; } - final ActivityStack topStack = stacks.get(topNdx); - mFocusedStack = topStack; - if (lastFocusedStack != null) { - mLastFocusedStack = lastFocusedStack; + final ActivityRecord parent = stack.mActivityContainer.mParentActivity; + if (parent != null) { + stack = parent.task.stack; } + return stack == mHomeStack.mStacks.get((mHomeStack.mStacks.size() - 1)); + } + + void setFocusStack(String reason, ActivityStack focusedStack) { + mLastFocusedStack = mFocusedStack; + mFocusedStack = focusedStack; EventLogTags.writeAmFocusedStack( mCurrentUser, mFocusedStack == null ? -1 : mFocusedStack.getStackId(), @@ -642,7 +643,7 @@ public final class ActivityStackSupervisor implements DisplayListener { ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks; for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) { final ActivityStack stack = stacks.get(stackNdx); - if (!isFrontStack(stack)) { + if (!isFocusedStack(stack)) { continue; } ActivityRecord hr = stack.topRunningActivityLocked(); @@ -673,7 +674,7 @@ public final class ActivityStackSupervisor implements DisplayListener { ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks; for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) { final ActivityStack stack = stacks.get(stackNdx); - if (!isFrontStack(stack) || stack.numActivities() == 0) { + if (!isFocusedStack(stack) || stack.numActivities() == 0) { continue; } final ActivityRecord resumedActivity = stack.mResumedActivity; @@ -692,7 +693,7 @@ public final class ActivityStackSupervisor implements DisplayListener { ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks; for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) { final ActivityStack stack = stacks.get(stackNdx); - if (isFrontStack(stack)) { + if (isFocusedStack(stack)) { final ActivityRecord r = stack.mResumedActivity; if (r != null && r.state != RESUMED) { return false; @@ -737,7 +738,7 @@ public final class ActivityStackSupervisor implements DisplayListener { ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks; for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) { final ActivityStack stack = stacks.get(stackNdx); - if (!isFrontStack(stack) && stack.mResumedActivity != null) { + if (!isFocusedStack(stack) && stack.mResumedActivity != null) { if (DEBUG_STATES) Slog.d(TAG_STATES, "pauseBackStacks: stack=" + stack + " mResumedActivity=" + stack.mResumedActivity); someActivityPaused |= stack.startPausingLocked(userLeaving, false, resuming, @@ -1374,7 +1375,7 @@ public final class ActivityStackSupervisor implements DisplayListener { // launching the initial activity (that is, home), so that it can have // a chance to initialize itself while in the background, making the // switch back to it faster and look better. - if (isFrontStack(stack)) { + if (isFocusedStack(stack)) { mService.startSetupActivityLocked(); } @@ -2621,7 +2622,7 @@ public final class ActivityStackSupervisor implements DisplayListener { r.idle = true; //Slog.i(TAG, "IDLE: mBooted=" + mBooted + ", fromTimeout=" + fromTimeout); - if (isFrontStack(r.task.stack) || fromTimeout) { + if (isFocusedStack(r.task.stack) || fromTimeout) { booting = checkFinishBootingLocked(); } } @@ -2773,7 +2774,7 @@ public final class ActivityStackSupervisor implements DisplayListener { final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks; for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) { final ActivityStack stack = stacks.get(stackNdx); - if (isFrontStack(stack)) { + if (isFocusedStack(stack)) { if (stack.mResumedActivity != null) { fgApp = stack.mResumedActivity.app; } else if (stack.mPausingActivity != null) { @@ -2805,7 +2806,7 @@ public final class ActivityStackSupervisor implements DisplayListener { } // Do targetStack first. boolean result = false; - if (isFrontStack(targetStack)) { + if (isFocusedStack(targetStack)) { result = targetStack.resumeTopActivityLocked(target, targetOptions); } @@ -2817,7 +2818,7 @@ public final class ActivityStackSupervisor implements DisplayListener { // Already started above. continue; } - if (isFrontStack(stack)) { + if (isFocusedStack(stack)) { stack.resumeTopActivityLocked(null); } } @@ -3243,7 +3244,7 @@ public final class ActivityStackSupervisor implements DisplayListener { ActivityStack moveTaskToStackUncheckedLocked( TaskRecord task, int stackId, boolean toTop, boolean forceFocus, String reason) { final ActivityRecord r = task.getTopActivity(); - final boolean wasFocused = isFrontStack(task.stack) && (topRunningActivityLocked() == r); + final boolean wasFocused = isFocusedStack(task.stack) && (topRunningActivityLocked() == r); final boolean wasResumed = wasFocused && (task.stack.mResumedActivity == r); final boolean resizeable = task.mResizeable; @@ -3469,7 +3470,7 @@ public final class ActivityStackSupervisor implements DisplayListener { for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) { final ActivityStack stack = stacks.get(stackNdx); stack.awakeFromSleepingLocked(); - if (isFrontStack(stack)) { + if (isFocusedStack(stack)) { resumeTopActivitiesLocked(); } } @@ -3536,7 +3537,7 @@ public final class ActivityStackSupervisor implements DisplayListener { boolean reportResumedActivityLocked(ActivityRecord r) { final ActivityStack stack = r.task.stack; - if (isFrontStack(stack)) { + if (isFocusedStack(stack)) { mService.updateUsageStats(r, true); } if (allResumedActivitiesComplete()) { @@ -3829,7 +3830,7 @@ public final class ActivityStackSupervisor implements DisplayListener { final ActivityStack stack = stacks.get(stackNdx); final ActivityRecord r = stack.topRunningActivityLocked(); final ActivityState state = r == null ? DESTROYED : r.state; - if (isFrontStack(stack)) { + if (isFocusedStack(stack)) { if (r == null) Slog.e(TAG, "validateTop...: null top activity, stack=" + stack); else { diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java index 39479c1a9681..fab8ee55b22c 100644 --- a/services/core/java/com/android/server/wm/DisplayContent.java +++ b/services/core/java/com/android/server/wm/DisplayContent.java @@ -18,7 +18,7 @@ package com.android.server.wm; import static android.app.ActivityManager.DOCKED_STACK_ID; import static android.app.ActivityManager.HOME_STACK_ID; - +import static android.app.ActivityManager.PINNED_STACK_ID; import static com.android.server.wm.WindowManagerService.DEBUG_VISIBILITY; import static com.android.server.wm.WindowManagerService.TAG; import static com.android.server.wm.WindowState.RESIZE_HANDLE_WIDTH_IN_DP; @@ -243,10 +243,30 @@ class DisplayContent { } void moveStack(TaskStack stack, boolean toTop) { + if (stack.mStackId == PINNED_STACK_ID && !toTop) { + // Pinned stack is always-on-top silly... + Slog.w(TAG, "Ignoring move of always-on-top stack=" + stack + " to bottom"); + return; + } + if (!mStacks.remove(stack)) { Slog.wtf(TAG, "moving stack that was not added: " + stack, new Throwable()); } - mStacks.add(toTop ? mStacks.size() : 0, stack); + + int addIndex = toTop ? mStacks.size() : 0; + + if (toTop + && mService.isStackVisibleLocked(PINNED_STACK_ID) + && stack.mStackId != PINNED_STACK_ID) { + // The pinned stack is always the top most stack (always-on-top) when it is visible. + // So, stack is moved just below the pinned stack. + addIndex--; + TaskStack topStack = mStacks.get(addIndex); + if (topStack.mStackId != PINNED_STACK_ID) { + throw new IllegalStateException("Pinned stack isn't top stack??? " + mStacks); + } + } + mStacks.add(addIndex, stack); } void detachStack(TaskStack stack) { diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index 62553cf6a2b0..fb99d9eae897 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -3284,10 +3284,8 @@ public class WindowManagerService extends IWindowManager.Stub } } - final TaskStack dockedStack = mStackIdToStack.get(DOCKED_STACK_ID); - final TaskStack freeformStack = mStackIdToStack.get(FREEFORM_WORKSPACE_STACK_ID); - if ((dockedStack != null && dockedStack.isVisibleLocked()) - || (freeformStack != null && freeformStack.isVisibleLocked())) { + if (isStackVisibleLocked(DOCKED_STACK_ID) + || isStackVisibleLocked(FREEFORM_WORKSPACE_STACK_ID)) { // We don't let app affect the system orientation when in freeform or docked mode since // they don't occupy the entire display and their request can conflict with other apps. return SCREEN_ORIENTATION_UNSPECIFIED; @@ -4518,6 +4516,11 @@ public class WindowManagerService extends IWindowManager.Stub } } + boolean isStackVisibleLocked(int stackId) { + final TaskStack stack = mStackIdToStack.get(stackId); + return (stack != null && stack.isVisibleLocked()); + } + public void setDockedStackCreateMode(int mode) { synchronized (mWindowMap) { sDockedStackCreateMode = mode; @@ -10214,8 +10217,7 @@ public class WindowManagerService extends IWindowManager.Stub @Override public boolean isStackVisible(int stackId) { synchronized (mWindowMap) { - final TaskStack stack = mStackIdToStack.get(stackId); - return (stack != null && stack.isVisibleLocked()); + return WindowManagerService.this.isStackVisibleLocked(stackId); } } } |