diff options
11 files changed, 303 insertions, 79 deletions
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 @@ public class Am extends BaseCommand { " 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 @@ public class Am extends BaseCommand { "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 @@ public class Am extends BaseCommand { "\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 @@ public class Am extends BaseCommand { 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 @@ public class Am extends BaseCommand { runTaskLock(); } else if (op.equals("resizeable")) { runTaskResizeable(); + } else if (op.equals("resize")) { + runTaskResize(); } else { showError("Error: unknown command '" + op + "'"); return; @@ -1890,6 +1878,20 @@ public class Am extends BaseCommand { } } + 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 @@ public class Am extends BaseCommand { } 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 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM 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 @@ class ActivityManagerProxy implements IActivityManager } @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 interface IActivityManager extends IInterface { 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 @@ public interface IActivityManager extends IInterface { 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 @@ public final class ViewRootImpl implements ViewParent, 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 @@ public final class ViewRootImpl implements ViewParent, mReportNextDraw = true; } - if (mView != null) { - forceLayout(mView); - } - requestLayout(); } break; @@ -3262,9 +3247,6 @@ public final class ViewRootImpl implements ViewParent, 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 @@ public class MediaProjectionPermissionActivity extends Activity @Override protected void onDestroy() { super.onDestroy(); - mDialog.dismiss(); + if (mDialog != null) { + mDialog.dismiss(); + } } @Override @@ -128,7 +130,9 @@ public class MediaProjectionPermissionActivity extends Activity 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 @@ public final class ActivityManagerService extends ActivityManagerNative } @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 @@ final class ActivityStack { * 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 @@ final class ActivityStack { return count; } + int numTasks() { + return mTaskHistory.size(); + } + ActivityStack(ActivityStackSupervisor.ActivityContainer activityContainer, RecentTasks recentTasks) { mActivityContainer = activityContainer; @@ -1154,6 +1158,23 @@ final class ActivityStack { 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 @@ final class ActivityStack { 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 class ActivityStack { 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 class ActivityStack { 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 @@ final class ActivityStack { 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 @@ final class ActivityStack { } 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 @@ final class ActivityStack { } 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 @@ public final class ActivityStackSupervisor implements DisplayListener { 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 @@ public final class ActivityStackSupervisor implements DisplayListener { } ActivityRecord resumedAppLocked() { - ActivityStack stack = getFocusedStack(); + ActivityStack stack = mFocusedStack; if (stack == null) { return null; } @@ -739,7 +739,7 @@ public final class ActivityStackSupervisor implements DisplayListener { } ActivityRecord topRunningActivityLocked() { - final ActivityStack focusedStack = getFocusedStack(); + final ActivityStack focusedStack = mFocusedStack; ActivityRecord r = focusedStack.topRunningActivityLocked(null); if (r != null) { return r; @@ -885,7 +885,7 @@ public final class ActivityStackSupervisor implements DisplayListener { final ActivityStack stack; if (container == null || container.mStack.isOnHomeDisplay()) { - stack = getFocusedStack(); + stack = mFocusedStack; } else { stack = container.mStack; } @@ -1502,7 +1502,7 @@ public final class ActivityStackSupervisor implements DisplayListener { 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 @@ public final class ActivityStackSupervisor implements DisplayListener { 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 @@ public final class ActivityStackSupervisor implements DisplayListener { // 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 @@ public final class ActivityStackSupervisor implements DisplayListener { 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 @@ public final class ActivityStackSupervisor implements DisplayListener { } } + /** 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 @@ public final class ActivityStackSupervisor implements DisplayListener { 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 @@ public final class ActivityStackSupervisor implements DisplayListener { 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 @@ public final class ActivityStackSupervisor implements DisplayListener { } 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 @@ public final class ActivityStackSupervisor implements DisplayListener { } 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..b8f26c9 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 @@ class Task { 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 @@ public class WindowManagerService extends IWindowManager.Stub 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 @@ public class WindowManagerService extends IWindowManager.Stub + " 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 class WindowManagerService extends IWindowManager.Stub } } + 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 @@ public class WindowManagerService extends IWindowManager.Stub 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. |
