diff options
9 files changed, 199 insertions, 200 deletions
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl index f86adfe7dc01..33c51ff367c9 100644 --- a/core/java/android/view/IWindowManager.aidl +++ b/core/java/android/view/IWindowManager.aidl @@ -97,21 +97,21 @@ interface IWindowManager * @param launchTaskBehind True if the token is been launched from behind. * @param taskBounds Bounds to use when creating a new Task with the input task Id if * the task doesn't exist yet. - * @return The configuration of the task if it was newly created. null otherwise. + * @param configuration Configuration that is being used with this task. */ - Configuration addAppToken(int addPos, IApplicationToken token, int taskId, int stackId, + void addAppToken(int addPos, IApplicationToken token, int taskId, int stackId, int requestedOrientation, boolean fullscreen, boolean showWhenLocked, int userId, int configChanges, boolean voiceInteraction, boolean launchTaskBehind, - in Rect taskBounds); + in Rect taskBounds, in Configuration configuration); /** * * @param token The token we are adding to the input task Id. * @param taskId The Id of the task we are adding the token to. * @param taskBounds Bounds to use when creating a new Task with the input task Id if * the task doesn't exist yet. - * @return The configuration of the task if it was newly created. null otherwise. + * @param config Configuration that is being used with this task. */ - Configuration setAppTask(IBinder token, int taskId, in Rect taskBounds); + void setAppTask(IBinder token, int taskId, in Rect taskBounds, in Configuration config); void setAppOrientation(IApplicationToken token, int requestedOrientation); int getAppOrientation(IApplicationToken token); void setFocusedApp(IBinder token, boolean moveFocusNow); diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java index f50df3a1f34f..37ddd4df7ffb 100644 --- a/services/core/java/com/android/server/am/ActivityStack.java +++ b/services/core/java/com/android/server/am/ActivityStack.java @@ -3975,8 +3975,7 @@ final class ActivityStack { * for whatever reason. Ensures the HistoryRecord is updated with the * correct configuration and all other bookkeeping is handled. */ - final boolean ensureActivityConfigurationLocked(ActivityRecord r, - int globalChanges) { + final boolean ensureActivityConfigurationLocked(ActivityRecord r, int globalChanges) { if (mConfigWillChange) { if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION, "Skipping config check (will change): " + r); @@ -4589,25 +4588,19 @@ final class ActivityStack { void addConfigOverride(ActivityRecord r, TaskRecord task) { final Rect bounds = task.getLaunchBounds(); - final Configuration config = - mWindowManager.addAppToken(task.mActivities.indexOf(r), r.appToken, - r.task.taskId, mStackId, r.info.screenOrientation, r.fullscreen, - (r.info.flags & ActivityInfo.FLAG_SHOW_FOR_ALL_USERS) != 0, r.userId, - r.info.configChanges, task.voiceSession != null, r.mLaunchTaskBehind, - bounds); - if (config != null) { - task.updateOverrideConfiguration(config, bounds); - } + final Configuration config = task.updateOverrideConfiguration(mStackId, bounds); + mWindowManager.addAppToken(task.mActivities.indexOf(r), r.appToken, + r.task.taskId, mStackId, r.info.screenOrientation, r.fullscreen, + (r.info.flags & ActivityInfo.FLAG_SHOW_FOR_ALL_USERS) != 0, r.userId, + r.info.configChanges, task.voiceSession != null, r.mLaunchTaskBehind, + bounds, config); r.taskConfigOverride = task.mOverrideConfig; } private void setAppTask(ActivityRecord r, TaskRecord task) { final Rect bounds = task.getLaunchBounds(); - final Configuration config = - mWindowManager.setAppTask(r.appToken, task.taskId, task.getLaunchBounds()); - if (config != null) { - task.updateOverrideConfiguration(config, bounds); - } + final Configuration config = task.updateOverrideConfiguration(mStackId, bounds); + mWindowManager.setAppTask(r.appToken, task.taskId, task.getLaunchBounds(), config); r.taskConfigOverride = task.mOverrideConfig; } diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java index c86056b1a5f0..33e0ef83299c 100644 --- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java +++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java @@ -97,7 +97,6 @@ import android.service.voice.IVoiceInteractionSession; import android.util.ArrayMap; import android.util.ArraySet; import android.util.EventLog; -import android.util.IntArray; import android.util.Slog; import android.util.SparseArray; @@ -334,6 +333,9 @@ public final class ActivityStackSupervisor implements DisplayListener { // temp. rect used during resize calculation so we don't need to create a new object each time. private final Rect tempRect = new Rect(); + private final SparseArray<Configuration> mTmpConfigs = new SparseArray<>(); + private final SparseArray<Rect> mTmpBounds = new SparseArray<>(); + /** * Description of a request to start a new activity, which has been held * due to app switches being disabled. @@ -2917,19 +2919,19 @@ public final class ActivityStackSupervisor implements DisplayListener { ActivityRecord r = stack.topRunningActivityLocked(null); final boolean resizeTasks = r != null && r.task.mResizeable; - final IntArray changedTaskIds = new IntArray(stack.numTasks()); - final List<Configuration> newTaskConfigs = new ArrayList<>(stack.numTasks()); - stack.mFullscreen = mWindowManager.resizeStack( - stackId, bounds, resizeTasks, changedTaskIds, newTaskConfigs); - for (int i = changedTaskIds.size() - 1; i >= 0; i--) { - final TaskRecord task = anyTaskForIdLocked(changedTaskIds.get(i), false); - if (task == null) { - Slog.wtf(TAG, "Task in WindowManager, but not in ActivityManager???"); - continue; + mTmpBounds.clear(); + mTmpConfigs.clear(); + if (resizeTasks) { + ArrayList<TaskRecord> tasks = stack.getAllTasks(); + for (int i = tasks.size() - 1; i >= 0; i--) { + TaskRecord task = tasks.get(i); + task.updateOverrideConfiguration(stackId, bounds); + mTmpConfigs.put(task.taskId, task.mOverrideConfig); + mTmpBounds.put(task.taskId, task.mBounds); } - task.updateOverrideConfiguration(newTaskConfigs.get(i), bounds); } - + stack.mFullscreen = mWindowManager.resizeStack(stackId, bounds, resizeTasks, mTmpConfigs, + mTmpBounds); if (stack.mStackId == DOCKED_STACK_ID) { // Dock stack funness...Yay! if (stack.mFullscreen) { @@ -3024,25 +3026,27 @@ public final class ActivityStackSupervisor implements DisplayListener { stackId = FREEFORM_WORKSPACE_STACK_ID; } if (stackId != task.stack.mStackId) { - final String reason = "resizeTask"; - final ActivityStack stack = - moveTaskToStackUncheckedLocked(task, stackId, ON_TOP, !FORCE_FOCUS, reason); + moveTaskToStackUncheckedLocked(task, stackId, ON_TOP, !FORCE_FOCUS, "resizeTask"); } - final Configuration overrideConfig = mWindowManager.resizeTask(task.taskId, bounds); - if (task.updateOverrideConfiguration(overrideConfig, bounds)) { + final Configuration overrideConfig = task.updateOverrideConfiguration(stackId, bounds); + // This variable holds information whether the configuration didn't change in a signficant + // 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 (overrideConfig != null) { ActivityRecord r = task.topRunningActivityLocked(null); if (r != null) { final ActivityStack stack = task.stack; - final boolean updated = stack.ensureActivityConfigurationLocked(r, 0); - // And we need to make sure at this point that all other activities - // are made visible with the correct configuration. + kept = stack.ensureActivityConfigurationLocked(r, 0); + // All other activities must be made visible with their correct configuration. ensureActivitiesVisibleLocked(r, 0); - if (!updated) { + if (!kept) { resumeTopActivitiesLocked(stack, null, null); } } } + mWindowManager.resizeTask(task.taskId, bounds, task.mOverrideConfig, kept); } ActivityStack createStackOnDisplay(int stackId, int displayId, boolean onTop) { diff --git a/services/core/java/com/android/server/am/LaunchingTaskPositioner.java b/services/core/java/com/android/server/am/LaunchingTaskPositioner.java index 5c4fd138c19c..735c06ffbcf2 100644 --- a/services/core/java/com/android/server/am/LaunchingTaskPositioner.java +++ b/services/core/java/com/android/server/am/LaunchingTaskPositioner.java @@ -16,6 +16,7 @@ package com.android.server.am; +import static android.app.ActivityManager.FREEFORM_WORKSPACE_STACK_ID; import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM; import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME; @@ -234,7 +235,7 @@ class LaunchingTaskPositioner { break; } } - task.setInitialBounds(proposal); + task.updateOverrideConfiguration(FREEFORM_WORKSPACE_STACK_ID, proposal); } private boolean shiftedToFar(Rect start, int shiftPolicy) { diff --git a/services/core/java/com/android/server/am/TaskRecord.java b/services/core/java/com/android/server/am/TaskRecord.java index 9cbaec53ce60..12c7b863e1e3 100644 --- a/services/core/java/com/android/server/am/TaskRecord.java +++ b/services/core/java/com/android/server/am/TaskRecord.java @@ -20,6 +20,7 @@ import static android.app.ActivityManager.DOCKED_STACK_ID; import static android.app.ActivityManager.FREEFORM_WORKSPACE_STACK_ID; import static android.app.ActivityManager.FULLSCREEN_WORKSPACE_STACK_ID; import static android.app.ActivityManager.HOME_STACK_ID; +import static android.app.ActivityManager.INVALID_STACK_ID; import static android.content.Intent.FLAG_ACTIVITY_NEW_DOCUMENT; import static android.content.Intent.FLAG_ACTIVITY_RETAIN_IN_RECENTS; import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_ALWAYS; @@ -52,6 +53,7 @@ import android.os.ParcelFileDescriptor; import android.os.RemoteException; import android.os.UserHandle; import android.service.voice.IVoiceInteractionSession; +import android.util.DisplayMetrics; import android.util.Slog; import com.android.internal.app.IVoiceInteractor; import com.android.internal.util.XmlUtils; @@ -63,6 +65,7 @@ import java.io.File; import java.io.IOException; import java.io.PrintWriter; import java.util.ArrayList; +import java.util.Objects; final class TaskRecord { private static final String TAG = TAG_WITH_CLASS_NAME ? "TaskRecord" : TAG_AM; @@ -106,6 +109,13 @@ final class TaskRecord { static final int INVALID_TASK_ID = -1; + // The height/width divide used when fitting a task within a bounds with method + // {@link #fitWithinBounds}. + // We always want the task to to be visible in the bounds without affecting its size when + // fitting. To make sure this is the case, we don't adjust the task left or top side pass + // the input bounds right or bottom side minus the width or height divided by this value. + private static final int FIT_WITHIN_BOUNDS_DIVIDER = 3; + final int taskId; // Unique identifier for this task. String affinity; // The affinity name for this task, or null; may change identity. String rootAffinity; // Initial base affinity, or null; does not change from initial root. @@ -218,6 +228,8 @@ final class TaskRecord { Configuration mOverrideConfig = Configuration.EMPTY; + private Rect mTmpRect = new Rect(); + TaskRecord(ActivityManagerService service, int _taskId, ActivityInfo info, Intent _intent, IVoiceInteractionSession _voiceSession, IVoiceInteractor _voiceInteractor) { mService = service; @@ -271,8 +283,7 @@ final class TaskRecord { long _firstActiveTime, long _lastActiveTime, long lastTimeMoved, boolean neverRelinquishIdentity, TaskDescription _lastTaskDescription, int taskAffiliation, int prevTaskId, int nextTaskId, int taskAffiliationColor, - int callingUid, String callingPackage, boolean resizeable, boolean privileged, - Rect bounds) { + int callingUid, String callingPackage, boolean resizeable, boolean privileged) { mService = service; mFilename = String.valueOf(_taskId) + TASK_THUMBNAIL_SUFFIX + TaskPersister.IMAGE_EXTENSION; @@ -309,7 +320,6 @@ final class TaskRecord { mCallingPackage = callingPackage; mResizeable = resizeable; mPrivileged = privileged; - mBounds = mLastNonFullscreenBounds = bounds; } void touchActiveTime() { @@ -1163,7 +1173,8 @@ final class TaskRecord { autoRemoveRecents, askedCompatMode, taskType, userId, effectiveUid, lastDescription, activities, firstActiveTime, lastActiveTime, lastTimeOnTop, neverRelinquishIdentity, taskDescription, taskAffiliation, prevTaskId, nextTaskId, taskAffiliationColor, - callingUid, callingPackage, resizeable, privileged, bounds); + callingUid, callingPackage, resizeable, privileged); + task.updateOverrideConfiguration(INVALID_STACK_ID, bounds); for (int activityNdx = activities.size() - 1; activityNdx >=0; --activityNdx) { activities.get(activityNdx).task = task; @@ -1173,25 +1184,51 @@ final class TaskRecord { return task; } - boolean updateOverrideConfiguration(Configuration newConfig, Rect bounds) { + /** + * Update task's override configuration based on the bounds. + * @return Update configuration or null if there is no change. + */ + Configuration updateOverrideConfiguration(int stackId, Rect bounds) { + if (stackId == FREEFORM_WORKSPACE_STACK_ID) { + // For freeform stack we don't adjust the size of the tasks to match that of the + // stack, but we do try to make sure the tasks are still contained with the + // bounds of the stack. + bounds = fitWithinBounds(bounds); + } + if (Objects.equals(mBounds, bounds)) { + return null; + } Configuration oldConfig = mOverrideConfig; - mOverrideConfig = (newConfig == null) ? Configuration.EMPTY : newConfig; - // We override the configuration only when the task's dimensions are different from the - // display. In this manner, we know that if the override configuration is empty, the task - // is necessarily fullscreen. - mFullscreen = Configuration.EMPTY.equals(mOverrideConfig); + + mFullscreen = bounds == null; if (mFullscreen) { if (mBounds != null && stack.mStackId != DOCKED_STACK_ID) { mLastNonFullscreenBounds = mBounds; } mBounds = null; + mOverrideConfig = Configuration.EMPTY; } else { mBounds = new Rect(bounds); if (stack.mStackId != DOCKED_STACK_ID) { mLastNonFullscreenBounds = mBounds; } - } - return !mOverrideConfig.equals(oldConfig); + + final Configuration serviceConfig = mService.mConfiguration; + mOverrideConfig = new Configuration(serviceConfig); + // TODO(multidisplay): Update Dp to that of display stack is on. + final float density = serviceConfig.densityDpi * DisplayMetrics.DENSITY_DEFAULT_SCALE; + mOverrideConfig.screenWidthDp = + Math.min((int)(mBounds.width() / density), serviceConfig.screenWidthDp); + mOverrideConfig.screenHeightDp = + Math.min((int)(mBounds.height() / density), serviceConfig.screenHeightDp); + mOverrideConfig.smallestScreenWidthDp = + Math.min(mOverrideConfig.screenWidthDp, mOverrideConfig.screenHeightDp); + mOverrideConfig.orientation = + (mOverrideConfig.screenWidthDp <= mOverrideConfig.screenHeightDp) + ? Configuration.ORIENTATION_PORTRAIT + : Configuration.ORIENTATION_LANDSCAPE; + } + return !mOverrideConfig.equals(oldConfig) ? mOverrideConfig : null; } /** Returns the stack that should be used to launch this task. */ @@ -1225,12 +1262,39 @@ final class TaskRecord { return mLastNonFullscreenBounds; } - void setInitialBounds(Rect rect) { - if (mBounds == null) { - mBounds = new Rect(); + /** Fits the tasks within the input bounds adjusting the task bounds as needed. + * @param bounds Bounds to fit the task within. Nothing is done if null. + * @return Returns final configuration after updating with the adjusted bounds. + * */ + Rect fitWithinBounds(Rect bounds) { + if (bounds == null || mBounds == null || bounds.contains(mBounds)) { + return bounds; + } + mTmpRect.set(mBounds); + + if (mBounds.left < bounds.left || mBounds.right > bounds.right) { + final int maxRight = bounds.right - (bounds.width() / FIT_WITHIN_BOUNDS_DIVIDER); + int horizontalDiff = bounds.left - mBounds.left; + if ((horizontalDiff < 0 && mBounds.left >= maxRight) + || (mBounds.left + horizontalDiff >= maxRight)) { + horizontalDiff = maxRight - mBounds.left; + } + mTmpRect.left += horizontalDiff; + mTmpRect.right += horizontalDiff; } - mBounds.set(rect); - mLastNonFullscreenBounds = mBounds; + + if (mBounds.top < bounds.top || mBounds.bottom > bounds.bottom) { + final int maxBottom = bounds.bottom - (bounds.height() / FIT_WITHIN_BOUNDS_DIVIDER); + int verticalDiff = bounds.top - mBounds.top; + if ((verticalDiff < 0 && mBounds.top >= maxBottom) + || (mBounds.top + verticalDiff >= maxBottom)) { + verticalDiff = maxBottom - mBounds.top; + } + mTmpRect.top += verticalDiff; + mTmpRect.bottom += verticalDiff; + } + + return mTmpRect; } void dump(PrintWriter pw, String prefix) { diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java index 554af2849919..666d902682a7 100644 --- a/services/core/java/com/android/server/wm/Task.java +++ b/services/core/java/com/android/server/wm/Task.java @@ -23,7 +23,6 @@ import static android.app.ActivityManager.FREEFORM_WORKSPACE_STACK_ID; import android.content.res.Configuration; import android.graphics.Rect; -import android.util.DisplayMetrics; import android.util.EventLog; import android.util.Slog; import android.util.SparseArray; @@ -41,13 +40,6 @@ class Task implements DimLayer.DimLayerUser { * when no window animation is driving it. */ private static final int DEFAULT_DIM_DURATION = 200; - // The amount we divide the height/width of the bounds we are trying to fit the task within - // when using the method {@link #fitWithinBounds}. - // We always want the task to to be visible in the bounds without affecting its size when - // fitting. To make sure this is the case, we don't adjust the task left or top side pass - // the input bounds right or bottom side minus the width or height divided by this value. - private static final int FIT_WITHIN_BOUNDS_DIVIDER = 3; - TaskStack mStack; final AppTokenList mAppTokens = new AppTokenList(); final int mTaskId; @@ -84,13 +76,13 @@ class Task implements DimLayer.DimLayerUser { // of creating a new object per fullscreen task on a display. private static final SparseArray<DimLayer> sSharedFullscreenDimLayers = new SparseArray<>(); - Task(int taskId, TaskStack stack, int userId, WindowManagerService service, Rect bounds) { + Task(int taskId, TaskStack stack, int userId, WindowManagerService service, Rect bounds, + Configuration config) { mTaskId = taskId; mStack = stack; mUserId = userId; mService = service; - mOverrideConfig = Configuration.EMPTY; - setBounds(bounds); + setBounds(bounds, config); } DisplayContent getDisplayContent() { @@ -172,43 +164,18 @@ class Task implements DimLayer.DimLayerUser { } } - /** Fits the tasks within the input bounds adjusting the task bounds as needed. - * @param bounds Bounds to fit the task within. Nothing is done if null. - * @return Returns true if the task bounds was adjusted in any way. - * */ - boolean fitWithinBounds(Rect bounds) { - if (bounds == null || bounds.contains(mBounds)) { - return false; + /** Set the task bounds. Passing in null sets the bounds to fullscreen. */ + boolean setBounds(Rect bounds, Configuration config) { + if (config == null) { + config = Configuration.EMPTY; } - mTmpRect2.set(mBounds); - - if (mBounds.left < bounds.left || mBounds.right > bounds.right) { - final int maxRight = bounds.right - (bounds.width() / FIT_WITHIN_BOUNDS_DIVIDER); - int horizontalDiff = bounds.left - mBounds.left; - if ((horizontalDiff < 0 && mBounds.left >= maxRight) - || (mBounds.left + horizontalDiff >= maxRight)) { - horizontalDiff = maxRight - mBounds.left; - } - mTmpRect2.left += horizontalDiff; - mTmpRect2.right += horizontalDiff; + if (bounds == null && !Configuration.EMPTY.equals(config)) { + throw new IllegalArgumentException("null bounds but non empty configuration: " + + config); } - - if (mBounds.top < bounds.top || mBounds.bottom > bounds.bottom) { - final int maxBottom = bounds.bottom - (bounds.height() / FIT_WITHIN_BOUNDS_DIVIDER); - int verticalDiff = bounds.top - mBounds.top; - if ((verticalDiff < 0 && mBounds.top >= maxBottom) - || (mBounds.top + verticalDiff >= maxBottom)) { - verticalDiff = maxBottom - mBounds.top; - } - mTmpRect2.top += verticalDiff; - mTmpRect2.bottom += verticalDiff; + if (bounds != null && Configuration.EMPTY.equals(config)) { + throw new IllegalArgumentException("non null bounds, but empty configuration"); } - - return setBounds(mTmpRect2); - } - - /** Set the task bounds. Passing in null sets the bounds to fullscreen. */ - boolean setBounds(Rect bounds) { boolean oldFullscreen = mFullscreen; int rotation = Surface.ROTATION_0; final DisplayContent displayContent = mStack.getDisplayContent(); @@ -241,7 +208,7 @@ class Task implements DimLayer.DimLayerUser { mBounds.set(bounds); mRotation = rotation; updateDimLayer(); - updateOverrideConfiguration(); + mOverrideConfig = mFullscreen ? Configuration.EMPTY : config; return true; } @@ -249,36 +216,12 @@ class Task implements DimLayer.DimLayerUser { out.set(mBounds); } - private void updateOverrideConfiguration() { - final Configuration serviceConfig = mService.mCurConfiguration; - if (mFullscreen) { - mOverrideConfig = Configuration.EMPTY; - return; - } - - if (mOverrideConfig == Configuration.EMPTY) { - mOverrideConfig = new Configuration(); - } - - // TODO(multidisplay): Update Dp to that of display stack is on. - final float density = serviceConfig.densityDpi * DisplayMetrics.DENSITY_DEFAULT_SCALE; - mOverrideConfig.screenWidthDp = - Math.min((int)(mBounds.width() / density), serviceConfig.screenWidthDp); - mOverrideConfig.screenHeightDp = - Math.min((int)(mBounds.height() / density), serviceConfig.screenHeightDp); - mOverrideConfig.smallestScreenWidthDp = - Math.min(mOverrideConfig.screenWidthDp, mOverrideConfig.screenHeightDp); - mOverrideConfig.orientation = - (mOverrideConfig.screenWidthDp <= mOverrideConfig.screenHeightDp) - ? Configuration.ORIENTATION_PORTRAIT : Configuration.ORIENTATION_LANDSCAPE; - } - void updateDisplayInfo(final DisplayContent displayContent) { if (displayContent == null) { return; } if (mFullscreen) { - setBounds(null); + setBounds(null, Configuration.EMPTY); return; } final int newRotation = displayContent.getDisplayInfo().rotation; @@ -313,7 +256,7 @@ class Task implements DimLayer.DimLayerUser { mTmpRect2.bottom = mTmpRect2.top + mBounds.width(); break; } - setBounds(mTmpRect2); + setBounds(mTmpRect2, mOverrideConfig); } /** Updates the dim layer bounds, recreating it if needed. */ diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java index 25a71d9fc7f1..a7ef2f8ae165 100644 --- a/services/core/java/com/android/server/wm/TaskStack.java +++ b/services/core/java/com/android/server/wm/TaskStack.java @@ -27,6 +27,7 @@ import android.os.RemoteException; import android.util.EventLog; import android.util.IntArray; import android.util.Slog; +import android.util.SparseArray; import android.view.DisplayInfo; import com.android.server.EventLogTags; @@ -96,15 +97,15 @@ public class TaskStack implements DimLayer.DimLayerUser { /** * Set the bounds of the stack and its containing tasks. - * @param bounds New stack bounds. Passing in null sets the bounds to fullscreen. + * @param stackBounds New stack bounds. Passing in null sets the bounds to fullscreen. * @param resizeTasks If true, the tasks within the stack will also be resized. - * @param changedTaskIds Output list of Ids of tasks that changed in bounds. - * @param newTaskConfigs Output list of new Configuation of the tasks that changed. + * @param configs Configuration for individual tasks, keyed by task id. + * @param taskBounds Bounds for individual tasks, keyed by task id. * @return True if the stack bounds was changed. * */ - boolean setBounds(Rect bounds, boolean resizeTasks, IntArray changedTaskIds, - List<Configuration> newTaskConfigs) { - if (!setBounds(bounds)) { + boolean setBounds(Rect stackBounds, boolean resizeTasks, SparseArray<Configuration> configs, + SparseArray<Rect> taskBounds) { + if (!setBounds(stackBounds)) { return false; } @@ -113,20 +114,17 @@ public class TaskStack implements DimLayer.DimLayerUser { } // Update bounds of containing tasks. - final Rect newBounds = mFullscreen ? null : mBounds; for (int taskNdx = mTasks.size() - 1; taskNdx >= 0; --taskNdx) { final Task task = mTasks.get(taskNdx); - if (mStackId == FREEFORM_WORKSPACE_STACK_ID) { - // For freeform stack we don't adjust the size of the tasks to match that of the - // stack, but we do try to make sure the tasks are still contained with the - // bounds of the stack. - if (task.fitWithinBounds(newBounds)) { - changedTaskIds.add(task.mTaskId); - newTaskConfigs.add(task.mOverrideConfig); + Configuration config = configs.get(task.mTaskId); + if (config != null) { + Rect bounds = taskBounds.get(task.mTaskId); + if (bounds == null) { + bounds = stackBounds; } - } else if (task.setBounds(newBounds)) { - changedTaskIds.add(task.mTaskId); - newTaskConfigs.add(task.mOverrideConfig); + task.setBounds(bounds, config); + } else { + Slog.wtf(TAG, "No config for task: " + task + ", is there a mismatch with AM?"); } } return true; diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index cf690a56c2d1..bf7d1e7f27ee 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -3041,8 +3041,8 @@ public class WindowManagerService extends IWindowManager.Stub Binder.restoreCallingIdentity(origId); } - private Task createTaskLocked( - int taskId, int stackId, int userId, AppWindowToken atoken, Rect bounds) { + private Task createTaskLocked(int taskId, int stackId, int userId, AppWindowToken atoken, + Rect bounds, Configuration config) { if (DEBUG_STACK) Slog.i(TAG, "createTaskLocked: taskId=" + taskId + " stackId=" + stackId + " atoken=" + atoken + " bounds=" + bounds); final TaskStack stack = mStackIdToStack.get(stackId); @@ -3050,17 +3050,17 @@ public class WindowManagerService extends IWindowManager.Stub throw new IllegalArgumentException("addAppToken: invalid stackId=" + stackId); } EventLog.writeEvent(EventLogTags.WM_TASK_CREATED, taskId, stackId); - Task task = new Task(taskId, stack, userId, this, bounds); + Task task = new Task(taskId, stack, userId, this, bounds, config); mTaskIdToTask.put(taskId, task); stack.addTask(task, !atoken.mLaunchTaskBehind /* toTop */, atoken.showForAllUsers); return task; } @Override - public Configuration addAppToken(int addPos, IApplicationToken token, int taskId, int stackId, + public void addAppToken(int addPos, IApplicationToken token, int taskId, int stackId, int requestedOrientation, boolean fullscreen, boolean showForAllUsers, int userId, int configChanges, boolean voiceInteraction, boolean launchTaskBehind, - Rect taskBounds) { + Rect taskBounds, Configuration config) { if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, "addAppToken()")) { throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); @@ -3084,7 +3084,7 @@ public class WindowManagerService extends IWindowManager.Stub AppWindowToken atoken = findAppWindowToken(token.asBinder()); if (atoken != null) { Slog.w(TAG, "Attempted to add existing app token: " + token); - return null; + return; } atoken = new AppWindowToken(this, token, voiceInteraction); atoken.inputDispatchingTimeoutNanos = inputDispatchingTimeoutNanos; @@ -3098,10 +3098,8 @@ public class WindowManagerService extends IWindowManager.Stub + " to stack=" + stackId + " task=" + taskId + " at " + addPos); Task task = mTaskIdToTask.get(taskId); - Configuration outConfig = null; if (task == null) { - task = createTaskLocked(taskId, stackId, userId, atoken, taskBounds); - outConfig = task.mOverrideConfig; + task = createTaskLocked(taskId, stackId, userId, atoken, taskBounds, config); } task.addAppToken(addPos, atoken); @@ -3110,13 +3108,11 @@ public class WindowManagerService extends IWindowManager.Stub // Application tokens start out hidden. atoken.hidden = true; atoken.hiddenRequested = true; - - return outConfig; } } @Override - public Configuration setAppTask(IBinder token, int taskId, Rect taskBounds) { + public void setAppTask(IBinder token, int taskId, Rect taskBounds, Configuration config) { if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, "setAppTask()")) { throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); @@ -3126,20 +3122,18 @@ public class WindowManagerService extends IWindowManager.Stub final AppWindowToken atoken = findAppWindowToken(token); if (atoken == null) { Slog.w(TAG, "Attempted to set task id of non-existing app token: " + token); - return null; + return; } final Task oldTask = atoken.mTask; oldTask.removeAppToken(atoken); Task newTask = mTaskIdToTask.get(taskId); - Configuration outConfig = null; if (newTask == null) { newTask = createTaskLocked( - taskId, oldTask.mStack.mStackId, oldTask.mUserId, atoken, taskBounds); - outConfig = newTask.mOverrideConfig; + taskId, oldTask.mStack.mStackId, oldTask.mUserId, atoken, taskBounds, + config); } newTask.addAppToken(Integer.MAX_VALUE /* at top */, atoken); - return outConfig; } } @@ -4599,19 +4593,19 @@ public class WindowManagerService extends IWindowManager.Stub * @param stackId Id of stack to resize. * @param bounds New stack bounds. Passing in null sets the bounds to fullscreen. * @param resizeTasks If true, the tasks within the stack will also be resized. - * @param changedTaskIds Output list of Ids of tasks that changed in bounds due to resize. - * @param newTaskConfigs Output list of new Configuation of the tasks that changed. + * @param configs Configurations for tasks in the resized stack, keyed by task id. + * @param taskBounds Bounds for tasks in the resized stack, keyed by task id. * @return True if the stack is now fullscreen. * */ public boolean resizeStack(int stackId, Rect bounds, boolean resizeTasks, - IntArray changedTaskIds, List<Configuration> newTaskConfigs) { + SparseArray<Configuration> configs, SparseArray<Rect> taskBounds) { synchronized (mWindowMap) { final TaskStack stack = mStackIdToStack.get(stackId); if (stack == null) { throw new IllegalArgumentException("resizeStack: stackId " + stackId + " not found."); } - if (stack.setBounds(bounds, resizeTasks, changedTaskIds, newTaskConfigs)) { + if (stack.setBounds(bounds, resizeTasks, configs, taskBounds)) { stack.resizeWindows(); stack.getDisplayContent().layoutNeeded = true; performLayoutAndPlaceSurfacesLocked(); @@ -4648,19 +4642,20 @@ public class WindowManagerService extends IWindowManager.Stub * Returns a {@link Configuration} object that contains configurations settings * that should be overridden due to the operation. */ - public Configuration resizeTask(int taskId, Rect bounds) { + public void resizeTask(int taskId, Rect bounds, Configuration configuration, boolean relayout) { synchronized (mWindowMap) { Task task = mTaskIdToTask.get(taskId); if (task == null) { throw new IllegalArgumentException("resizeTask: taskId " + taskId + " not found."); } - if (task.setBounds(bounds)) { + if (task.setBounds(bounds, configuration)) { task.resizeWindows(); - task.getDisplayContent().layoutNeeded = true; - performLayoutAndPlaceSurfacesLocked(); + if (relayout) { + task.getDisplayContent().layoutNeeded = true; + performLayoutAndPlaceSurfacesLocked(); + } } - return new Configuration(task.mOverrideConfig); } } diff --git a/tests/permission/src/com/android/framework/permission/tests/WindowManagerPermissionTests.java b/tests/permission/src/com/android/framework/permission/tests/WindowManagerPermissionTests.java index 6177784a17c5..95f676e08895 100644 --- a/tests/permission/src/com/android/framework/permission/tests/WindowManagerPermissionTests.java +++ b/tests/permission/src/com/android/framework/permission/tests/WindowManagerPermissionTests.java @@ -32,7 +32,7 @@ import junit.framework.TestCase; */ public class WindowManagerPermissionTests extends TestCase { IWindowManager mWm; - + @Override protected void setUp() throws Exception { super.setUp(); @@ -51,7 +51,7 @@ public class WindowManagerPermissionTests extends TestCase { } catch (RemoteException e) { fail("Unexpected remote exception"); } - + try { mWm.resumeKeyDispatching(null); fail("IWindowManager.resumeKeyDispatching did not throw SecurityException as" @@ -61,7 +61,7 @@ public class WindowManagerPermissionTests extends TestCase { } catch (RemoteException e) { fail("Unexpected remote exception"); } - + try { mWm.setEventDispatching(true); fail("IWindowManager.setEventDispatching did not throw SecurityException as" @@ -71,7 +71,7 @@ public class WindowManagerPermissionTests extends TestCase { } catch (RemoteException e) { fail("Unexpected remote exception"); } - + try { mWm.addWindowToken(null, 0); fail("IWindowManager.addWindowToken did not throw SecurityException as" @@ -81,7 +81,7 @@ public class WindowManagerPermissionTests extends TestCase { } catch (RemoteException e) { fail("Unexpected remote exception"); } - + try { mWm.removeWindowToken(null); fail("IWindowManager.removeWindowToken did not throw SecurityException as" @@ -91,9 +91,10 @@ public class WindowManagerPermissionTests extends TestCase { } catch (RemoteException e) { fail("Unexpected remote exception"); } - + try { - mWm.addAppToken(0, null, 0, 0, 0, false, false, 0, 0, false, false, null); + mWm.addAppToken(0, null, 0, 0, 0, false, false, 0, 0, false, false, null, + Configuration.EMPTY); fail("IWindowManager.addAppToken did not throw SecurityException as" + " expected"); } catch (SecurityException e) { @@ -101,9 +102,9 @@ public class WindowManagerPermissionTests extends TestCase { } catch (RemoteException e) { fail("Unexpected remote exception"); } - + try { - mWm.setAppTask(null, 0, null); + mWm.setAppTask(null, 0, null, null); fail("IWindowManager.setAppGroupId did not throw SecurityException as" + " expected"); } catch (SecurityException e) { @@ -111,7 +112,7 @@ public class WindowManagerPermissionTests extends TestCase { } catch (RemoteException e) { fail("Unexpected remote exception"); } - + try { mWm.updateOrientationFromAppTokens(new Configuration(), null); fail("IWindowManager.updateOrientationFromAppTokens did not throw SecurityException as" @@ -121,7 +122,7 @@ public class WindowManagerPermissionTests extends TestCase { } catch (RemoteException e) { fail("Unexpected remote exception"); } - + try { mWm.setAppOrientation(null, 0); mWm.addWindowToken(null, 0); @@ -132,7 +133,7 @@ public class WindowManagerPermissionTests extends TestCase { } catch (RemoteException e) { fail("Unexpected remote exception"); } - + try { mWm.setFocusedApp(null, false); fail("IWindowManager.setFocusedApp did not throw SecurityException as" @@ -142,7 +143,7 @@ public class WindowManagerPermissionTests extends TestCase { } catch (RemoteException e) { fail("Unexpected remote exception"); } - + try { mWm.prepareAppTransition(0, false); fail("IWindowManager.prepareAppTransition did not throw SecurityException as" @@ -152,7 +153,7 @@ public class WindowManagerPermissionTests extends TestCase { } catch (RemoteException e) { fail("Unexpected remote exception"); } - + try { mWm.executeAppTransition(); fail("IWindowManager.executeAppTransition did not throw SecurityException as" @@ -162,7 +163,7 @@ public class WindowManagerPermissionTests extends TestCase { } catch (RemoteException e) { fail("Unexpected remote exception"); } - + try { mWm.setAppStartingWindow(null, "foo", 0, null, null, 0, 0, 0, 0, null, false); fail("IWindowManager.setAppStartingWindow did not throw SecurityException as" @@ -172,7 +173,7 @@ public class WindowManagerPermissionTests extends TestCase { } catch (RemoteException e) { fail("Unexpected remote exception"); } - + try { mWm.setAppWillBeHidden(null); fail("IWindowManager.setAppWillBeHidden did not throw SecurityException as" @@ -182,7 +183,7 @@ public class WindowManagerPermissionTests extends TestCase { } catch (RemoteException e) { fail("Unexpected remote exception"); } - + try { mWm.setAppVisibility(null, false); fail("IWindowManager.setAppVisibility did not throw SecurityException as" @@ -192,7 +193,7 @@ public class WindowManagerPermissionTests extends TestCase { } catch (RemoteException e) { fail("Unexpected remote exception"); } - + try { mWm.startAppFreezingScreen(null, 0); fail("IWindowManager.startAppFreezingScreen did not throw SecurityException as" @@ -202,7 +203,7 @@ public class WindowManagerPermissionTests extends TestCase { } catch (RemoteException e) { fail("Unexpected remote exception"); } - + try { mWm.stopAppFreezingScreen(null, false); fail("IWindowManager.stopAppFreezingScreen did not throw SecurityException as" @@ -212,7 +213,7 @@ public class WindowManagerPermissionTests extends TestCase { } catch (RemoteException e) { fail("Unexpected remote exception"); } - + try { mWm.removeAppToken(null); fail("IWindowManager.removeAppToken did not throw SecurityException as" @@ -236,7 +237,7 @@ public class WindowManagerPermissionTests extends TestCase { } catch (RemoteException e) { fail("Unexpected remote exception"); } - + try { mWm.reenableKeyguard(token); fail("IWindowManager.reenableKeyguard did not throw SecurityException as" @@ -246,7 +247,7 @@ public class WindowManagerPermissionTests extends TestCase { } catch (RemoteException e) { fail("Unexpected remote exception"); } - + try { mWm.exitKeyguardSecurely(null); fail("IWindowManager.exitKeyguardSecurely did not throw SecurityException as" @@ -257,7 +258,7 @@ public class WindowManagerPermissionTests extends TestCase { fail("Unexpected remote exception"); } } - + @SmallTest public void testSET_ANIMATION_SCALE() { try { @@ -269,7 +270,7 @@ public class WindowManagerPermissionTests extends TestCase { } catch (RemoteException e) { fail("Unexpected remote exception"); } - + try { mWm.setAnimationScales(new float[1]); fail("IWindowManager.setAnimationScales did not throw SecurityException as" @@ -280,7 +281,7 @@ public class WindowManagerPermissionTests extends TestCase { fail("Unexpected remote exception"); } } - + @SmallTest public void testSET_ORIENTATION() { try { |