Move updating stack override config to ActivityStack

Also added some multi-display TODOs.

Change-Id: Iada3f84c4f57c9623fc7f116819d4e0267ebc32a
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 8782820..51eef89 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -1715,6 +1715,7 @@
                     }
                     if (ar != null && mCompatModePackages.getPackageNotifyUnsupportedZoomLocked(
                             ar.packageName)) {
+                        // TODO(multi-display): Show dialog on appropriate display.
                         mUnsupportedDisplaySizeDialog = new UnsupportedDisplaySizeDialog(
                                 ActivityManagerService.this, mContext, ar.info.applicationInfo);
                         mUnsupportedDisplaySizeDialog.show();
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index 806416d..b82e28d 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -118,6 +118,7 @@
 import android.util.EventLog;
 import android.util.Log;
 import android.util.Slog;
+import android.util.SparseArray;
 import android.view.Display;
 
 import com.android.internal.app.IVoiceInteractor;
@@ -228,6 +229,13 @@
     // stack and the new stack will be on top of all stacks.
     static final int REMOVE_TASK_MODE_MOVING_TO_TOP = 2;
 
+    // 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 ActivityManagerService mService;
     final WindowManagerService mWindowManager;
     private final RecentTasks mRecentTasks;
@@ -321,6 +329,12 @@
     /** The attached Display's unique identifier, or -1 if detached */
     int mDisplayId;
 
+    /** Temp variables used during override configuration update. */
+    private final SparseArray<Configuration> mTmpConfigs = new SparseArray<>();
+    private final SparseArray<Rect> mTmpBounds = new SparseArray<>();
+    private final SparseArray<Rect> mTmpInsetBounds = new SparseArray<>();
+    private final Rect tempRect2 = new Rect();
+
     /** Run all ActivityStacks through this */
     final ActivityStackSupervisor mStackSupervisor;
 
@@ -4524,6 +4538,86 @@
         }
     }
 
+    /** Update override configurations of all tasks in the stack. */
+    void updateOverrideConfiguration(Rect stackBounds, Rect tempTaskBounds,
+            Rect tempTaskInsetBounds) {
+
+        final Rect taskBounds = tempTaskBounds != null ? tempTaskBounds : stackBounds;
+        final Rect insetBounds = tempTaskInsetBounds != null ? tempTaskInsetBounds : taskBounds;
+
+        mTmpBounds.clear();
+        mTmpConfigs.clear();
+        mTmpInsetBounds.clear();
+
+        for (int i = mTaskHistory.size() - 1; i >= 0; i--) {
+            final TaskRecord task = mTaskHistory.get(i);
+            if (task.isResizeable()) {
+                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.
+                    tempRect2.set(task.mBounds);
+                    fitWithinBounds(tempRect2, stackBounds);
+                    task.updateOverrideConfiguration(tempRect2);
+                } else {
+                    task.updateOverrideConfiguration(taskBounds, insetBounds);
+                }
+            }
+
+            mTmpConfigs.put(task.taskId, task.mOverrideConfig);
+            mTmpBounds.put(task.taskId, task.mBounds);
+            if (tempTaskInsetBounds != null) {
+                mTmpInsetBounds.put(task.taskId, tempTaskInsetBounds);
+            }
+        }
+
+        // We might trigger a configuration change. Save the current task bounds for freezing.
+        mWindowManager.prepareFreezingTaskBounds(mStackId);
+        mFullscreen = mWindowManager.resizeStack(mStackId, stackBounds, mTmpConfigs, mTmpBounds,
+                mTmpInsetBounds);
+        setBounds(stackBounds);
+    }
+
+
+    /**
+     * Adjust bounds to stay within stack bounds.
+     *
+     * Since bounds might be outside of stack bounds, this method tries to move the bounds in a way
+     * that keep them unchanged, but be contained within the stack bounds.
+     *
+     * @param bounds Bounds to be adjusted.
+     * @param stackBounds Bounds within which the other bounds should remain.
+     */
+    private static void fitWithinBounds(Rect bounds, Rect stackBounds) {
+        if (stackBounds == null || stackBounds.contains(bounds)) {
+            return;
+        }
+
+        if (bounds.left < stackBounds.left || bounds.right > stackBounds.right) {
+            final int maxRight = stackBounds.right
+                    - (stackBounds.width() / FIT_WITHIN_BOUNDS_DIVIDER);
+            int horizontalDiff = stackBounds.left - bounds.left;
+            if ((horizontalDiff < 0 && bounds.left >= maxRight)
+                    || (bounds.left + horizontalDiff >= maxRight)) {
+                horizontalDiff = maxRight - bounds.left;
+            }
+            bounds.left += horizontalDiff;
+            bounds.right += horizontalDiff;
+        }
+
+        if (bounds.top < stackBounds.top || bounds.bottom > stackBounds.bottom) {
+            final int maxBottom = stackBounds.bottom
+                    - (stackBounds.height() / FIT_WITHIN_BOUNDS_DIVIDER);
+            int verticalDiff = stackBounds.top - bounds.top;
+            if ((verticalDiff < 0 && bounds.top >= maxBottom)
+                    || (bounds.top + verticalDiff >= maxBottom)) {
+                verticalDiff = maxBottom - bounds.top;
+            }
+            bounds.top += verticalDiff;
+            bounds.bottom += verticalDiff;
+        }
+    }
+
     /**
      * Make sure the given activity matches the current configuration. Returns false if the activity
      * had to be destroyed.  Returns true if the configuration is the same, or the activity will
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 80d51e5..8602bb6 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -267,13 +267,6 @@
     /** Action restriction: launching the activity is restricted by an app op. */
     private static final int ACTIVITY_RESTRICTION_APPOP = 2;
 
