diff options
author | TreeHugger Robot <treehugger-gerrit@google.com> | 2017-01-11 19:14:52 +0000 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2017-01-11 19:14:55 +0000 |
commit | 3c6f28aa5968b1edb823495efa15e7358de5261e (patch) | |
tree | 705dec4140ec55530700827d0214390404e7e7c3 | |
parent | 801e7bb7fde79eebd250debdf4e768c82a3a4e86 (diff) | |
parent | e1fe7fa288a34ecaaab390f49ef540edc4a6c52d (diff) |
Merge "Added TaskWindowContainerController"
20 files changed, 740 insertions, 505 deletions
diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl index a2d9c45035d3..2ed9eab46277 100644 --- a/core/java/android/app/IActivityManager.aidl +++ b/core/java/android/app/IActivityManager.aidl @@ -590,6 +590,12 @@ interface IActivityManager { void dismissKeyguard(in IBinder token, in IKeyguardDismissCallback callback); int restartUserInBackground(int userId); + /** Cancels the window transitions for the given task. */ + void cancelTaskWindowTransition(int taskId); + + /** Cancels the thumbnail transitions for the given task. */ + void cancelTaskThumbnailTransition(int taskId); + // WARNING: when these transactions are updated, check if they are any callers on the native // side. If so, make sure they are using the correct transaction ids and arguments. // If a transaction which will also be used on the native side is being inserted, add it diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl index 8611d69ba94d..c0ebd2c4b8e7 100644 --- a/core/java/android/view/IWindowManager.aidl +++ b/core/java/android/view/IWindowManager.aidl @@ -190,16 +190,6 @@ interface IWindowManager void enableSurfaceTrace(in ParcelFileDescriptor fd); void disableSurfaceTrace(); - /** - * Cancels the window transitions for the given task. - */ - void cancelTaskWindowTransition(int taskId); - - /** - * Cancels the thumbnail transitions for the given task. - */ - void cancelTaskThumbnailTransition(int taskId); - // These can only be called with the SET_ORIENTATION permission. /** * Update the current screen rotation based on the current state of diff --git a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java index 05df63467c02..779113216530 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java +++ b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java @@ -567,10 +567,10 @@ public class SystemServicesProxy { * Cancels the current window transtion to/from Recents for the given task id. */ public void cancelWindowTransition(int taskId) { - if (mWm == null) return; + if (mIam == null) return; try { - WindowManagerGlobal.getWindowManagerService().cancelTaskWindowTransition(taskId); + mIam.cancelTaskWindowTransition(taskId); } catch (RemoteException e) { e.printStackTrace(); } @@ -580,10 +580,10 @@ public class SystemServicesProxy { * Cancels the current thumbnail transtion to/from Recents for the given task id. */ public void cancelThumbnailTransition(int taskId) { - if (mWm == null) return; + if (mIam == null) return; try { - WindowManagerGlobal.getWindowManagerService().cancelTaskThumbnailTransition(taskId); + mIam.cancelTaskThumbnailTransition(taskId); } catch (RemoteException e) { e.printStackTrace(); } diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 3b2041e499ab..2c1871da6439 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -367,6 +367,7 @@ import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_VISIBLE_B import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM; import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME; import static com.android.server.am.ActivityStackSupervisor.ActivityContainer.FORCE_NEW_TASK_FLAGS; +import static com.android.server.am.ActivityStackSupervisor.CREATE_IF_NEEDED; import static com.android.server.am.ActivityStackSupervisor.DEFER_RESUME; import static com.android.server.am.ActivityStackSupervisor.FORCE_FOCUS; import static com.android.server.am.ActivityStackSupervisor.ON_TOP; @@ -9527,12 +9528,7 @@ public class ActivityManagerService extends IActivityManager.Stub Slog.w(TAG, "setTaskResizeable: taskId=" + taskId + " not found"); return; } - if (task.mResizeMode != resizeableMode) { - task.mResizeMode = resizeableMode; - mWindowManager.setTaskResizeable(taskId, resizeableMode); - mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS); - mStackSupervisor.resumeFocusedStackTopActivityLocked(); - } + task.setResizeMode(resizeableMode); } } @@ -9565,13 +9561,12 @@ public class ActivityManagerService extends IActivityManager.Stub } boolean preserveWindow = (resizeMode & RESIZE_MODE_PRESERVE_WINDOW) != 0; if (stackId != task.getStackId()) { - mStackSupervisor.moveTaskToStackUncheckedLocked( - task, stackId, ON_TOP, !FORCE_FOCUS, "resizeTask"); + mStackSupervisor.moveTaskToStackUncheckedLocked(task, stackId, ON_TOP, + !FORCE_FOCUS, "resizeTask", true /* allowStackOnTop */); preserveWindow = false; } - mStackSupervisor.resizeTaskLocked(task, bounds, resizeMode, preserveWindow, - false /* deferResume */); + task.resize(bounds, resizeMode, preserveWindow, false /* deferResume */); } } finally { Binder.restoreCallingIdentity(ident); @@ -9594,7 +9589,7 @@ public class ActivityManagerService extends IActivityManager.Stub if (task.getStack() != null) { // Return the bounds from window manager since it will be adjusted for various // things like the presense of a docked stack for tasks that aren't resizeable. - mWindowManager.getTaskBounds(task.taskId, rect); + task.getWindowContainerBounds(rect); } else { // Task isn't in window manager yet since it isn't associated with a stack. // Return the persist value from activity manager @@ -9612,6 +9607,44 @@ public class ActivityManagerService extends IActivityManager.Stub } @Override + public void cancelTaskWindowTransition(int taskId) { + enforceCallingPermission(MANAGE_ACTIVITY_STACKS, "cancelTaskWindowTransition()"); + final long ident = Binder.clearCallingIdentity(); + try { + synchronized (this) { + final TaskRecord task = mStackSupervisor.anyTaskForIdLocked( + taskId, !RESTORE_FROM_RECENTS, INVALID_STACK_ID); + if (task == null) { + Slog.w(TAG, "cancelTaskWindowTransition: taskId=" + taskId + " not found"); + return; + } + task.cancelWindowTransition(); + } + } finally { + Binder.restoreCallingIdentity(ident); + } + } + + @Override + public void cancelTaskThumbnailTransition(int taskId) { + enforceCallingPermission(MANAGE_ACTIVITY_STACKS, "cancelTaskThumbnailTransition()"); + final long ident = Binder.clearCallingIdentity(); + try { + synchronized (this) { + final TaskRecord task = mStackSupervisor.anyTaskForIdLocked( + taskId, !RESTORE_FROM_RECENTS, INVALID_STACK_ID); + if (task == null) { + Slog.w(TAG, "cancelTaskThumbnailTransition: taskId=" + taskId + " not found"); + return; + } + task.cancelThumbnailTransition(); + } + } finally { + Binder.restoreCallingIdentity(ident); + } + } + + @Override public Bitmap getTaskDescriptionIcon(String filePath, int userId) { if (userId != UserHandle.getCallingUserId()) { enforceCallingPermission(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, @@ -9949,7 +9982,7 @@ public class ActivityManagerService extends IActivityManager.Stub // Defer the resume so resume/pausing while moving stacks is dangerous. mStackSupervisor.moveTaskToStackLocked(topTask.taskId, DOCKED_STACK_ID, false /* toTop */, !FORCE_FOCUS, "swapDockedAndFullscreenStack", - ANIMATE, true /* deferResume */); + ANIMATE, true /* deferResume */, true /* allowStackOnTop */); final int size = tasks.size(); for (int i = 0; i < size; i++) { final int id = tasks.get(i).taskId; @@ -9958,7 +9991,8 @@ public class ActivityManagerService extends IActivityManager.Stub } mStackSupervisor.moveTaskToStackLocked(id, FULLSCREEN_WORKSPACE_STACK_ID, true /* toTop */, !FORCE_FOCUS, - "swapDockedAndFullscreenStack", ANIMATE, true /* deferResume */); + "swapDockedAndFullscreenStack", ANIMATE, true /* deferResume */, + true /* allowStackOnTop */); } // Because we deferred the resume, to avoid conflicts with stack switches while @@ -9999,7 +10033,7 @@ public class ActivityManagerService extends IActivityManager.Stub mWindowManager.setDockedStackCreateState(createMode, initialBounds); final boolean moved = mStackSupervisor.moveTaskToStackLocked( taskId, DOCKED_STACK_ID, toTop, !FORCE_FOCUS, "moveTaskToDockedStack", - animate, DEFER_RESUME); + animate, DEFER_RESUME, true /* allowStackOnTop */); if (moved) { if (moveHomeStackFront) { mStackSupervisor.moveHomeStackToFront("moveTaskToDockedStack"); @@ -10113,10 +10147,12 @@ public class ActivityManagerService extends IActivityManager.Stub synchronized (this) { long ident = Binder.clearCallingIdentity(); try { - if (DEBUG_STACK) Slog.d(TAG_STACK, - "positionTaskInStack: positioning task=" + taskId - + " in stackId=" + stackId + " at position=" + position); - mStackSupervisor.positionTaskInStackLocked(taskId, stackId, position); + if (DEBUG_STACK) Slog.d(TAG_STACK, "positionTaskInStack: positioning task=" + + taskId + " in stackId=" + stackId + " at position=" + position); + final ActivityStack stack = mStackSupervisor.getStack(stackId, CREATE_IF_NEEDED, + !ON_TOP); + + stack.positionChildAt(taskId, position); } finally { Binder.restoreCallingIdentity(ident); } diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java index 0e4ab96cccb4..2963ad1d54f6 100644 --- a/services/core/java/com/android/server/am/ActivityRecord.java +++ b/services/core/java/com/android/server/am/ActivityRecord.java @@ -41,7 +41,6 @@ import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE_VIA_SDK_VER import static android.content.pm.ActivityInfo.RESIZE_MODE_UNRESIZEABLE; import static android.os.Build.VERSION_CODES.HONEYCOMB; import static android.os.Process.SYSTEM_UID; -import static android.view.Display.DEFAULT_DISPLAY; import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_CONFIGURATION; import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_SAVED_STATE; import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_SCREENSHOTS; @@ -75,7 +74,6 @@ import android.content.res.CompatibilityInfo; import android.content.res.Configuration; import android.graphics.Bitmap; import android.graphics.Rect; -import android.os.Build; import android.os.Bundle; import android.os.Debug; import android.os.IBinder; @@ -103,6 +101,7 @@ import com.android.server.am.ActivityStack.ActivityState; import com.android.server.am.ActivityStackSupervisor.ActivityContainer; import com.android.server.wm.AppWindowContainerController; import com.android.server.wm.AppWindowContainerListener; +import com.android.server.wm.TaskWindowContainerController; import java.io.File; import java.io.IOException; @@ -724,6 +723,10 @@ final class ActivityRecord implements AppWindowContainerListener { null : ComponentName.unflattenFromString(aInfo.requestedVrComponent); } + AppWindowContainerController getWindowContainerController() { + return mWindowContainerController; + } + void createWindowContainer() { if (mWindowContainerController != null) { throw new IllegalArgumentException("Window container=" + mWindowContainerController @@ -734,9 +737,10 @@ final class ActivityRecord implements AppWindowContainerListener { inHistory = true; task.updateOverrideConfigurationFromLaunchBounds(); + final TaskWindowContainerController taskController = task.getWindowContainerController(); - mWindowContainerController = new AppWindowContainerController(appToken, this, task.taskId, - Integer.MAX_VALUE /* add on top */, info.screenOrientation, fullscreen, + mWindowContainerController = new AppWindowContainerController(taskController, appToken, + this, Integer.MAX_VALUE /* add on top */, info.screenOrientation, fullscreen, (info.flags & FLAG_SHOW_FOR_ALL_USERS) != 0, info.configChanges, task.voiceSession != null, mLaunchTaskBehind, isAlwaysFocusable(), appInfo.targetSdkVersion, mRotationAnimationHint, @@ -749,12 +753,7 @@ final class ActivityRecord implements AppWindowContainerListener { void removeWindowContainer() { mWindowContainerController.removeContainer(getDisplayId()); - } - - // TODO: Remove once task record is converted to use controller in which case we can use - // positionChildAt() - void positionWindowContainerAt(int index) { - mWindowContainerController.positionAt(task.taskId, index); + mWindowContainerController = null; } private boolean isHomeIntent(Intent intent) { diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java index f7c3cea2eed6..ab65eb126150 100644 --- a/services/core/java/com/android/server/am/ActivityStack.java +++ b/services/core/java/com/android/server/am/ActivityStack.java @@ -737,7 +737,7 @@ final class ActivityStack extends ConfigurationContainer { task = topTask(); if (task != null) { - mWindowManager.moveTaskToTop(task.taskId); + task.moveWindowContainerToTop(true /* includingParents */); } } @@ -756,7 +756,7 @@ final class ActivityStack extends ConfigurationContainer { mTaskHistory.remove(task); mTaskHistory.add(0, task); updateTaskMovement(task, false); - mWindowManager.moveTaskToBottom(task.taskId); + task.moveWindowContainerToBottom(); } } @@ -2557,10 +2557,16 @@ final class ActivityStack extends ConfigurationContainer { position = Math.min(position, maxPosition); mTaskHistory.remove(task); mTaskHistory.add(position, task); + task.positionWindowContainerAt(mStackId, position); updateTaskMovement(task, true); } private void insertTaskAtTop(TaskRecord task, ActivityRecord newActivity) { + insertTaskAtTop(task, newActivity, true /* allowStackOnTop */); + } + + private void insertTaskAtTop(TaskRecord task, ActivityRecord newActivity, + boolean allowStackOnTop) { boolean isLastTaskOverHome = false; // If the moving task is over home stack, transfer its return type to next task if (task.isOverHomeStack()) { @@ -2619,7 +2625,7 @@ final class ActivityStack extends ConfigurationContainer { } mTaskHistory.add(taskNdx, task); updateTaskMovement(task, true); - mWindowManager.moveTaskToTop(task.taskId); + task.moveWindowContainerToTop(allowStackOnTop /* includingParents */); } final void startActivityLocked(ActivityRecord r, ActivityRecord focusedTopActivity, @@ -2863,7 +2869,7 @@ final class ActivityStack extends ConfigurationContainer { targetTask.addActivityAtBottom(p); } - mWindowManager.moveTaskToBottom(targetTask.taskId); + targetTask.moveWindowContainerToBottom(); replyChainEnd = -1; } else if (forceReset || finishOnTaskLaunch || clearWhenTaskReset) { // If the activity should just be removed -- either @@ -2999,7 +3005,7 @@ final class ActivityStack extends ConfigurationContainer { if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Pulling activity " + p + " from " + srcPos + " in to resetting task " + task); } - mWindowManager.moveTaskToTop(taskId); + task.moveWindowContainerToTop(true /* includingParents */); // Now we've moved it in to place... but what if this is // a singleTop activity and we have put it on top of another @@ -4368,7 +4374,7 @@ final class ActivityStack extends ConfigurationContainer { } mWindowManager.prepareAppTransition(TRANSIT_TASK_TO_BACK, false); - mWindowManager.moveTaskToBottom(taskId); + tr.moveWindowContainerToBottom(); final TaskRecord task = mResumedActivity != null ? mResumedActivity.task : null; if (prevIsHome || (task == tr && canGoHome) || (numTasks <= 1 && isOnHomeDisplay())) { @@ -4800,14 +4806,7 @@ final class ActivityStack extends ConfigurationContainer { */ void removeTask(TaskRecord task, String reason, int mode) { if (mode == REMOVE_TASK_MODE_DESTROYING) { - mStackSupervisor.removeLockedTaskLocked(task); - mWindowManager.removeTask(task.taskId); - if (!StackId.persistTaskBounds(mStackId)) { - // Reset current bounds for task whose bounds shouldn't be persisted so it uses - // default configuration the next time it launches. - task.updateOverrideConfiguration(null); - } - mService.mTaskChangeNotificationController.notifyTaskRemoved(task.taskId); + task.removeWindowContainer(); } final ActivityRecord r = mResumedActivity; @@ -4879,11 +4878,7 @@ final class ActivityStack extends ConfigurationContainer { && !isLockscreenShown) { task.updateOverrideConfiguration(mBounds); } - final Rect bounds = task.updateOverrideConfigurationFromLaunchBounds(); - final boolean showForAllUsers = (info.flags & FLAG_SHOW_FOR_ALL_USERS) != 0; - mWindowManager.addTask(taskId, mStackId, task.userId, bounds, - task.getOverrideConfiguration(), task.mResizeMode, task.isHomeTask(), - task.isOnTopLauncher(), toTop, showForAllUsers); + task.createWindowContainer(toTop, (info.flags & FLAG_SHOW_FOR_ALL_USERS) != 0); return task; } @@ -4900,11 +4895,16 @@ final class ActivityStack extends ConfigurationContainer { } void addTask(final TaskRecord task, final boolean toTop, String reason) { + addTask(task, toTop, reason, true /* allowStackOnTop */); + } + + void addTask(final TaskRecord task, final boolean toTop, String reason, + boolean allowStackOnTop) { final ActivityStack prevStack = preAddTask(task, reason, toTop); task.setStack(this); if (toTop) { - insertTaskAtTop(task, null); + insertTaskAtTop(task, null, allowStackOnTop); } else { mTaskHistory.add(0, task); updateTaskMovement(task, false); @@ -4912,13 +4912,20 @@ final class ActivityStack extends ConfigurationContainer { postAddTask(task, prevStack); } - /** @see ActivityManagerService#positionTaskInStack(int, int, int). */ - void positionTask(final TaskRecord task, int position) { + void positionChildAt(int taskId, int index) { + final TaskRecord task = mStackSupervisor.anyTaskForIdLocked(taskId); + if (task == null) { + Slog.w(TAG, "positionTaskInStackLocked: no task for id=" + taskId); + return; + } + + task.updateOverrideConfigurationForStack(this); + final ActivityRecord topRunningActivity = task.topRunningActivityLocked(); final boolean wasResumed = topRunningActivity == task.getStack().mResumedActivity; final ActivityStack prevStack = preAddTask(task, "positionTask", !ON_TOP); task.setStack(this); - insertTaskAtPosition(task, position); + insertTaskAtPosition(task, index); postAddTask(task, prevStack); if (wasResumed) { if (mResumedActivity != null) { @@ -4928,6 +4935,11 @@ final class ActivityStack extends ConfigurationContainer { } mResumedActivity = topRunningActivity; } + + // The task might have already been running and its visibility needs to be synchronized with + // the visibility of the stack / windows. + ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS); + mStackSupervisor.resumeFocusedStackTopActivityLocked(); } private ActivityStack preAddTask(TaskRecord task, String reason, boolean toTop) { diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java index a93524903b29..8cf0708e22aa 100644 --- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java +++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java @@ -89,6 +89,8 @@ import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_LAUNCHABLE_PRIV; import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_PINNABLE; import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_WHITELISTED; import static com.android.server.wm.AppTransition.TRANSIT_DOCK_TASK_FROM_RECENTS; +import static java.lang.Integer.MAX_VALUE; +import static java.lang.Integer.MIN_VALUE; import android.Manifest; import android.annotation.NonNull; @@ -175,7 +177,6 @@ import java.util.ArrayList; 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 { @@ -1932,7 +1933,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D } if (stackId != currentStack.mStackId) { currentStack = moveTaskToStackUncheckedLocked(task, stackId, ON_TOP, - !FORCE_FOCUS, reason); + !FORCE_FOCUS, reason, true /* allowStackOnTop */); stackId = currentStack.mStackId; // moveTaskToStackUncheckedLocked() should already placed the task on top, // still need moveTaskToFrontLocked() below for any transition settings. @@ -1945,9 +1946,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D // WM resizeTask must be done after the task is moved to the correct stack, // because Task's setBounds() also updates dim layer's bounds, but that has // dependency on the stack. - mWindowManager.resizeTask(task.taskId, task.mBounds, - task.getOverrideConfiguration(), false /* relayout */, - false /* forced */); + task.resizeWindowContainer(); } } } @@ -2173,8 +2172,10 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D continueUpdateBounds(HOME_STACK_ID); for (int i = mResizingTasksDuringAnimation.size() - 1; i >= 0; i--) { final int taskId = mResizingTasksDuringAnimation.valueAt(i); - if (anyTaskForIdLocked(taskId, !RESTORE_FROM_RECENTS, INVALID_STACK_ID) != null) { - mWindowManager.setTaskDockedResizing(taskId, false); + final TaskRecord task = + anyTaskForIdLocked(taskId, !RESTORE_FROM_RECENTS, INVALID_STACK_ID); + if (task != null) { + task.setTaskDockedResizing(false); } } mResizingTasksDuringAnimation.clear(); @@ -2220,7 +2221,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D // display because it no longer contains any tasks. mAllowDockedStackResize = false; } - final ActivityStack fullscreenStack = getStack(FULLSCREEN_WORKSPACE_STACK_ID); + ActivityStack fullscreenStack = getStack(FULLSCREEN_WORKSPACE_STACK_ID); final boolean isFullscreenStackVisible = fullscreenStack != null && fullscreenStack.getStackVisibilityLocked(null) == STACK_VISIBLE; final ArrayList<TaskRecord> tasks = stack.getAllTasks(); @@ -2237,15 +2238,18 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D } moveTaskToStackLocked(tasks.get(i).taskId, FULLSCREEN_WORKSPACE_STACK_ID, onTop, onTop /*forceFocus*/, - "moveTasksToFullscreenStack", ANIMATE, DEFER_RESUME); + "moveTasksToFullscreenStack - onTop", ANIMATE, DEFER_RESUME, + true /* allowStackOnTop */); } ensureActivitiesVisibleLocked(null, 0, PRESERVE_WINDOWS); resumeFocusedStackTopActivityLocked(); } else { - for (int i = size - 1; i >= 0; i--) { - positionTaskInStackLocked(tasks.get(i).taskId, - FULLSCREEN_WORKSPACE_STACK_ID, 0 /* position */); + for (int i = 0; i < size; i++) { + moveTaskToStackLocked(tasks.get(i).taskId, FULLSCREEN_WORKSPACE_STACK_ID, + true /* onTop */, false /* forceFocus */, + "moveTasksToFullscreenStack - NOT_onTop", !ANIMATE, DEFER_RESUME, + false /* allowStackOnTop */); } } } finally { @@ -2346,71 +2350,6 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D } } - boolean resizeTaskLocked(TaskRecord task, Rect bounds, int resizeMode, boolean preserveWindow, - boolean deferResume) { - if (!task.isResizeable()) { - Slog.w(TAG, "resizeTask: task " + task + " not resizeable."); - return true; - } - - // If this is a forced resize, let it go through even if the bounds is not changing, - // as we might need a relayout due to surface size change (to/from fullscreen). - final boolean forced = (resizeMode & RESIZE_MODE_FORCED) != 0; - if (Objects.equals(task.mBounds, bounds) && !forced) { - // Nothing to do here... - return true; - } - bounds = TaskRecord.validateBounds(bounds); - - if (!mWindowManager.isValidTaskId(task.taskId)) { - // Task doesn't exist in window manager yet (e.g. was restored from recents). - // All we can do for now is update the bounds so it can be used when the task is - // added to window manager. - task.updateOverrideConfiguration(bounds); - if (task.getStackId() != FREEFORM_WORKSPACE_STACK_ID) { - // re-restore the task so it can have the proper stack association. - restoreRecentTaskLocked(task, FREEFORM_WORKSPACE_STACK_ID); - } - return true; - } - - if (!task.canResizeToBounds(bounds)) { - throw new IllegalArgumentException("resizeTaskLocked: Can not resize task=" + task - + " to bounds=" + bounds + " resizeMode=" + task.mResizeMode); - } - - // Do not move the task to another stack here. - // This method assumes that the task is already placed in the right stack. - // we do not mess with that decision and we only do the resize! - - Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "am.resizeTask_" + task.taskId); - - final boolean updatedConfig = task.updateOverrideConfiguration(bounds); - // This variable holds information whether the configuration didn't change in a significant - // way and the activity was kept the way it was. If it's false, it means the activity had - // to be relaunched due to configuration change. - boolean kept = true; - if (updatedConfig) { - final ActivityRecord r = task.topRunningActivityLocked(); - if (r != null) { - kept = r.ensureActivityConfigurationLocked(0 /* globalChanges */, preserveWindow); - - if (!deferResume) { - // All other activities must be made visible with their correct configuration. - ensureActivitiesVisibleLocked(r, 0, !PRESERVE_WINDOWS); - if (!kept) { - resumeFocusedStackTopActivityLocked(); - } - } - } - } - mWindowManager.resizeTask(task.taskId, task.mBounds, task.getOverrideConfiguration(), kept, - forced); - - Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER); - return kept; - } - ActivityStack createStackOnDisplay(int stackId, int displayId, boolean onTop) { ActivityDisplay activityDisplay = mActivityDisplays.get(displayId); if (activityDisplay == null) { @@ -2424,7 +2363,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D } /** - * Removes the stack associed with the given {@param stackId}. If the {@param stackId} is the + * Removes the stack associated with the given {@param stackId}. If the {@param stackId} is the * pinned stack, then its tasks are not explicitly removed when the stack is destroyed, but * instead moved back onto the fullscreen stack. */ @@ -2446,8 +2385,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D final int insertPosition = isFullscreenStackVisible ? Math.max(0, fullscreenStack.getChildCount() - 1) : fullscreenStack.getChildCount(); - positionTaskInStackLocked(tasks.get(i).taskId, FULLSCREEN_WORKSPACE_STACK_ID, - insertPosition); + fullscreenStack.positionChildAt(tasks.get(i).taskId, insertPosition); } ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS); resumeFocusedStackTopActivityLocked(); @@ -2577,7 +2515,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D * or is not a static stack). * @return true if the task has been restored successfully. */ - private boolean restoreRecentTaskLocked(TaskRecord task, int stackId) { + boolean restoreRecentTaskLocked(TaskRecord task, int stackId) { if (!StackId.isStaticStack(stackId)) { // If stack is not static (or stack id is invalid) - use the default one. // This means that tasks that were on external displays will be restored on the @@ -2612,10 +2550,8 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D } stack.addTask(task, false /* toTop */, "restoreRecentTask"); - final Rect bounds = task.updateOverrideConfigurationFromLaunchBounds(); - mWindowManager.addTask(task.taskId, stack.mStackId, task.userId, bounds, - task.getOverrideConfiguration(), task.mResizeMode, task.isHomeTask(), - task.isOnTopLauncher(), false /* toTop */, true /* showForAllUsers */); + // TODO: move call for creation here and other place into Stack.addTask() + task.createWindowContainer(false /* toTop */, true /* showForAllUsers */); if (DEBUG_RECENTS) Slog.v(TAG_RECENTS, "Added restored task=" + task + " to stack=" + stack); final ArrayList<ActivityRecord> activities = task.mActivities; @@ -2669,10 +2605,13 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D * @param toTop True if the task should be placed at the top of the stack. * @param forceFocus if focus should be moved to the new stack * @param reason Reason the task is been moved. + * @param allowStackOnTop If stack movement should be moved to the top due to the addition of + * the task to the stack. E.g. Moving the stack to the front because it + * should be focused because it now contains the focused activity. * @return The stack the task was moved to. */ - ActivityStack moveTaskToStackUncheckedLocked( - TaskRecord task, int stackId, boolean toTop, boolean forceFocus, String reason) { + ActivityStack moveTaskToStackUncheckedLocked(TaskRecord task, int stackId, boolean toTop, + boolean forceFocus, String reason, boolean allowStackOnTop) { if (StackId.isMultiWindowStack(stackId) && !mService.mSupportsMultiWindow) { throw new IllegalStateException("moveTaskToStackUncheckedLocked: Device doesn't " @@ -2703,15 +2642,15 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D // if a docked stack is created below which will lead to the stack we are moving from and // its resizeable tasks being resized. task.mTemporarilyUnresizable = true; - final ActivityStack stack = getStack(stackId, CREATE_IF_NEEDED, toTop); + final ActivityStack stack = getStack(stackId, CREATE_IF_NEEDED, toTop && allowStackOnTop); task.mTemporarilyUnresizable = false; - mWindowManager.moveTaskToStack(task.taskId, stack.mStackId, toTop); - stack.addTask(task, toTop, reason); + task.reparentWindowContainer(stack.mStackId, toTop ? MAX_VALUE : MIN_VALUE); + stack.addTask(task, toTop, reason, allowStackOnTop); // If the task had focus before (or we're requested to move focus), // move focus to the new stack by moving the stack to the front. stack.moveToFrontAndResumeStateIfNeeded( - r, forceFocus || wasFocused || wasFront, wasResumed, reason); + r, allowStackOnTop && (forceFocus || wasFocused || wasFront), wasResumed, reason); return stack; } @@ -2719,11 +2658,11 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D boolean moveTaskToStackLocked(int taskId, int stackId, boolean toTop, boolean forceFocus, String reason, boolean animate) { return moveTaskToStackLocked(taskId, stackId, toTop, forceFocus, reason, animate, - false /* deferResume */); + false /* deferResume */, true /* allowStackOnTop */); } boolean moveTaskToStackLocked(int taskId, int stackId, boolean toTop, boolean forceFocus, - String reason, boolean animate, boolean deferResume) { + String reason, boolean animate, boolean deferResume, boolean allowStackOnTop) { final TaskRecord task = anyTaskForIdLocked(taskId); if (task == null) { Slog.w(TAG, "moveTaskToStack: no task for id=" + taskId); @@ -2763,7 +2702,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D boolean kept = true; try { final ActivityStack stack = moveTaskToStackUncheckedLocked( - task, stackId, toTop, forceFocus, reason + " moveTaskToStack"); + task, stackId, toTop, forceFocus, reason + " moveTaskToStack", allowStackOnTop); stackId = stack.mStackId; if (!animate) { @@ -2775,19 +2714,18 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D // Make sure the task has the appropriate bounds/size for the stack it is in. if (stackId == FULLSCREEN_WORKSPACE_STACK_ID && task.mBounds != null) { - kept = resizeTaskLocked(task, stack.mBounds, RESIZE_MODE_SYSTEM, - !mightReplaceWindow, deferResume); + kept = task.resize(stack.mBounds, RESIZE_MODE_SYSTEM, !mightReplaceWindow, + deferResume); } else if (stackId == FREEFORM_WORKSPACE_STACK_ID) { Rect bounds = task.getLaunchBounds(); if (bounds == null) { stack.layoutTaskInStack(task, null); bounds = task.mBounds; } - kept = resizeTaskLocked(task, bounds, RESIZE_MODE_FORCED, !mightReplaceWindow, - deferResume); + kept = task.resize(bounds, RESIZE_MODE_FORCED, !mightReplaceWindow, deferResume); } else if (stackId == DOCKED_STACK_ID || stackId == PINNED_STACK_ID) { - kept = resizeTaskLocked(task, stack.mBounds, RESIZE_MODE_SYSTEM, - !mightReplaceWindow, deferResume); + kept = task.resize(stack.mBounds, RESIZE_MODE_SYSTEM, !mightReplaceWindow, + deferResume); } } finally { mWindowManager.continueSurfaceLayout(); @@ -2917,28 +2855,6 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D return true; } - /** @see ActivityManagerService#positionTaskInStack(int, int, int). */ - void positionTaskInStackLocked(int taskId, int stackId, int position) { - final TaskRecord task = anyTaskForIdLocked(taskId); - if (task == null) { - Slog.w(TAG, "positionTaskInStackLocked: no task for id=" + taskId); - return; - } - final ActivityStack stack = getStack(stackId, CREATE_IF_NEEDED, !ON_TOP); - - task.updateOverrideConfigurationForStack(stack); - - // TODO: Return final position from WM for AM to use instead of duplicating computations in - // ActivityStack#insertTaskAtPosition. - mWindowManager.positionTaskInStack( - taskId, stackId, position, task.mBounds, task.getOverrideConfiguration()); - stack.positionTask(task, position); - // The task might have already been running and its visibility needs to be synchronized with - // the visibility of the stack / windows. - stack.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS); - resumeFocusedStackTopActivityLocked(); - } - ActivityRecord findTaskLocked(ActivityRecord r) { mTmpFindTaskResult.r = null; mTmpFindTaskResult.matchedByRootAffinity = false; @@ -3361,7 +3277,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D stack.switchUserLocked(userId); TaskRecord task = stack.topTask(); if (task != null) { - mWindowManager.moveTaskToTop(task.taskId); + task.moveWindowContainerToTop(true /* includingParents */); } } } @@ -3822,7 +3738,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D : task.getTopActivity() != null ? task.getTopActivity().packageName : "unknown"; taskBounds[i] = new Rect(); - mWindowManager.getTaskBounds(task.taskId, taskBounds[i]); + task.getWindowContainerBounds(taskBounds[i]); taskUserIds[i] = task.userId; } info.taskIds = taskIds; @@ -4777,11 +4693,11 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D /** * Puts a task into resizing mode during the next app transition. * - * @param taskId the id of the task to put into resizing mode + * @param task The task to put into resizing mode */ - private void setResizingDuringAnimation(int taskId) { - mResizingTasksDuringAnimation.add(taskId); - mWindowManager.setTaskDockedResizing(taskId, true); + private void setResizingDuringAnimation(TaskRecord task) { + mResizingTasksDuringAnimation.add(task.taskId); + task.setTaskDockedResizing(true); } final int startActivityFromRecentsInner(int taskId, Bundle bOptions) { @@ -4846,7 +4762,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D // the window renders full-screen with the background filling the void. Also only // call this at the end to make sure that tasks exists on the window manager side. if (launchStackId == DOCKED_STACK_ID) { - setResizingDuringAnimation(taskId); + setResizingDuringAnimation(task); } mService.mActivityStarter.postStartActivityUncheckedProcessing(task.getTopActivity(), @@ -4863,7 +4779,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D int result = mService.startActivityInPackage(callingUid, callingPackage, intent, null, null, null, 0, 0, bOptions, userId, null, task); if (launchStackId == DOCKED_STACK_ID) { - setResizingDuringAnimation(task.taskId); + setResizingDuringAnimation(task); } return result; } diff --git a/services/core/java/com/android/server/am/ActivityStarter.java b/services/core/java/com/android/server/am/ActivityStarter.java index 007a478ec683..61e3ad5ea052 100644 --- a/services/core/java/com/android/server/am/ActivityStarter.java +++ b/services/core/java/com/android/server/am/ActivityStarter.java @@ -1770,8 +1770,8 @@ class ActivityStarter { mInTask.updateOverrideConfiguration(mLaunchBounds); int stackId = mInTask.getLaunchStackId(); if (stackId != mInTask.getStackId()) { - final ActivityStack stack = mSupervisor.moveTaskToStackUncheckedLocked( - mInTask, stackId, ON_TOP, !FORCE_FOCUS, "inTaskToFront"); + final ActivityStack stack = mSupervisor.moveTaskToStackUncheckedLocked(mInTask, + stackId, ON_TOP, !FORCE_FOCUS, "inTaskToFront", true /* allowStackOnTop */); stackId = stack.mStackId; } if (StackId.resizeStackWithLaunchBounds(stackId)) { @@ -1824,7 +1824,7 @@ class ActivityStarter { mSupervisor.getNextTaskIdForUserLocked(mStartActivity.userId), mStartActivity.info, mIntent, null, null, true, mStartActivity.mActivityType); mStartActivity.setTask(task, null); - mWindowManager.moveTaskToTop(mStartActivity.task.taskId); + mStartActivity.task.moveWindowContainerToTop(true /* includingParents */); if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Starting new activity " + mStartActivity + " in new guessed " + mStartActivity.task); } diff --git a/services/core/java/com/android/server/am/TaskRecord.java b/services/core/java/com/android/server/am/TaskRecord.java index a17cf3b79cab..0d8829e97976 100644 --- a/services/core/java/com/android/server/am/TaskRecord.java +++ b/services/core/java/com/android/server/am/TaskRecord.java @@ -39,6 +39,7 @@ import android.graphics.Rect; import android.os.Debug; import android.os.ParcelFileDescriptor; import android.os.RemoteException; +import android.os.Trace; import android.os.UserHandle; import android.provider.Settings; import android.service.voice.IVoiceInteractionSession; @@ -48,6 +49,7 @@ import android.util.Slog; import com.android.internal.app.IVoiceInteractor; import com.android.internal.util.XmlUtils; +import com.android.server.wm.TaskWindowContainerController; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import org.xmlpull.v1.XmlSerializer; @@ -58,6 +60,7 @@ import java.io.PrintWriter; import java.util.ArrayList; import java.util.Objects; +import static android.app.ActivityManager.RESIZE_MODE_FORCED; import static android.app.ActivityManager.StackId.DOCKED_STACK_ID; import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID; import static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID; @@ -80,6 +83,7 @@ import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZEABLE; import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE; import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION; import static android.content.pm.ApplicationInfo.PRIVATE_FLAG_PRIVILEGED; +import static android.os.Trace.TRACE_TAG_ACTIVITY_MANAGER; import static android.provider.Settings.Secure.USER_SETUP_COMPLETE; import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_ADD_REMOVE; import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_LOCKTASK; @@ -95,6 +99,7 @@ import static com.android.server.am.ActivityRecord.APPLICATION_ACTIVITY_TYPE; import static com.android.server.am.ActivityRecord.HOME_ACTIVITY_TYPE; import static com.android.server.am.ActivityRecord.RECENTS_ACTIVITY_TYPE; import static com.android.server.am.ActivityRecord.STARTING_WINDOW_SHOWN; +import static com.android.server.am.ActivityStackSupervisor.PRESERVE_WINDOWS; final class TaskRecord extends ConfigurationContainer { private static final String TAG = TAG_WITH_CLASS_NAME ? "TaskRecord" : TAG_AM; @@ -280,6 +285,8 @@ final class TaskRecord extends ConfigurationContainer { /** Helper object used for updating override configuration. */ private Configuration mTmpConfig = new Configuration(); + private TaskWindowContainerController mWindowContainerController; + TaskRecord(ActivityManagerService service, int _taskId, ActivityInfo info, Intent _intent, IVoiceInteractionSession _voiceSession, IVoiceInteractor _voiceInteractor, int type) { mService = service; @@ -389,6 +396,155 @@ final class TaskRecord extends ConfigurationContainer { mService.mTaskChangeNotificationController.notifyTaskCreated(_taskId, realActivity); } + TaskWindowContainerController getWindowContainerController() { + return mWindowContainerController; + } + + void createWindowContainer(boolean onTop, boolean showForAllUsers) { + if (mWindowContainerController != null) { + throw new IllegalArgumentException("Window container=" + mWindowContainerController + + " already created for task=" + this); + } + + final Rect bounds = updateOverrideConfigurationFromLaunchBounds(); + final Configuration overrideConfig = getOverrideConfiguration(); + mWindowContainerController = new TaskWindowContainerController(taskId, getStackId(), userId, + bounds, overrideConfig, mResizeMode, isHomeTask(), isOnTopLauncher(), onTop, + showForAllUsers); + } + + void removeWindowContainer() { + mService.mStackSupervisor.removeLockedTaskLocked(this); + mWindowContainerController.removeContainer(); + if (!StackId.persistTaskBounds(getStackId())) { + // Reset current bounds for task whose bounds shouldn't be persisted so it uses + // default configuration the next time it launches. + updateOverrideConfiguration(null); + } + mService.mTaskChangeNotificationController.notifyTaskRemoved(taskId); + mWindowContainerController = null; + } + + void setResizeMode(int resizeMode) { + if (mResizeMode == resizeMode) { + return; + } + mResizeMode = resizeMode; + mWindowContainerController.setResizeable(resizeMode); + mService.mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS); + mService.mStackSupervisor.resumeFocusedStackTopActivityLocked(); + } + + void setTaskDockedResizing(boolean resizing) { + mWindowContainerController.setTaskDockedResizing(resizing); + } + + boolean resize(Rect bounds, int resizeMode, boolean preserveWindow, boolean deferResume) { + if (!isResizeable()) { + Slog.w(TAG, "resizeTask: task " + this + " not resizeable."); + return true; + } + + // If this is a forced resize, let it go through even if the bounds is not changing, + // as we might need a relayout due to surface size change (to/from fullscreen). + final boolean forced = (resizeMode & RESIZE_MODE_FORCED) != 0; + if (Objects.equals(mBounds, bounds) && !forced) { + // Nothing to do here... + return true; + } + bounds = validateBounds(bounds); + + if (mWindowContainerController == null) { + // Task doesn't exist in window manager yet (e.g. was restored from recents). + // All we can do for now is update the bounds so it can be used when the task is + // added to window manager. + updateOverrideConfiguration(bounds); + if (getStackId() != FREEFORM_WORKSPACE_STACK_ID) { + // re-restore the task so it can have the proper stack association. + mService.mStackSupervisor.restoreRecentTaskLocked(this, + FREEFORM_WORKSPACE_STACK_ID); + } + return true; + } + + if (!canResizeToBounds(bounds)) { + throw new IllegalArgumentException("resizeTask: Can not resize task=" + this + + " to bounds=" + bounds + " resizeMode=" + mResizeMode); + } + + // Do not move the task to another stack here. + // This method assumes that the task is already placed in the right stack. + // we do not mess with that decision and we only do the resize! + + Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "am.resizeTask_" + taskId); + + final boolean updatedConfig = updateOverrideConfiguration(bounds); + // This variable holds information whether the configuration didn't change in a significant + // way and the activity was kept the way it was. If it's false, it means the activity had + // to be relaunched due to configuration change. + boolean kept = true; + if (updatedConfig) { + final ActivityRecord r = topRunningActivityLocked(); + if (r != null) { + kept = r.ensureActivityConfigurationLocked(0 /* globalChanges */, preserveWindow); + + if (!deferResume) { + // All other activities must be made visible with their correct configuration. + mService.mStackSupervisor.ensureActivitiesVisibleLocked(r, 0, !PRESERVE_WINDOWS); + if (!kept) { + mService.mStackSupervisor.resumeFocusedStackTopActivityLocked(); + } + } + } + } + mWindowContainerController.resize(mBounds, getOverrideConfiguration(), kept, forced); + + Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER); + return kept; + } + + // TODO: Investigate combining with the resize() method above. + void resizeWindowContainer() { + mWindowContainerController.resize(mBounds, getOverrideConfiguration(), false /* relayout */, + false /* forced */); + } + + // TODO: Remove once we have a stack controller. + void positionWindowContainerAt(int stackId, int index) { + mWindowContainerController.positionAt(stackId, index, mBounds, getOverrideConfiguration()); + } + + // TODO: Replace with moveChildToTop? + void moveWindowContainerToTop(boolean includingParents) { + if (mWindowContainerController != null) { + mWindowContainerController.moveToTop(includingParents); + } + } + + // TODO: Replace with moveChildToBottom? + void moveWindowContainerToBottom() { + if (mWindowContainerController != null) { + mWindowContainerController.moveToBottom(); + } + } + + void getWindowContainerBounds(Rect bounds) { + mWindowContainerController.getBounds(bounds); + } + + // TODO: make this part of adding it to the stack? + void reparentWindowContainer(int stackId, int position) { + mWindowContainerController.reparent(stackId, position); + } + + void cancelWindowTransition() { + mWindowContainerController.cancelWindowTransition(); + } + + void cancelThumbnailTransition() { + mWindowContainerController.cancelThumbnailTransition(); + } + void touchActiveTime() { lastActiveTime = System.currentTimeMillis(); if (firstActiveTime == 0) { @@ -852,7 +1008,7 @@ final class TaskRecord extends ConfigurationContainer { // Sync. with window manager updateOverrideConfigurationFromLaunchBounds(); - r.positionWindowContainerAt(index); + mWindowContainerController.positionChildAt(r.getWindowContainerController(), index); r.onOverrideConfigurationSent(); } diff --git a/services/core/java/com/android/server/wm/AppWindowContainerController.java b/services/core/java/com/android/server/wm/AppWindowContainerController.java index cab39b56c3e9..76309847a172 100644 --- a/services/core/java/com/android/server/wm/AppWindowContainerController.java +++ b/services/core/java/com/android/server/wm/AppWindowContainerController.java @@ -31,7 +31,6 @@ import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; import android.content.res.CompatibilityInfo; import android.content.res.Configuration; import android.graphics.Bitmap; -import android.os.Binder; import android.os.Debug; import android.os.Handler; import android.os.IBinder; @@ -169,20 +168,21 @@ public class AppWindowContainerController } }; - public AppWindowContainerController(IApplicationToken token, - AppWindowContainerListener listener, int taskId, int index, int requestedOrientation, - boolean fullscreen, boolean showForAllUsers, int configChanges, + public AppWindowContainerController(TaskWindowContainerController taskController, + IApplicationToken token, AppWindowContainerListener listener, int index, + int requestedOrientation, boolean fullscreen, boolean showForAllUsers, int configChanges, boolean voiceInteraction, boolean launchTaskBehind, boolean alwaysFocusable, int targetSdkVersion, int rotationAnimationHint, long inputDispatchingTimeoutNanos) { - this(token, listener, taskId, index, requestedOrientation, fullscreen, showForAllUsers, + this(taskController, token, listener, index, requestedOrientation, fullscreen, + showForAllUsers, configChanges, voiceInteraction, launchTaskBehind, alwaysFocusable, targetSdkVersion, rotationAnimationHint, inputDispatchingTimeoutNanos, WindowManagerService.getInstance()); } - public AppWindowContainerController(IApplicationToken token, - AppWindowContainerListener listener, int taskId, int index, int requestedOrientation, - boolean fullscreen, boolean showForAllUsers, int configChanges, + public AppWindowContainerController(TaskWindowContainerController taskController, + IApplicationToken token, AppWindowContainerListener listener, int index, + int requestedOrientation, boolean fullscreen, boolean showForAllUsers, int configChanges, boolean voiceInteraction, boolean launchTaskBehind, boolean alwaysFocusable, int targetSdkVersion, int rotationAnimationHint, long inputDispatchingTimeoutNanos, WindowManagerService service) { @@ -196,11 +196,10 @@ public class AppWindowContainerController return; } - // TODO: Have the controller for the task passed in when task are changed to use - // controller. - final Task task = mService.mTaskIdToTask.get(taskId); + final Task task = taskController.mContainer; if (task == null) { - throw new IllegalArgumentException("addAppToken: invalid taskId=" + taskId); + throw new IllegalArgumentException("AppWindowContainerController: invalid " + + " controller=" + taskController); } atoken = new AppWindowToken(mService, token, voiceInteraction, task.getDisplayContent(), @@ -208,47 +207,27 @@ public class AppWindowContainerController requestedOrientation, rotationAnimationHint, configChanges, launchTaskBehind, alwaysFocusable, this); if (DEBUG_TOKEN_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG_WM, "addAppToken: " + atoken - + " task=" + taskId + " at " + index); + + " controller=" + taskController + " at " + index); task.addChild(atoken, index); } } public void removeContainer(int displayId) { - final long origId = Binder.clearCallingIdentity(); - try { - synchronized(mWindowMap) { - final DisplayContent dc = mRoot.getDisplayContent(displayId); - if (dc == null) { - Slog.w(TAG_WM, "removeAppToken: Attempted to remove binder token: " - + mToken + " from non-existing displayId=" + displayId); - return; - } - dc.removeAppToken(mToken.asBinder()); - super.removeContainer(); - } - } finally { - Binder.restoreCallingIdentity(origId); - } - } - - // TODO: Move to task window controller when that is created and rename to positionChildAt() - public void positionAt(int taskId, int index) { - synchronized(mService.mWindowMap) { - if (mContainer == null) { - Slog.w(TAG_WM, - "Attempted to position of non-existing app token: " + mToken); + synchronized(mWindowMap) { + final DisplayContent dc = mRoot.getDisplayContent(displayId); + if (dc == null) { + Slog.w(TAG_WM, "removeAppToken: Attempted to remove binder token: " + + mToken + " from non-existing displayId=" + displayId); return; } - - // TODO: Should get the window container from this owner when the task owner stuff is - // hooked-up. - final Task task = mService.mTaskIdToTask.get(taskId); - if (task == null) { - throw new IllegalArgumentException("positionChildAt: invalid taskId=" + taskId); - } - task.addChild(mContainer, index); + dc.removeAppToken(mToken.asBinder()); + super.removeContainer(); } + } + @Override + public void removeContainer() { + throw new UnsupportedOperationException("Use removeContainer(displayId) instead."); } public Configuration setOrientation(int requestedOrientation, int displayId, @@ -570,9 +549,7 @@ public class AppWindowContainerController "Attempted to freeze screen with non-existing app token: " + mContainer); return; } - final long origId = Binder.clearCallingIdentity(); mContainer.startFreezingScreen(); - Binder.restoreCallingIdentity(origId); } } @@ -581,11 +558,9 @@ public class AppWindowContainerController if (mContainer == null) { return; } - final long origId = Binder.clearCallingIdentity(); if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Clear freezing of " + mToken + ": hidden=" + mContainer.hidden + " freezing=" + mContainer.mAppAnimator.freezingScreen); mContainer.stopFreezingScreen(true, force); - Binder.restoreCallingIdentity(origId); } } @@ -635,4 +610,9 @@ public class AppWindowContainerController boolean keyDispatchingTimedOut(String reason) { return mListener != null && mListener.keyDispatchingTimedOut(reason); } + + @Override + public String toString() { + return "{AppWindowContainerController token=" + mToken + "}"; + } } diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java index a4685981fc35..b1b7542f62ce 100644 --- a/services/core/java/com/android/server/wm/Task.java +++ b/services/core/java/com/android/server/wm/Task.java @@ -22,6 +22,7 @@ import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID; import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZABLE_LANDSCAPE_ONLY; import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZABLE_PRESERVE_ORIENTATION; import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZABLE_PORTRAIT_ONLY; +import static com.android.server.EventLogTags.WM_TASK_REMOVED; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STACK; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TASK_MOVEMENT; import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME; @@ -89,8 +90,8 @@ class Task extends WindowContainer<AppWindowToken> implements DimLayer.DimLayerU private boolean mIsOnTopLauncher; Task(int taskId, TaskStack stack, int userId, WindowManagerService service, Rect bounds, - Configuration overrideConfig, boolean isOnTopLauncher, int resizeMode, - boolean homeTask) { + Configuration overrideConfig, boolean isOnTopLauncher, int resizeMode, boolean homeTask, + TaskWindowContainerController controller) { mTaskId = taskId; mStack = stack; mUserId = userId; @@ -98,6 +99,7 @@ class Task extends WindowContainer<AppWindowToken> implements DimLayer.DimLayerU mIsOnTopLauncher = isOnTopLauncher; mResizeMode = resizeMode; mHomeTask = homeTask; + setController(controller); setBounds(bounds, overrideConfig); } @@ -150,7 +152,7 @@ class Task extends WindowContainer<AppWindowToken> implements DimLayer.DimLayerU @Override void removeImmediately() { if (DEBUG_STACK) Slog.i(TAG, "removeTask: removing taskId=" + mTaskId); - EventLog.writeEvent(EventLogTags.WM_TASK_REMOVED, mTaskId, "removeTask"); + EventLog.writeEvent(WM_TASK_REMOVED, mTaskId, "removeTask"); mDeferRemoval = false; // Make sure to remove dim layer user first before removing task its from parent. @@ -160,19 +162,17 @@ class Task extends WindowContainer<AppWindowToken> implements DimLayer.DimLayerU } super.removeImmediately(); - mService.mTaskIdToTask.delete(mTaskId); } - // TODO: Change to use re-parenting in WC. - void moveTaskToStack(TaskStack stack, boolean toTop) { + void reparent(TaskStack stack, int position) { if (stack == mStack) { return; } - if (DEBUG_STACK) Slog.i(TAG, "moveTaskToStack: removing taskId=" + mTaskId + if (DEBUG_STACK) Slog.i(TAG, "reParentTask: removing taskId=" + mTaskId + " from stack=" + mStack); - EventLog.writeEvent(EventLogTags.WM_TASK_REMOVED, mTaskId, "moveTask"); + EventLog.writeEvent(WM_TASK_REMOVED, mTaskId, "reParentTask"); getParent().removeChild(this); - stack.addTask(this, toTop); + stack.addTask(this, position, showForAllUsers(), false /* moveParents */); } /** @see com.android.server.am.ActivityManagerService#positionTaskInStack(int, int, int). */ @@ -188,12 +188,13 @@ class Task extends WindowContainer<AppWindowToken> implements DimLayer.DimLayerU // and add to top of the target stack. We will move it proper position afterwards. if (DEBUG_STACK) Slog.i(TAG, "positionTaskInStack: removing taskId=" + mTaskId + " from stack=" + mStack); - EventLog.writeEvent(EventLogTags.WM_TASK_REMOVED, mTaskId, "moveTask"); + EventLog.writeEvent(WM_TASK_REMOVED, mTaskId, "positionTaskInStack"); mStack.removeChild(this); - stack.addTask(this, true /* toTop */); + stack.addTask(this, position); + } else { + stack.positionChildAt(position, this, true /* includingParents */); } - stack.positionChildAt(position, this, true /* includingParents */); resizeLocked(bounds, overrideConfig, false /* force */); for (int activityNdx = mChildren.size() - 1; activityNdx >= 0; --activityNdx) { @@ -225,7 +226,7 @@ class Task extends WindowContainer<AppWindowToken> implements DimLayer.DimLayerU super.removeChild(token); if (mChildren.isEmpty()) { - EventLog.writeEvent(EventLogTags.WM_TASK_REMOVED, mTaskId, "removeAppToken: last token"); + EventLog.writeEvent(WM_TASK_REMOVED, mTaskId, "removeAppToken: last token"); if (mDeferRemoval) { removeIfPossible(); } diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java index d7c7cfa319e1..eeea532858f1 100644 --- a/services/core/java/com/android/server/wm/TaskStack.java +++ b/services/core/java/com/android/server/wm/TaskStack.java @@ -507,8 +507,8 @@ public class TaskStack extends WindowContainer<Task> implements DimLayer.DimLaye } // TODO: Checkout the call points of this method and the ones below to see how they can fit in WC. - void addTask(Task task, boolean toTop) { - addTask(task, toTop, task.showForAllUsers()); + void addTask(Task task, int position) { + addTask(task, position, task.showForAllUsers(), true /* moveParents */); } /** @@ -516,10 +516,10 @@ public class TaskStack extends WindowContainer<Task> implements DimLayer.DimLaye * When task is added to top of the stack, the entire branch of the hierarchy (including stack * and display) will be brought to top. * @param task The task to add. - * @param toTop Whether to add it to the top or bottom. + * @param position Target position to add the task to. * @param showForAllUsers Whether to show the task regardless of the current user. */ - void addTask(Task task, boolean toTop, boolean showForAllUsers) { + void addTask(Task task, int position, boolean showForAllUsers, boolean moveParents) { final TaskStack currentStack = task.mStack; // TODO: We pass stack to task's constructor, but we still need to call this method. // This doesn't make sense, mStack will already be set equal to "this" at this point. @@ -529,14 +529,12 @@ public class TaskStack extends WindowContainer<Task> implements DimLayer.DimLaye + ", but it is already attached to stackId=" + task.mStack.mStackId); } - final int targetPosition = toTop ? mChildren.size() : 0; - // Add child task. task.mStack = this; - addChild(task, targetPosition); + addChild(task, null); // Move child to a proper position, as some restriction for position might apply. - positionChildAt(targetPosition, task, true /* includingParents */, showForAllUsers); + positionChildAt(position, task, moveParents /* includingParents */, showForAllUsers); } @Override @@ -546,7 +544,7 @@ public class TaskStack extends WindowContainer<Task> implements DimLayer.DimLaye /** * Overridden version of {@link TaskStack#positionChildAt(int, Task, boolean)}. Used in - * {@link TaskStack#addTask(Task, boolean, boolean showForAllUsers)}, as it can receive + * {@link TaskStack#addTask(Task, int, boolean showForAllUsers, boolean)}, as it can receive * showForAllUsers param from {@link AppWindowToken} instead of {@link Task#showForAllUsers()}. */ private void positionChildAt(int position, Task child, boolean includingParents, diff --git a/services/core/java/com/android/server/wm/TaskWindowContainerController.java b/services/core/java/com/android/server/wm/TaskWindowContainerController.java new file mode 100644 index 000000000000..9c303f811590 --- /dev/null +++ b/services/core/java/com/android/server/wm/TaskWindowContainerController.java @@ -0,0 +1,245 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +package com.android.server.wm; + +import android.content.res.Configuration; +import android.graphics.Rect; +import android.util.EventLog; +import android.util.Slog; + +import static com.android.server.EventLogTags.WM_TASK_CREATED; +import static com.android.server.wm.DragResizeMode.DRAG_RESIZE_MODE_DOCKED_DIVIDER; +import static com.android.server.wm.WindowContainer.POSITION_BOTTOM; +import static com.android.server.wm.WindowContainer.POSITION_TOP; +import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STACK; +import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; + +/** + * Controller for the task container. This is created by activity manager to link task records to + * the task container they use in window manager. + * + * Test class: {@link TaskWindowContainerControllerTests} + */ +public class TaskWindowContainerController + extends WindowContainerController<Task, WindowContainerListener> { + + private final int mTaskId; + + public TaskWindowContainerController(int taskId, int stackId, int userId, Rect bounds, + Configuration overrideConfig, int resizeMode, boolean homeTask, boolean isOnTopLauncher, + boolean toTop, boolean showForAllUsers) { + super(null, WindowManagerService.getInstance()); + mTaskId = taskId; + + synchronized(mWindowMap) { + if (DEBUG_STACK) Slog.i(TAG_WM, "TaskWindowContainerController: taskId=" + taskId + + " stackId=" + stackId + " bounds=" + bounds); + + // TODO: Pass controller for the stack to get the container object when stack is + // switched to use controller. + final TaskStack stack = mService.mStackIdToStack.get(stackId); + if (stack == null) { + throw new IllegalArgumentException("TaskWindowContainerController: invalid stackId=" + + stackId); + } + EventLog.writeEvent(WM_TASK_CREATED, taskId, stackId); + final Task task = new Task(taskId, stack, userId, mService, bounds, overrideConfig, + isOnTopLauncher, resizeMode, homeTask, this); + final int position = toTop ? POSITION_TOP : POSITION_BOTTOM; + stack.addTask(task, position, showForAllUsers, true /* moveParents */); + } + } + + @Override + public void removeContainer() { + synchronized(mWindowMap) { + if (mContainer == null) { + if (DEBUG_STACK) Slog.i(TAG_WM, "removeTask: could not find taskId=" + mTaskId); + return; + } + mContainer.removeIfPossible(); + super.removeContainer(); + } + } + + public void positionChildAt(AppWindowContainerController childController, int index) { + synchronized(mService.mWindowMap) { + final AppWindowToken aToken = childController.mContainer; + if (aToken == null) { + Slog.w(TAG_WM, + "Attempted to position of non-existing app : " + childController); + return; + } + + final Task task = mContainer; + if (task == null) { + throw new IllegalArgumentException("positionChildAt: invalid task=" + this); + } + task.addChild(aToken, index); + } + } + + public void reparent(int stackId, int position) { + synchronized (mWindowMap) { + if (DEBUG_STACK) Slog.i(TAG_WM, "reparent: moving taskId=" + mTaskId + + " to stackId=" + stackId + " at " + position); + if (mContainer == null) { + if (DEBUG_STACK) Slog.i(TAG_WM, + "reparent: could not find taskId=" + mTaskId); + return; + } + final TaskStack stack = mService.mStackIdToStack.get(stackId); + if (stack == null) { + if (DEBUG_STACK) Slog.i(TAG_WM, + "reparent: could not find stackId=" + stackId); + return; + } + mContainer.reparent(stack, position); + final DisplayContent displayContent = stack.getDisplayContent(); + displayContent.setLayoutNeeded(); + mService.mWindowPlacerLocked.performSurfacePlacement(); + } + } + + public void setResizeable(int resizeMode) { + synchronized (mWindowMap) { + if (mContainer != null) { + mContainer.setResizeable(resizeMode); + } + } + } + + public void resize(Rect bounds, Configuration overrideConfig, boolean relayout, + boolean forced) { + synchronized (mWindowMap) { + if (mContainer == null) { + throw new IllegalArgumentException("resizeTask: taskId " + mTaskId + " not found."); + } + + if (mContainer.resizeLocked(bounds, overrideConfig, forced) && relayout) { + mContainer.getDisplayContent().setLayoutNeeded(); + mService.mWindowPlacerLocked.performSurfacePlacement(); + } + } + } + + // TODO: Move to positionChildAt() in stack controller once we have a stack controller. + public void positionAt(int stackId, int index, Rect bounds, Configuration overrideConfig) { + synchronized (mWindowMap) { + if (DEBUG_STACK) Slog.i(TAG_WM, "positionChildAt: positioning taskId=" + mTaskId + + " in stackId=" + stackId + " at " + index); + if (mContainer == null) { + if (DEBUG_STACK) Slog.i(TAG_WM, + "positionTaskInStack: could not find taskId=" + mTaskId); + return; + } + final TaskStack stack = mService.mStackIdToStack.get(stackId); + if (stack == null) { + if (DEBUG_STACK) Slog.i(TAG_WM, + "positionTaskInStack: could not find stackId=" + stackId); + return; + } + mContainer.positionTaskInStack(stack, index, bounds, overrideConfig); + final DisplayContent displayContent = stack.getDisplayContent(); + displayContent.setLayoutNeeded(); + mService.mWindowPlacerLocked.performSurfacePlacement(); + } + } + + // TODO: Replace with moveChildToTop in stack controller? + public void moveToTop(boolean includingParents) { + synchronized(mWindowMap) { + if (mContainer == null) { + Slog.e(TAG_WM, "moveToTop: taskId=" + mTaskId + " not found"); + return; + } + final TaskStack stack = mContainer.mStack; + stack.positionChildAt(POSITION_TOP, mContainer, includingParents); + + if (mService.mAppTransition.isTransitionSet()) { + mContainer.setSendingToBottom(false); + } + stack.getDisplayContent().layoutAndAssignWindowLayersIfNeeded(); + } + } + + // TODO: Replace with moveChildToBottom in stack controller? + public void moveToBottom() { + synchronized(mWindowMap) { + if (mContainer == null) { + Slog.e(TAG_WM, "moveTaskToBottom: taskId=" + mTaskId + " not found"); + return; + } + final TaskStack stack = mContainer.mStack; + stack.positionChildAt(POSITION_BOTTOM, mContainer, false /* includingParents */); + if (mService.mAppTransition.isTransitionSet()) { + mContainer.setSendingToBottom(true); + } + stack.getDisplayContent().layoutAndAssignWindowLayersIfNeeded(); + } + } + + public void getBounds(Rect bounds) { + synchronized (mWindowMap) { + if (mContainer != null) { + mContainer.getBounds(bounds); + return; + } + bounds.setEmpty(); + } + } + + /** + * Puts this task into docked drag resizing mode. See {@link DragResizeMode}. + * + * @param resizing Whether to put the task into drag resize mode. + */ + public void setTaskDockedResizing(boolean resizing) { + synchronized (mWindowMap) { + if (mContainer == null) { + Slog.w(TAG_WM, "setTaskDockedResizing: taskId " + mTaskId + " not found."); + return; + } + mContainer.setDragResizing(resizing, DRAG_RESIZE_MODE_DOCKED_DIVIDER); + } + } + + public void cancelWindowTransition() { + synchronized (mWindowMap) { + if (mContainer == null) { + Slog.w(TAG_WM, "cancelWindowTransition: taskId " + mTaskId + " not found."); + return; + } + mContainer.cancelTaskWindowTransition(); + } + } + + public void cancelThumbnailTransition() { + synchronized (mWindowMap) { + if (mContainer == null) { + Slog.w(TAG_WM, "cancelThumbnailTransition: taskId " + mTaskId + " not found."); + return; + } + mContainer.cancelTaskThumbnailTransition(); + } + } + + @Override + public String toString() { + return "{TaskWindowContainerController taskId=" + mTaskId + "}"; + } +} diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java index 0e6ecde0506a..fd7ea6d6726a 100644 --- a/services/core/java/com/android/server/wm/WindowContainer.java +++ b/services/core/java/com/android/server/wm/WindowContainer.java @@ -235,7 +235,7 @@ class WindowContainer<E extends WindowContainer> implements Comparable<WindowCon @CallSuper void positionChildAt(int position, E child, boolean includingParents) { if ((position < 0 && position != POSITION_BOTTOM) - || (position >= mChildren.size() && position != POSITION_TOP)) { + || (position > mChildren.size() && position != POSITION_TOP)) { throw new IllegalArgumentException("positionAt: invalid position=" + position + ", children number=" + mChildren.size()); } @@ -248,7 +248,7 @@ class WindowContainer<E extends WindowContainer> implements Comparable<WindowCon switch (position) { case POSITION_TOP: - if (mChildren.getLast() != child) { + if (mChildren.peekLast() != child) { mChildren.remove(child); mChildren.addLast(child); } @@ -258,7 +258,7 @@ class WindowContainer<E extends WindowContainer> implements Comparable<WindowCon } break; case POSITION_BOTTOM: - if (mChildren.getFirst() != child) { + if (mChildren.peekFirst() != child) { mChildren.remove(child); mChildren.addFirst(child); } diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index 4e259354ae2a..048affb74728 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -707,8 +707,6 @@ public class WindowManagerService extends IWindowManager.Stub private final BoundsAnimationController mBoundsAnimationController; - SparseArray<Task> mTaskIdToTask = new SparseArray<>(); - /** All of the TaskStacks in the window manager, unordered. For an ordered list call * DisplayContent.getStacks(). */ // TODO: Don't believe this is needed with the WindowContainer model. @@ -912,7 +910,6 @@ public class WindowManagerService extends IWindowManager.Stub } private static WindowManagerService sInstance; - static WindowManagerService getInstance() { return sInstance; } @@ -2441,35 +2438,6 @@ public class WindowManagerService extends IWindowManager.Stub } } - public void addTask(int taskId, int stackId, int userId, Rect bounds, - Configuration overrideConfig, int resizeMode, boolean homeTask, boolean isOnTopLauncher, - boolean toTop, boolean showForAllUsers) { - if (!checkCallingPermission(MANAGE_APP_TOKENS, "addTask()")) { - throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); - } - - synchronized(mWindowMap) { - Task task = mTaskIdToTask.get(taskId); - if (task != null) { - throw new IllegalArgumentException( - "addTask: Attempt to add already existing task=" + task); - } - - if (DEBUG_STACK) Slog.i(TAG_WM, "createTaskLocked: taskId=" + taskId - + " stackId=" + stackId + " bounds=" + bounds); - - final TaskStack stack = mStackIdToStack.get(stackId); - if (stack == null) { - throw new IllegalArgumentException("addTask: invalid stackId=" + stackId); - } - EventLog.writeEvent(WM_TASK_CREATED, taskId, stackId); - task = new Task(taskId, stack, userId, this, bounds, overrideConfig, isOnTopLauncher, - resizeMode, homeTask); - mTaskIdToTask.put(taskId, task); - stack.addTask(task, toTop, showForAllUsers); - } - } - @Override public Configuration updateOrientationFromAppTokens(Configuration currentConfig, IBinder freezeThisOneIfNeeded, int displayId) { @@ -2851,50 +2819,6 @@ public class WindowManagerService extends IWindowManager.Stub } } - public void moveTaskToTop(int taskId) { - final long origId = Binder.clearCallingIdentity(); - try { - synchronized(mWindowMap) { - final Task task = mTaskIdToTask.get(taskId); - if (task == null) { - // Normal behavior, addAppToken will be called next and task will be created. - return; - } - task.mStack.positionChildAt(POSITION_TOP, task, true /* includingParents */); - - if (mAppTransition.isTransitionSet()) { - task.setSendingToBottom(false); - } - final DisplayContent displayContent = task.getDisplayContent(); - displayContent.layoutAndAssignWindowLayersIfNeeded(); - } - } finally { - Binder.restoreCallingIdentity(origId); - } - } - - public void moveTaskToBottom(int taskId) { - final long origId = Binder.clearCallingIdentity(); - try { - synchronized(mWindowMap) { - final Task task = mTaskIdToTask.get(taskId); - if (task == null) { - Slog.e(TAG_WM, "moveTaskToBottom: taskId=" + taskId - + " not found in mTaskIdToTask"); - return; - } - final TaskStack stack = task.mStack; - stack.positionChildAt(POSITION_BOTTOM, task, false /* includingParents */); - if (mAppTransition.isTransitionSet()) { - task.setSendingToBottom(true); - } - stack.getDisplayContent().layoutAndAssignWindowLayersIfNeeded(); - } - } finally { - Binder.restoreCallingIdentity(origId); - } - } - boolean isStackVisibleLocked(int stackId) { final TaskStack stack = mStackIdToStack.get(stackId); return (stack != null && stack.isVisible()); @@ -3064,58 +2988,6 @@ public class WindowManagerService extends IWindowManager.Stub } } - public void removeTask(int taskId) { - synchronized (mWindowMap) { - Task task = mTaskIdToTask.get(taskId); - if (task == null) { - if (DEBUG_STACK) Slog.i(TAG_WM, "removeTask: could not find taskId=" + taskId); - return; - } - task.removeIfPossible(); - } - } - - @Override - public void cancelTaskWindowTransition(int taskId) { - synchronized (mWindowMap) { - Task task = mTaskIdToTask.get(taskId); - if (task != null) { - task.cancelTaskWindowTransition(); - } - } - } - - @Override - public void cancelTaskThumbnailTransition(int taskId) { - synchronized (mWindowMap) { - Task task = mTaskIdToTask.get(taskId); - if (task != null) { - task.cancelTaskThumbnailTransition(); - } - } - } - - public void moveTaskToStack(int taskId, int stackId, boolean toTop) { - synchronized (mWindowMap) { - if (DEBUG_STACK) Slog.i(TAG_WM, "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_WM, "moveTaskToStack: could not find taskId=" + taskId); - return; - } - TaskStack stack = mStackIdToStack.get(stackId); - if (stack == null) { - if (DEBUG_STACK) Slog.i(TAG_WM, "moveTaskToStack: could not find stackId=" + stackId); - return; - } - task.moveTaskToStack(stack, toTop); - final DisplayContent displayContent = stack.getDisplayContent(); - displayContent.setLayoutNeeded(); - mWindowPlacerLocked.performSurfacePlacement(); - } - } - public void getStackDockedModeBounds(int stackId, Rect bounds, boolean ignoreVisibility) { synchronized (mWindowMap) { final TaskStack stack = mStackIdToStack.get(stackId); @@ -3191,69 +3063,6 @@ public class WindowManagerService extends IWindowManager.Stub } } - /** @see com.android.server.am.ActivityManagerService#positionTaskInStack(int, int, int). */ - public void positionTaskInStack(int taskId, int stackId, int position, Rect bounds, - Configuration overrideConfig) { - synchronized (mWindowMap) { - if (DEBUG_STACK) Slog.i(TAG_WM, "positionTaskInStack: positioning taskId=" + taskId - + " in stackId=" + stackId + " at " + position); - Task task = mTaskIdToTask.get(taskId); - if (task == null) { - if (DEBUG_STACK) Slog.i(TAG_WM, - "positionTaskInStack: could not find taskId=" + taskId); - return; - } - TaskStack stack = mStackIdToStack.get(stackId); - if (stack == null) { - if (DEBUG_STACK) Slog.i(TAG_WM, - "positionTaskInStack: could not find stackId=" + stackId); - return; - } - task.positionTaskInStack(stack, position, bounds, overrideConfig); - final DisplayContent displayContent = stack.getDisplayContent(); - displayContent.setLayoutNeeded(); - mWindowPlacerLocked.performSurfacePlacement(); - } - } - - /** - * Re-sizes the specified task and its containing windows. - * Returns a {@link Configuration} object that contains configurations settings - * that should be overridden due to the operation. - */ - public void resizeTask(int taskId, Rect bounds, Configuration overrideConfig, - boolean relayout, boolean forced) { - synchronized (mWindowMap) { - Task task = mTaskIdToTask.get(taskId); - if (task == null) { - throw new IllegalArgumentException("resizeTask: taskId " + taskId - + " not found."); - } - - if (task.resizeLocked(bounds, overrideConfig, forced) && relayout) { - task.getDisplayContent().setLayoutNeeded(); - mWindowPlacerLocked.performSurfacePlacement(); - } - } - } - - /** - * Puts a specific task into docked drag resizing mode. See {@link DragResizeMode}. - * - * @param taskId The id of the task to put into drag resize mode. - * @param resizing Whether to put the task into drag resize mode. - */ - public void setTaskDockedResizing(int taskId, boolean resizing) { - synchronized (mWindowMap) { - Task task = mTaskIdToTask.get(taskId); - if (task == null) { - Slog.w(TAG, "setTaskDockedResizing: taskId " + taskId + " not found."); - return; - } - task.setDragResizing(resizing, DRAG_RESIZE_MODE_DOCKED_DIVIDER); - } - } - /** * Starts deferring layout passes. Useful when doing multiple changes but to optimize * performance, only one layout pass should be done. This can be called multiple times, and @@ -3274,24 +3083,6 @@ public class WindowManagerService extends IWindowManager.Stub } } - public void getTaskBounds(int taskId, Rect bounds) { - synchronized (mWindowMap) { - Task task = mTaskIdToTask.get(taskId); - if (task != null) { - task.getBounds(bounds); - return; - } - bounds.setEmpty(); - } - } - - /** Return true if the input task id represents a valid window manager task. */ - public boolean isValidTaskId(int taskId) { - synchronized (mWindowMap) { - return mTaskIdToTask.get(taskId) != null; - } - } - /** * @return true if the activity contains windows that have * {@link LayoutParams#FLAG_SHOW_WHEN_LOCKED} set @@ -7827,15 +7618,6 @@ public class WindowManagerService extends IWindowManager.Stub } } - public void setTaskResizeable(int taskId, int resizeMode) { - synchronized (mWindowMap) { - final Task task = mTaskIdToTask.get(taskId); - if (task != null) { - task.setResizeable(resizeMode); - } - } - } - public void setForceResizableTasks(boolean forceResizableTasks) { synchronized (mWindowMap) { mForceResizableTasks = forceResizableTasks; diff --git a/services/tests/servicestests/src/com/android/server/wm/AppWindowContainerControllerTests.java b/services/tests/servicestests/src/com/android/server/wm/AppWindowContainerControllerTests.java index 8a962e709a24..7f1c273300da 100644 --- a/services/tests/servicestests/src/com/android/server/wm/AppWindowContainerControllerTests.java +++ b/services/tests/servicestests/src/com/android/server/wm/AppWindowContainerControllerTests.java @@ -18,16 +18,22 @@ package com.android.server.wm; import org.junit.Test; +import android.os.Binder; +import android.os.IBinder; import android.platform.test.annotations.Presubmit; import android.support.test.filters.SmallTest; import android.support.test.runner.AndroidJUnit4; +import android.view.IApplicationToken; +import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE; +import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; +import static android.content.res.Configuration.EMPTY; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; /** - * Test class for {@link WindowContainerController}. + * Test class for {@link AppWindowContainerController}. * * Build/Install/Run: * bit FrameworksServicesTests:com.android.server.wm.AppWindowContainerControllerTests @@ -36,7 +42,70 @@ import static org.junit.Assert.assertTrue; @Presubmit @org.junit.runner.RunWith(AndroidJUnit4.class) public class AppWindowContainerControllerTests extends WindowTestsBase { -// TODO Add tests once TaskWindowContainerController is created. + + @Test + public void testRemoveContainer() throws Exception { + final TestAppWindowContainerController controller = createAppWindowController(); + + // Assert token was added to display. + assertNotNull(sDisplayContent.getWindowToken(controller.mToken.asBinder())); + // Assert that the container was created and linked. + assertNotNull(controller.mContainer); + + controller.removeContainer(sDisplayContent.getDisplayId()); + + // Assert token was remove from display. + assertNull(sDisplayContent.getWindowToken(controller.mToken.asBinder())); + // Assert that the container was removed. + assertNull(controller.mContainer); + } + @Test - public void dummyTest() throws Exception {} + public void testSetOrientation() throws Exception { + final TestAppWindowContainerController controller = createAppWindowController(); + + // Assert orientation is unspecified to start. + assertEquals(SCREEN_ORIENTATION_UNSPECIFIED, controller.getOrientation()); + + controller.setOrientation(SCREEN_ORIENTATION_LANDSCAPE, sDisplayContent.getDisplayId(), + EMPTY /* displayConfig */, false /* freezeScreenIfNeeded */); + assertEquals(SCREEN_ORIENTATION_LANDSCAPE, controller.getOrientation()); + + controller.removeContainer(sDisplayContent.getDisplayId()); + // Assert orientation is unspecified to after container is removed. + assertEquals(SCREEN_ORIENTATION_UNSPECIFIED, controller.getOrientation()); + } + + private TestAppWindowContainerController createAppWindowController() { + final TaskStack stack = createTaskStackOnDisplay(sDisplayContent); + final TestTaskWindowContainerController taskController = + new TestTaskWindowContainerController(stack.mStackId); + final IApplicationToken token = new TestIApplicationToken(); + return new TestAppWindowContainerController(taskController, token); + } + + private class TestAppWindowContainerController extends AppWindowContainerController { + + final IApplicationToken mToken; + + TestAppWindowContainerController(TestTaskWindowContainerController taskController, + IApplicationToken token) { + super(taskController, token, null /* listener */, 0 /* index */, + SCREEN_ORIENTATION_UNSPECIFIED, true /* fullscreen */, + true /* showForAllUsers */, 0 /* configChanges */, false /* voiceInteraction */, + false /* launchTaskBehind */, false /* alwaysFocusable */, + 0 /* targetSdkVersion */, 0 /* rotationAnimationHint */, + 0 /* inputDispatchingTimeoutNanos */, sWm); + mToken = token; + } + } + + private class TestIApplicationToken implements IApplicationToken { + + private final Binder mBinder = new Binder(); + @Override + public IBinder asBinder() { + return mBinder; + } + } } diff --git a/services/tests/servicestests/src/com/android/server/wm/TaskWindowContainerControllerTests.java b/services/tests/servicestests/src/com/android/server/wm/TaskWindowContainerControllerTests.java new file mode 100644 index 000000000000..0dd31c36e207 --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/wm/TaskWindowContainerControllerTests.java @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +package com.android.server.wm; + +import org.junit.Test; + +import android.platform.test.annotations.Presubmit; +import android.support.test.filters.SmallTest; +import android.support.test.runner.AndroidJUnit4; + +/** + * Test class for {@link TaskWindowContainerController}. + * + * Build/Install/Run: + * bit FrameworksServicesTests:com.android.server.wm.TaskWindowContainerControllerTests + */ +@SmallTest +@Presubmit +@org.junit.runner.RunWith(AndroidJUnit4.class) +public class TaskWindowContainerControllerTests extends WindowTestsBase { +// TODO Add tests once StackWindowContainerController is created. + @Test + public void dummyTest() throws Exception {} +} diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowFrameTests.java b/services/tests/servicestests/src/com/android/server/wm/WindowFrameTests.java index ef6ee32c805b..466da942edbc 100644 --- a/services/tests/servicestests/src/com/android/server/wm/WindowFrameTests.java +++ b/services/tests/servicestests/src/com/android/server/wm/WindowFrameTests.java @@ -76,7 +76,7 @@ public class WindowFrameTests { final Rect mInsetBounds = new Rect(); boolean mFullscreenForTest = true; TaskWithBounds(Rect bounds) { - super(0, mStubStack, 0, sWm, null, null, false, 0, false); + super(0, mStubStack, 0, sWm, null, null, false, 0, false, null); mBounds = bounds; } @Override diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java b/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java index fb3beb3c5161..be080f56fb10 100644 --- a/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java +++ b/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java @@ -27,6 +27,7 @@ import android.view.WindowManager; import static android.app.ActivityManager.StackId.FIRST_DYNAMIC_STACK_ID; import static android.app.AppOpsManager.OP_NONE; +import static android.content.pm.ActivityInfo.RESIZE_MODE_UNRESIZEABLE; import static android.content.res.Configuration.EMPTY; import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW; import static android.view.WindowManager.LayoutParams.LAST_APPLICATION_WINDOW; @@ -39,6 +40,7 @@ import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG; import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR; import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR; import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER; +import static com.android.server.wm.WindowContainer.POSITION_TOP; import static org.mockito.Mockito.mock; /** @@ -144,8 +146,8 @@ class WindowTestsBase { /**Creates a {@link Task} and adds it to the specified {@link TaskStack}. */ Task createTaskInStack(TaskStack stack, int userId) { final Task newTask = new Task(sNextTaskId++, stack, userId, sWm, null, EMPTY, false, 0, - false); - stack.addTask(newTask, true); + false, null); + stack.addTask(newTask, POSITION_TOP); return newTask; } @@ -192,4 +194,17 @@ class WindowTestsBase { return mChildren.getLast(); } } + + /** + * Used so we can gain access to some protected members of {@link TaskWindowContainerController} + * class. + */ + class TestTaskWindowContainerController extends TaskWindowContainerController { + + TestTaskWindowContainerController(int stackId) { + super(sNextTaskId++, stackId, 0 /* userId */, null /* bounds */, + EMPTY /* overrideConfig*/, RESIZE_MODE_UNRESIZEABLE, false /* homeTask*/, + false /* isOnTopLauncher */, true /* toTop*/, true /* showForAllUsers */); + } + } } diff --git a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java index 71c1117c036c..5e5ebd7e6488 100644 --- a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java +++ b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java @@ -480,14 +480,6 @@ public class IWindowManagerImpl implements IWindowManager { } @Override - public void cancelTaskWindowTransition(int taskId) { - } - - @Override - public void cancelTaskThumbnailTransition(int taskId) { - } - - @Override public void endProlongedAnimations() { } |