Merge "Cleanup the activity before the task and stack"
diff --git a/cmds/am/src/com/android/commands/am/Am.java b/cmds/am/src/com/android/commands/am/Am.java
index 62081ee..a501fa7 100644
--- a/cmds/am/src/com/android/commands/am/Am.java
+++ b/cmds/am/src/com/android/commands/am/Am.java
@@ -138,6 +138,7 @@
" am task lock <TASK_ID>\n" +
" am task lock stop\n" +
" am task resizeable <TASK_ID> [true|false]\n" +
+ " am task resize <TASK_ID> <LEFT,TOP,RIGHT,BOTTOM>\n" +
" am get-config\n" +
"\n" +
"am start: start an Activity. Options are:\n" +
@@ -249,11 +250,11 @@
"am stack resize: change <STACK_ID> size and position to <LEFT,TOP,RIGHT,BOTTOM>" +
".\n" +
"\n" +
- "am stack split: split <STACK_ID> into 2 stacks <v>ertically or <h>orizontally" +
- " starting the new stack with [INTENT] if specified. If [INTENT] isn't" +
- " specified and the current stack has more than one task, then the top task" +
- " of the current task will be moved to the new stack. Command will also force" +
- " all current tasks in both stacks to be resizeable." +
+ "am stack split: split <STACK_ID> into 2 stacks <v>ertically or <h>orizontally\n" +
+ " starting the new stack with [INTENT] if specified. If [INTENT] isn't\n" +
+ " specified and the current stack has more than one task, then the top task\n" +
+ " of the current task will be moved to the new stack. Command will also force\n" +
+ " all current tasks in both stacks to be resizeable.\n" +
"\n" +
"am stack list: list all of the activity stacks and their sizes.\n" +
"\n" +
@@ -265,6 +266,10 @@
"\n" +
"am task resizeable: change if <TASK_ID> is resizeable (true) or not (false).\n" +
"\n" +
+ "am task resize: makes sure <TASK_ID> is in a stack with the specified bounds.\n" +
+ " Forces the task to be resizeable and creates a stack if no existing stack\n" +
+ " has the specified bounds.\n" +
+ "\n" +
"am get-config: retrieve the configuration and any recent configurations\n" +
" of the device\n" +
"\n" +
@@ -1742,33 +1747,14 @@
private void runStackResize() throws Exception {
String stackIdStr = nextArgRequired();
int stackId = Integer.valueOf(stackIdStr);
- String leftStr = nextArgRequired();
- int left = Integer.valueOf(leftStr);
- String topStr = nextArgRequired();
- int top = Integer.valueOf(topStr);
- String rightStr = nextArgRequired();
- int right = Integer.valueOf(rightStr);
- String bottomStr = nextArgRequired();
- int bottom = Integer.valueOf(bottomStr);
- if (left < 0) {
- System.err.println("Error: bad left arg: " + leftStr);
- return;
- }
- if (top < 0) {
- System.err.println("Error: bad top arg: " + topStr);
- return;
- }
- if (right <= 0) {
- System.err.println("Error: bad right arg: " + rightStr);
- return;
- }
- if (bottom <= 0) {
- System.err.println("Error: bad bottom arg: " + bottomStr);
+ final Rect bounds = getBounds();
+ if (bounds == null) {
+ System.err.println("Error: invalid input bounds");
return;
}
try {
- mAm.resizeStack(stackId, new Rect(left, top, right, bottom));
+ mAm.resizeStack(stackId, bounds);
} catch (RemoteException e) {
}
}
@@ -1857,6 +1843,8 @@
runTaskLock();
} else if (op.equals("resizeable")) {
runTaskResizeable();
+ } else if (op.equals("resize")) {
+ runTaskResize();
} else {
showError("Error: unknown command '" + op + "'");
return;
@@ -1890,6 +1878,20 @@
}
}
+ private void runTaskResize() throws Exception {
+ final String taskIdStr = nextArgRequired();
+ final int taskId = Integer.valueOf(taskIdStr);
+ final Rect bounds = getBounds();
+ if (bounds == null) {
+ System.err.println("Error: invalid input bounds");
+ return;
+ }
+ try {
+ mAm.resizeTask(taskId, bounds);
+ } catch (RemoteException e) {
+ }
+ }
+
private List<Configuration> getRecentConfigurations(int days) {
IUsageStatsManager usm = IUsageStatsManager.Stub.asInterface(ServiceManager.getService(
Context.USAGE_STATS_SERVICE));
@@ -1986,4 +1988,32 @@
}
return fd;
}
+
+ private Rect getBounds() {
+ String leftStr = nextArgRequired();
+ int left = Integer.valueOf(leftStr);
+ String topStr = nextArgRequired();
+ int top = Integer.valueOf(topStr);
+ String rightStr = nextArgRequired();
+ int right = Integer.valueOf(rightStr);
+ String bottomStr = nextArgRequired();
+ int bottom = Integer.valueOf(bottomStr);
+ if (left < 0) {
+ System.err.println("Error: bad left arg: " + leftStr);
+ return null;
+ }
+ if (top < 0) {
+ System.err.println("Error: bad top arg: " + topStr);
+ return null;
+ }
+ if (right <= 0) {
+ System.err.println("Error: bad right arg: " + rightStr);
+ return null;
+ }
+ if (bottom <= 0) {
+ System.err.println("Error: bad bottom arg: " + bottomStr);
+ return null;
+ }
+ return new Rect(left, top, right, bottom);
+ }
}
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index 005b1d9..bb307bb 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -2313,6 +2313,15 @@
return true;
}
+ case RESIZE_TASK_TRANSACTION: {
+ data.enforceInterface(IActivityManager.descriptor);
+ int taskId = data.readInt();
+ Rect r = Rect.CREATOR.createFromParcel(data);
+ resizeTask(taskId, r);
+ reply.writeNoException();
+ return true;
+ }
+
case GET_TASK_DESCRIPTION_ICON_TRANSACTION: {
data.enforceInterface(IActivityManager.descriptor);
String filename = data.readString();
@@ -5438,6 +5447,20 @@
}
@Override
+ public void resizeTask(int taskId, Rect r) throws RemoteException
+ {
+ Parcel data = Parcel.obtain();
+ Parcel reply = Parcel.obtain();
+ data.writeInterfaceToken(IActivityManager.descriptor);
+ data.writeInt(taskId);
+ r.writeToParcel(data, 0);
+ mRemote.transact(RESIZE_TASK_TRANSACTION, data, reply, IBinder.FLAG_ONEWAY);
+ reply.readException();
+ data.recycle();
+ reply.recycle();
+ }
+
+ @Override
public Bitmap getTaskDescriptionIcon(String filename) throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index 1f5a1a0..a7e9413 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -464,6 +464,7 @@
public void setTaskDescription(IBinder token, ActivityManager.TaskDescription values)
throws RemoteException;
public void setTaskResizeable(int taskId, boolean resizeable) throws RemoteException;
+ public void resizeTask(int taskId, Rect bounds) throws RemoteException;
public Bitmap getTaskDescriptionIcon(String filename) throws RemoteException;
public void startInPlaceAnimationOnFrontMostApplication(ActivityOptions opts)
@@ -808,4 +809,5 @@
int GET_FOCUSED_STACK_ID_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+282;
int SET_TASK_RESIZEABLE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+283;
int REQUEST_ASSIST_CONTEXT_EXTRAS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+284;
+ int RESIZE_TASK_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+285;
}
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 3baf3e0..a5fa5ed 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -3100,17 +3100,6 @@
return (theParent instanceof ViewGroup) && isViewDescendantOf((View) theParent, parent);
}
- private static void forceLayout(View view) {
- view.forceLayout();
- if (view instanceof ViewGroup) {
- ViewGroup group = (ViewGroup) view;
- final int count = group.getChildCount();
- for (int i = 0; i < count; i++) {
- forceLayout(group.getChildAt(i));
- }
- }
- }
-
private final static int MSG_INVALIDATE = 1;
private final static int MSG_INVALIDATE_RECT = 2;
private final static int MSG_DIE = 3;
@@ -3244,10 +3233,6 @@
mReportNextDraw = true;
}
- if (mView != null) {
- forceLayout(mView);
- }
-
requestLayout();
}
break;
@@ -3262,9 +3247,6 @@
mWinFrame.top = t;
mWinFrame.bottom = t + h;
- if (mView != null) {
- forceLayout(mView);
- }
requestLayout();
}
break;
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index c418dc3..d240047 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -31,7 +31,7 @@
<integer name="max_action_buttons">2</integer>
<dimen name="toast_y_offset">64dip</dimen>
<!-- Height of the status bar -->
- <dimen name="status_bar_height">25dip</dimen>
+ <dimen name="status_bar_height">24dp</dimen>
<!-- Height of the bottom navigation / system bar. -->
<dimen name="navigation_bar_height">48dp</dimen>
<!-- Height of the bottom navigation bar in portrait; often the same as @dimen/navigation_bar_height -->
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaProjectionPermissionActivity.java b/packages/SystemUI/src/com/android/systemui/media/MediaProjectionPermissionActivity.java
index 25bab17..c23f45d 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaProjectionPermissionActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaProjectionPermissionActivity.java
@@ -114,7 +114,9 @@
@Override
protected void onDestroy() {
super.onDestroy();
- mDialog.dismiss();
+ if (mDialog != null) {
+ mDialog.dismiss();
+ }
}
@Override
@@ -128,7 +130,9 @@
Log.e(TAG, "Error granting projection permission", e);
setResult(RESULT_CANCELED);
} finally {
- mDialog.dismiss();
+ if (mDialog != null) {
+ mDialog.dismiss();
+ }
finish();
}
}
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 6229778..966dc88 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -7909,6 +7909,25 @@
}
@Override
+ public void resizeTask(int taskId, Rect bounds) {
+ enforceCallingPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS,
+ "resizeTask()");
+ long ident = Binder.clearCallingIdentity();
+ try {
+ synchronized (this) {
+ TaskRecord task = mStackSupervisor.anyTaskForIdLocked(taskId, true);
+ if (task == null) {
+ Slog.w(TAG, "resizeTask: taskId=" + taskId + " not found");
+ return;
+ }
+ mStackSupervisor.resizeTaskLocked(task, bounds);
+ }
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+ }
+
+ @Override
public Bitmap getTaskDescriptionIcon(String filename) {
if (!FileUtils.isValidExtFilename(filename)
|| !filename.contains(ActivityRecord.ACTIVITY_ICON_SUFFIX)) {
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index a0df032..c3343f5 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -152,25 +152,25 @@
* The back history of all previous (and possibly still
* running) activities. It contains #TaskRecord objects.
*/
- private ArrayList<TaskRecord> mTaskHistory = new ArrayList<TaskRecord>();
+ private ArrayList<TaskRecord> mTaskHistory = new ArrayList<>();
/**
* Used for validating app tokens with window manager.
*/
- final ArrayList<TaskGroup> mValidateAppTokens = new ArrayList<TaskGroup>();
+ final ArrayList<TaskGroup> mValidateAppTokens = new ArrayList<>();
/**
* List of running activities, sorted by recent usage.
* The first entry in the list is the least recently used.
* It contains HistoryRecord objects.
*/
- final ArrayList<ActivityRecord> mLRUActivities = new ArrayList<ActivityRecord>();
+ final ArrayList<ActivityRecord> mLRUActivities = new ArrayList<>();
/**
* Animations that for the current transition have requested not to
* be considered for the transition animation.
*/
- final ArrayList<ActivityRecord> mNoAnimActivities = new ArrayList<ActivityRecord>();
+ final ArrayList<ActivityRecord> mNoAnimActivities = new ArrayList<>();
/**
* When we are in the process of pausing an activity, before starting the
@@ -346,6 +346,10 @@
return count;
}
+ int numTasks() {
+ return mTaskHistory.size();
+ }
+
ActivityStack(ActivityStackSupervisor.ActivityContainer activityContainer,
RecentTasks recentTasks) {
mActivityContainer = activityContainer;
@@ -1154,6 +1158,23 @@
return null;
}
+ private ActivityStack getNextVisibleStackLocked() {
+ ArrayList<ActivityStack> stacks = mStacks;
+ final ActivityRecord parent = mActivityContainer.mParentActivity;
+ if (parent != null) {
+ stacks = parent.task.stack.mStacks;
+ }
+ if (stacks != null) {
+ for (int i = stacks.size() - 1; i >= 0; --i) {
+ ActivityStack stack = stacks.get(i);
+ if (stack != this && stack.isStackVisibleLocked()) {
+ return stack;
+ }
+ }
+ }
+ return null;
+ }
+
// Checks if any of the stacks above this one has a fullscreen activity behind it.
// If so, this stack is hidden, otherwise it is visible.
private boolean isStackVisibleLocked() {
@@ -1482,7 +1503,7 @@
return result;
}
- final boolean resumeTopActivityInnerLocked(ActivityRecord prev, Bundle options) {
+ private boolean resumeTopActivityInnerLocked(ActivityRecord prev, Bundle options) {
if (ActivityManagerService.DEBUG_LOCKSCREEN) mService.logLockScreen("");
if (!mService.mBooting && !mService.mBooted) {
@@ -1510,8 +1531,17 @@
final TaskRecord prevTask = prev != null ? prev.task : null;
if (next == null) {
- // There are no more activities! Let's just start up the
- // Launcher...
+ // There are no more activities!
+ final String reason = "noMoreActivities";
+ if (!mFullscreen) {
+ // 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.resumeTopActivitiesLocked(stack, prev, null);
+ }
+ }
+ // Let's just start up the Launcher...
ActivityOptions.abort(options);
if (DEBUG_STATES) Slog.d(TAG, "resumeTopActivityLocked: No more activities go home");
if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
@@ -1519,7 +1549,7 @@
final int returnTaskType = prevTask == null || !prevTask.isOverHomeStack() ?
HOME_ACTIVITY_TYPE : prevTask.getTaskToReturnTo();
return isOnHomeDisplay() &&
- mStackSupervisor.resumeHomeStackTask(returnTaskType, prev, "noMoreActivities");
+ mStackSupervisor.resumeHomeStackTask(returnTaskType, prev, reason);
}
next.delayedResume = false;
@@ -2516,20 +2546,45 @@
private void adjustFocusedActivityLocked(ActivityRecord r, String reason) {
if (mStackSupervisor.isFrontStack(this) && mService.mFocusedActivity == r) {
ActivityRecord next = topRunningActivityLocked(null);
+ final String myReason = reason + " adjustFocus";
if (next != r) {
final TaskRecord task = r.task;
if (r.frontOfTask && task == topTask() && task.isOverHomeStack()) {
- mStackSupervisor.moveHomeStackTaskToTop(task.getTaskToReturnTo(),
- reason + " adjustFocus");
+ // 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)) {
+ return;
+ }
+ // Move the home stack to the top if this stack is fullscreen or there is no
+ // other visible stack.
+ mStackSupervisor.moveHomeStackTaskToTop(task.getTaskToReturnTo(), myReason);
}
}
- ActivityRecord top = mStackSupervisor.topRunningActivityLocked();
+
+ final ActivityRecord top = mStackSupervisor.topRunningActivityLocked();
if (top != null) {
- mService.setFocusedActivityLocked(top, reason + " adjustTopFocus");
+ mService.setFocusedActivityLocked(top, myReason);
}
}
}
+ private boolean adjustFocusToNextVisibleStackLocked(ActivityStack inStack, String reason) {
+ final ActivityStack stack = (inStack != null) ? inStack : getNextVisibleStackLocked();
+ final String myReason = reason + " adjustFocusToNextVisibleStack";
+ if (stack == null) {
+ return false;
+ }
+ final ActivityRecord top = stack.topRunningActivityLocked(null);
+ if (top == null) {
+ return false;
+ }
+ stack.moveToFront(myReason);
+ mService.setFocusedActivityLocked(top, myReason);
+ return true;
+ }
+
final void stopActivityLocked(ActivityRecord r) {
if (DEBUG_SWITCH) Slog.d(TAG, "Stopping: " + r);
if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_HISTORY) != 0
@@ -4128,8 +4183,14 @@
}
void removeTask(TaskRecord task, String reason) {
+ removeTask(task, reason, true);
+ }
+
+ void removeTask(TaskRecord task, String reason, boolean removeFromWindowManager) {
mStackSupervisor.endLockTaskModeIfTaskEnding(task);
- mWindowManager.removeTask(task.taskId);
+ if (removeFromWindowManager) {
+ mWindowManager.removeTask(task.taskId);
+ }
final ActivityRecord r = mResumedActivity;
if (r != null && r.task == task) {
mResumedActivity = null;
@@ -4163,10 +4224,13 @@
}
if (mTaskHistory.isEmpty()) {
- if (DEBUG_STACK) Slog.i(TAG, "removeTask: moving to back stack=" + this);
+ if (DEBUG_STACK) Slog.i(TAG, "removeTask: removing stack=" + this);
final boolean notHomeStack = !isHomeStack();
if (isOnHomeDisplay()) {
- mStackSupervisor.moveHomeStack(notHomeStack, reason + " leftTaskHistoryEmpty");
+ String myReason = reason + " leftTaskHistoryEmpty";
+ if (mFullscreen || !adjustFocusToNextVisibleStackLocked(null, myReason)) {
+ mStackSupervisor.moveHomeStack(notHomeStack, myReason);
+ }
}
if (mStacks != null) {
mStacks.remove(this);
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 9fe3c48..907381e 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -386,8 +386,8 @@
return mLastFocusedStack;
}
- // TODO: Split into two methods isFrontStack for any visible stack and isFrontmostStack for the
- // top of all visible stacks.
+ /** Top of all visible stacks. Use {@link ActivityStack#isStackVisibleLocked} to determine if a
+ * specific stack is visible or not. */
boolean isFrontStack(ActivityStack stack) {
final ActivityRecord parent = stack.mActivityContainer.mParentActivity;
if (parent != null) {
@@ -535,7 +535,7 @@
}
ActivityRecord resumedAppLocked() {
- ActivityStack stack = getFocusedStack();
+ ActivityStack stack = mFocusedStack;
if (stack == null) {
return null;
}
@@ -739,7 +739,7 @@
}
ActivityRecord topRunningActivityLocked() {
- final ActivityStack focusedStack = getFocusedStack();
+ final ActivityStack focusedStack = mFocusedStack;
ActivityRecord r = focusedStack.topRunningActivityLocked(null);
if (r != null) {
return r;
@@ -885,7 +885,7 @@
final ActivityStack stack;
if (container == null || container.mStack.isOnHomeDisplay()) {
- stack = getFocusedStack();
+ stack = mFocusedStack;
} else {
stack = container.mStack;
}
@@ -1502,7 +1502,7 @@
outActivity[0] = r;
}
- final ActivityStack stack = getFocusedStack();
+ final ActivityStack stack = mFocusedStack;
if (voiceSession == null && (stack.mResumedActivity == null
|| stack.mResumedActivity.info.applicationInfo.uid != callingUid)) {
if (!mService.checkAppSwitchAllowedLocked(callingPid, callingUid,
@@ -1706,7 +1706,7 @@
if ((startFlags&ActivityManager.START_FLAG_ONLY_IF_NEEDED) != 0) {
ActivityRecord checkedCaller = sourceRecord;
if (checkedCaller == null) {
- checkedCaller = getFocusedStack().topRunningNonDelayedActivityLocked(notTop);
+ checkedCaller = mFocusedStack.topRunningNonDelayedActivityLocked(notTop);
}
if (!checkedCaller.realActivity.equals(r.realActivity)) {
// Caller is not the same as launcher, so always needed.
@@ -2030,7 +2030,7 @@
// If the activity being launched is the same as the one currently
// at the top, then we need to check if it should only be launched
// once.
- ActivityStack topStack = getFocusedStack();
+ ActivityStack topStack = mFocusedStack;
ActivityRecord top = topStack.topRunningNonDelayedActivityLocked(notTop);
if (top != null && r.resultTo == null) {
if (top.realActivity.equals(r.realActivity) && top.userId == r.userId) {
@@ -2482,13 +2482,14 @@
boolean resumeTopActivitiesLocked(ActivityStack targetStack, ActivityRecord target,
Bundle targetOptions) {
if (targetStack == null) {
- targetStack = getFocusedStack();
+ targetStack = mFocusedStack;
}
// Do targetStack first.
boolean result = false;
if (isFrontStack(targetStack)) {
result = targetStack.resumeTopActivityLocked(target, targetOptions);
}
+
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
@@ -2640,6 +2641,48 @@
}
}
+ /** Makes sure the input task is in a stack with the specified bounds by either resizing the
+ * current task stack if it only has one entry, moving the task to a stack that matches the
+ * bounds, or creating a new stack with the required bounds. Also, makes the task resizeable.*/
+ void resizeTaskLocked(TaskRecord task, Rect bounds) {
+ task.mResizeable = true;
+ final ActivityStack currentStack = task.stack;
+ if (currentStack.isHomeStack()) {
+ // Can't move task off the home stack. Sorry!
+ return;
+ }
+
+ final int matchingStackId = mWindowManager.getStackIdWithBounds(bounds);
+ if (matchingStackId != -1) {
+ // There is already a stack with the right bounds!
+ if (currentStack != null && currentStack.mStackId == matchingStackId) {
+ // Nothing to do here. Already in the right stack...
+ return;
+ }
+ // Move task to stack with matching bounds.
+ moveTaskToStackLocked(task.taskId, matchingStackId, true);
+ return;
+ }
+
+ if (currentStack != null && currentStack.numTasks() == 1) {
+ // Just resize the current stack since this is the task in it.
+ resizeStackLocked(currentStack.mStackId, bounds);
+ return;
+ }
+
+ // Create new stack and move the task to it.
+ final int displayId = (currentStack != null && currentStack.mDisplayId != -1)
+ ? currentStack.mDisplayId : Display.DEFAULT_DISPLAY;
+ ActivityStack newStack = createStackOnDisplay(getNextStackId(), displayId);
+
+ if (newStack == null) {
+ Slog.e(TAG, "resizeTaskLocked: Can't create stack for task=" + task);
+ return;
+ }
+ moveTaskToStackLocked(task.taskId, newStack.mStackId, true);
+ resizeStackLocked(newStack.mStackId, bounds);
+ }
+
ActivityStack createStackOnDisplay(int stackId, int displayId) {
ActivityDisplay activityDisplay = mActivityDisplays.get(displayId);
if (activityDisplay == null) {
@@ -2718,6 +2761,7 @@
void moveTaskToStackLocked(int taskId, int stackId, boolean toTop) {
final TaskRecord task = anyTaskForIdLocked(taskId);
if (task == null) {
+ Slog.w(TAG, "moveTaskToStack: no task for id=" + taskId);
return;
}
final ActivityStack stack = getStack(stackId);
@@ -2725,9 +2769,11 @@
Slog.w(TAG, "moveTaskToStack: no stack for id=" + stackId);
return;
}
- task.stack.removeTask(task, "moveTaskToStack");
+ mWindowManager.moveTaskToStack(taskId, stackId, toTop);
+ if (task.stack != null) {
+ task.stack.removeTask(task, "moveTaskToStack", false);
+ }
stack.addTask(task, toTop, true);
- mWindowManager.addTask(taskId, stackId, toTop);
resumeTopActivitiesLocked();
}
@@ -3068,7 +3114,7 @@
}
boolean switchUserLocked(int userId, UserStartedState uss) {
- mUserStackInFront.put(mCurrentUser, getFocusedStack().getStackId());
+ mUserStackInFront.put(mCurrentUser, mFocusedStack.getStackId());
final int restoreStackId = mUserStackInFront.get(userId, HOME_STACK_ID);
mCurrentUser = userId;
@@ -3192,7 +3238,7 @@
}
ArrayList<ActivityRecord> getDumpActivitiesLocked(String name) {
- return getFocusedStack().getDumpActivitiesLocked(name);
+ return mFocusedStack.getDumpActivitiesLocked(name);
}
static boolean printThisActivity(PrintWriter pw, ActivityRecord activity, String dumpPackage,
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index a9b26e2..b8f26c96 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -72,6 +72,19 @@
mService.mTaskIdToTask.delete(mTaskId);
}
+ void moveTaskToStack(TaskStack stack, boolean toTop) {
+ if (stack == mStack) {
+ return;
+ }
+ if (DEBUG_STACK) Slog.i(TAG, "moveTaskToStack: removing taskId=" + mTaskId
+ + " from stack=" + mStack);
+ EventLog.writeEvent(EventLogTags.WM_TASK_REMOVED, mTaskId, "removeTask");
+ if (mStack != null) {
+ mStack.removeTask(this);
+ }
+ stack.addTask(this, toTop);
+ }
+
boolean removeAppToken(AppWindowToken wtoken) {
boolean removed = mAppTokens.remove(wtoken);
if (mAppTokens.size() == 0) {
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index d4a15af5..fde0bd5 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -16,6 +16,7 @@
package com.android.server.wm;
+import static com.android.server.am.ActivityStackSupervisor.HOME_STACK_ID;
import static android.view.WindowManager.LayoutParams.*;
import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
@@ -682,11 +683,11 @@
final WindowAnimator mAnimator;
- SparseArray<Task> mTaskIdToTask = new SparseArray<Task>();
+ SparseArray<Task> mTaskIdToTask = new SparseArray<>();
/** All of the TaskStacks in the window manager, unordered. For an ordered list call
* DisplayContent.getStacks(). */
- SparseArray<TaskStack> mStackIdToStack = new SparseArray<TaskStack>();
+ SparseArray<TaskStack> mStackIdToStack = new SparseArray<>();
private final PointerEventDispatcher mPointerEventDispatcher;
@@ -5088,6 +5089,7 @@
+ " to " + (toTop ? "top" : "bottom"));
Task task = mTaskIdToTask.get(taskId);
if (task == null) {
+ if (DEBUG_STACK) Slog.i(TAG, "addTask: could not find taskId=" + taskId);
return;
}
TaskStack stack = mStackIdToStack.get(stackId);
@@ -5098,6 +5100,27 @@
}
}
+ public void moveTaskToStack(int taskId, int stackId, boolean toTop) {
+ synchronized (mWindowMap) {
+ if (DEBUG_STACK) Slog.i(TAG, "moveTaskToStack: moving taskId=" + taskId
+ + " to stackId=" + stackId + " at " + (toTop ? "top" : "bottom"));
+ Task task = mTaskIdToTask.get(taskId);
+ if (task == null) {
+ if (DEBUG_STACK) Slog.i(TAG, "moveTaskToStack: could not find taskId=" + taskId);
+ return;
+ }
+ TaskStack stack = mStackIdToStack.get(stackId);
+ if (stack == null) {
+ if (DEBUG_STACK) Slog.i(TAG, "moveTaskToStack: could not find stackId=" + stackId);
+ return;
+ }
+ task.moveTaskToStack(stack, toTop);
+ final DisplayContent displayContent = stack.getDisplayContent();
+ displayContent.layoutNeeded = true;
+ performLayoutAndPlaceSurfacesLocked();
+ }
+ }
+
/**
* Re-sizes the specified stack and its containing windows.
* Returns a {@link Configuration} object that contains configurations settings
@@ -5128,6 +5151,24 @@
bounds.setEmpty();
}
+ /** Returns the id of an application (non-home stack) stack that match the input bounds.
+ * -1 if no stack matches.*/
+ public int getStackIdWithBounds(Rect bounds) {
+ Rect stackBounds = new Rect();
+ synchronized (mWindowMap) {
+ for (int i = mStackIdToStack.size() - 1; i >= 0; --i) {
+ TaskStack stack = mStackIdToStack.valueAt(i);
+ if (stack.mStackId != HOME_STACK_ID) {
+ stack.getBounds(stackBounds);
+ if (stackBounds.equals(bounds)) {
+ return stack.mStackId;
+ }
+ }
+ }
+ }
+ return -1;
+ }
+
/** Forces the stack to fullscreen if input is true, else un-forces the stack from fullscreen.
* Returns a {@link Configuration} object that contains configurations settings
* that should be overridden due to the operation.