-    // 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;
-
     /** Status Bar Service **/
     private IBinder mToken = new Binder();
     private IStatusBarService mStatusBarService;
@@ -402,13 +395,11 @@
     /** Used to keep resumeTopActivityUncheckedLocked() from being entered recursively */
     boolean inResumeTopActivity;
 
-    // temp. rects used during resize calculation so we don't need to create a new object each time.
+    /**
+     * Temporary rect used during docked stack resize calculation so we don't need to create a new
+     * object each time.
+     */
     private final Rect tempRect = new Rect();
-    private final Rect tempRect2 = new Rect();
-
-    private final SparseArray<Configuration> mTmpConfigs = new SparseArray<>();
-    private final SparseArray<Rect> mTmpBounds = new SparseArray<>();
-    private final SparseArray<Rect> mTmpInsetBounds = new SparseArray<>();
 
     // The default minimal size that will be used if the activity doesn't specify its minimal size.
     // It will be calculated when the default display gets added.
@@ -1912,6 +1903,7 @@
         if (!createStaticStackIfNeeded || !StackId.isStaticStack(stackId)) {
             return null;
         }
+        // TODO(multi-display): Allow creating stacks on secondary displays.
         return createStackOnDisplay(stackId, Display.DEFAULT_DISPLAY, createOnTop);
     }
 
@@ -1923,14 +1915,6 @@
         return allStacks;
     }
 
-    IBinder getHomeActivityToken() {
-        ActivityRecord homeActivity = getHomeActivity();
-        if (homeActivity != null) {
-            return homeActivity.appToken;
-        }
-        return null;
-    }
-
     ActivityRecord getHomeActivity() {
         return getHomeActivityForUser(mCurrentUser);
     }
@@ -2060,39 +2044,7 @@
             return;
         }
 
-        mTmpBounds.clear();
-        mTmpConfigs.clear();
-        mTmpInsetBounds.clear();
-        final ArrayList<TaskRecord> tasks = stack.getAllTasks();
-        final Rect taskBounds = tempTaskBounds != null ? tempTaskBounds : bounds;
-        final Rect insetBounds = tempTaskInsetBounds != null ? tempTaskInsetBounds : taskBounds;
-        for (int i = tasks.size() - 1; i >= 0; i--) {
-            final TaskRecord task = tasks.get(i);
-            if (task.isResizeable()) {
-                if (stack.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.
-                    tempRect2.set(task.mBounds);
-                    fitWithinBounds(tempRect2, bounds);
-                    task.updateOverrideConfiguration(tempRect2);
-                } else {
-                    task.updateOverrideConfiguration(taskBounds, insetBounds);
-                }
-            }
-
-            mTmpConfigs.put(task.taskId, task.mOverrideConfig);
-            mTmpBounds.put(task.taskId, task.mBounds);
-            if (tempTaskInsetBounds != null) {
-                mTmpInsetBounds.put(task.taskId, tempTaskInsetBounds);
-            }
-        }
-
-        // We might trigger a configuration change. Save the current task bounds for freezing.
-        mWindowManager.prepareFreezingTaskBounds(stack.mStackId);
-        stack.mFullscreen = mWindowManager.resizeStack(stack.mStackId, bounds, mTmpConfigs,
-                mTmpBounds, mTmpInsetBounds);
-        stack.setBounds(bounds);
+        stack.updateOverrideConfiguration(bounds, tempTaskBounds, tempTaskInsetBounds);
     }
 
     void moveTasksToFullscreenStackLocked(int fromStackId, boolean onTop) {
@@ -4371,45 +4323,6 @@
         }
     }
 
