diff options
author | Filip Gruszczynski <gruszczy@google.com> | 2015-08-25 16:51:05 -0700 |
---|---|---|
committer | Filip Gruszczynski <gruszczy@google.com> | 2015-09-01 08:14:51 -0700 |
commit | ebcc875f10f05db7365cd8afbf4e9425221ab14d (patch) | |
tree | 0c733889ff0f4be8ed914dffdfcdf2db9d14398c | |
parent | e9acfd59b818a138f189336181ff721aceadbfb1 (diff) |
Move Configuration creation from Window Manager to Activity Manager.
Currently the construction of configuration is split between thease
two entities. This poses two problems: it's harder to follow the
construction logic and more importantly we can't determine if
configuration changes significantly before delegating work to the
Window Manager. This CL moves the configuration override logic to
the Activity Manager, since it both detects configuration changes and
informs clients about them. Window Manager becomes purely a recipient
of the information.
Change-Id: I075570ee055cce9c5665772fa8d4fe8ccb5c6313
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 { |