Support for pinned stack to always be on-top of visible stacks
Bug: 25006507
Change-Id: I577e11224eead72dbb50def6be30b640707d2187
diff --git a/core/java/com/android/internal/policy/PhoneWindow.java b/core/java/com/android/internal/policy/PhoneWindow.java
index afef763..7fab31f 100644
--- a/core/java/com/android/internal/policy/PhoneWindow.java
+++ b/core/java/com/android/internal/policy/PhoneWindow.java
@@ -5409,7 +5409,7 @@
* @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 1cd3758..a6f0df0 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -530,25 +530,35 @@
* @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);
+ if (!isAttached()) {
+ return;
+ }
- // TODO(multi-display): Needs to also work if focus is moving to the non-home display.
- if (isOnHomeDisplay()) {
- mStackSupervisor.setFocusStack(reason, lastFocusStack);
+ 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--;
}
- if (task != null) {
- insertTaskAtTop(task, null);
- } else {
- task = topTask();
- }
- if (task != null) {
- mWindowManager.moveTaskToTop(task.taskId);
- }
+ }
+
+ 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);
}
}
@@ -1304,12 +1314,7 @@
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 @@
// 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 @@
}
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 @@
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 @@
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 @@
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 3bf87d8..1cd71a1 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
// 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 @@
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 @@
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 @@
}
// Do targetStack first.
boolean result = false;
- if (isFrontStack(targetStack)) {
+ if (isFocusedStack(targetStack)) {
result = targetStack.resumeTopActivityLocked(target, targetOptions);
}
@@ -2817,7 +2818,7 @@
// Already started above.
continue;
}
- if (isFrontStack(stack)) {
+ if (isFocusedStack(stack)) {
stack.resumeTopActivityLocked(null);
}
}
@@ -3243,7 +3244,7 @@
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 @@
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 @@
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 @@
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 39479c1..fab8ee5 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 @@
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 @@
}
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 62553cf..fb99d9ea 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 @@
}
}
- 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 @@
}
}
+ 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 @@
@Override
public boolean isStackVisible(int stackId) {
synchronized (mWindowMap) {
- final TaskStack stack = mStackIdToStack.get(stackId);
- return (stack != null && stack.isVisibleLocked());
+ return WindowManagerService.this.isStackVisibleLocked(stackId);
}
}
}