-    /**
-     * Adjust bounds to stay within stack bounds.
-     *
-     * Since bounds might be outside of stack bounds, this method tries to move the bounds in a way
-     * that keep them unchanged, but be contained within the stack bounds.
-     *
-     * @param bounds Bounds to be adjusted.
-     * @param stackBounds Bounds within which the other bounds should remain.
-     */
-    private static void fitWithinBounds(Rect bounds, Rect stackBounds) {
-        if (stackBounds == null || stackBounds.contains(bounds)) {
-            return;
-        }
-
-        if (bounds.left < stackBounds.left || bounds.right > stackBounds.right) {
-            final int maxRight = stackBounds.right
-                    - (stackBounds.width() / FIT_WITHIN_BOUNDS_DIVIDER);
-            int horizontalDiff = stackBounds.left - bounds.left;
-            if ((horizontalDiff < 0 && bounds.left >= maxRight)
-                    || (bounds.left + horizontalDiff >= maxRight)) {
-                horizontalDiff = maxRight - bounds.left;
-            }
-            bounds.left += horizontalDiff;
-            bounds.right += horizontalDiff;
-        }
-
-        if (bounds.top < stackBounds.top || bounds.bottom > stackBounds.bottom) {
-            final int maxBottom = stackBounds.bottom
-                    - (stackBounds.height() / FIT_WITHIN_BOUNDS_DIVIDER);
-            int verticalDiff = stackBounds.top - bounds.top;
-            if ((verticalDiff < 0 && bounds.top >= maxBottom)
-                    || (bounds.top + verticalDiff >= maxBottom)) {
-                verticalDiff = maxBottom - bounds.top;
-            }
-            bounds.top += verticalDiff;
-            bounds.bottom += verticalDiff;
-        }
-    }
-
     ActivityStack findStackBehind(ActivityStack stack) {
         // TODO(multi-display): We are only looking for stacks on the default display.
         final ActivityDisplay display = mActivityDisplays.get(Display.DEFAULT_DISPLAY);
@@ -4525,6 +4438,8 @@
      * entry will be the focused activity.
      */
     public List<IBinder> getTopVisibleActivities() {
+        // TODO(multi-display): Get rid of DEFAULT_DISPLAY here. Used in
+        // VoiceInteractionManagerServiceImpl#showSessionLocked.
         final ActivityDisplay display = mActivityDisplays.get(Display.DEFAULT_DISPLAY);
         if (display == null) {
             return Collections.EMPTY_LIST;
diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java
index 475b155..2b00f86 100644
--- a/services/core/java/com/android/server/am/ProcessList.java
+++ b/services/core/java/com/android/server/am/ProcessList.java
@@ -220,6 +220,7 @@
     void applyDisplaySize(WindowManagerService wm) {
         if (!mHaveDisplaySize) {
             Point p = new Point();
+            // TODO(multi-display): Compute based on sum of all connected displays' resolutions.
             wm.getBaseDisplaySize(Display.DEFAULT_DISPLAY, p);
             if (p.x != 0 && p.y != 0) {
                 updateOomLevels(p.x, p.y, true);
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index 2828b96..f9aa66b 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -325,6 +325,8 @@
                 // The token is not closing nor opening, so even if there is an animation set, that
                 // doesn't mean that it goes through the normal app transition cycle so we have
                 // to inform the docked controller about visibility change.
+                // TODO(multi-display): notify docked divider on all displays where visibility was
+                // affected.
                 mService.getDefaultDisplayContentLocked().getDockedDividerController()
                         .notifyAppVisibilityChanged();
             }
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 0501fdc..7a32845 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -8804,6 +8804,7 @@
             if (line != null) {
                 String[] toks = line.split("%");
                 if (toks != null && toks.length > 0) {
+                    // TODO(multi-display): Show watermarks on secondary displays.
                     mWatermark = new Watermark(getDefaultDisplayContentLocked().getDisplay(),
                             mRealDisplayMetrics, mFxSession, toks);
                 }
diff --git a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
index 5025df6..8f2723c 100644
--- a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
+++ b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
@@ -303,6 +303,7 @@
         mSustainedPerformanceModeCurrent = false;
         mService.mTransactionSequence++;
 
+        // TODO(multi-display): Perform same actions on all displays.
         final DisplayContent defaultDisplay = mService.getDefaultDisplayContentLocked();
         final DisplayInfo defaultInfo = defaultDisplay.getDisplayInfo();
         final int defaultDw = defaultInfo.logicalWidth;