Fix lack of dim layer behind "Power off" window.

This enables dim behind functionality for both tasks and stacks and
groups it inside a controller that manages the dim layers (including
shared dim layers for full screen tasks/stacks).

Bug: 24331704

Change-Id: I0d1ba996d9e00d05e0203166b82268da00fbb35e
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 1f986dd..af33880 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -29,7 +29,6 @@
 import android.util.EventLog;
 import android.util.Slog;
 import android.util.SparseArray;
-import android.util.TypedValue;
 import android.view.DisplayInfo;
 import android.view.Surface;
 
@@ -39,10 +38,6 @@
 import java.util.ArrayList;
 
 class Task implements DimLayer.DimLayerUser {
-    /** Amount of time in milliseconds to animate the dim surface from one value to another,
-     * when no window animation is driving it. */
-    private static final int DEFAULT_DIM_DURATION = 200;
-
     // Return value from {@link setBounds} indicating no change was made to the Task bounds.
     static final int BOUNDS_CHANGE_NONE = 0;
     // Return value from {@link setBounds} indicating the position of the Task bounds changed.
@@ -78,17 +73,6 @@
     // Whether the task is currently being drag-resized
     private boolean mDragResizing;
 
-    // The particular window with FLAG_DIM_BEHIND set. If null, hide mDimLayer.
-    WindowStateAnimator mDimWinAnimator;
-    // Used to support {@link android.view.WindowManager.LayoutParams#FLAG_DIM_BEHIND}
-    private DimLayer mDimLayer;
-    // Set to false at the start of performLayoutAndPlaceSurfaces. If it is still false by the end
-    // then stop any dimming.
-    private boolean mContinueDimming;
-    // Shared dim layer for fullscreen tasks. {@link #mDimLayer} will point to this instead
-    // 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,
             Configuration config) {
         mTaskId = taskId;
@@ -128,6 +112,10 @@
         if (DEBUG_STACK) Slog.i(TAG, "removeTask: removing taskId=" + mTaskId);
         EventLog.writeEvent(EventLogTags.WM_TASK_REMOVED, mTaskId, "removeTask");
         mDeferRemoval = false;
+        DisplayContent content = getDisplayContent();
+        if (content != null) {
+            content.mDimBehindController.removeDimLayerUser(this);
+        }
         mStack.removeTask(this);
         mService.mTaskIdToTask.delete(mTaskId);
     }
@@ -228,7 +216,9 @@
 
         mBounds.set(bounds);
         mRotation = rotation;
-        updateDimLayer();
+        if (displayContent != null) {
+            displayContent.mDimBehindController.updateDimLayer(this);
+        }
         mOverrideConfig = mFullscreen ? Configuration.EMPTY : config;
         return boundsChange;
     }
@@ -261,7 +251,8 @@
     }
 
     /** Bounds of the task with other system factors taken into consideration. */
-    void getBounds(Rect out) {
+    @Override
+    public void getBounds(Rect out) {
         if (useCurrentBounds()) {
             // No need to adjust the output bounds if fullscreen or the docked stack is visible
             // since it is already what we want to represent to the rest of the system.
@@ -309,139 +300,6 @@
         }
     }
 
-    /** Updates the dim layer bounds, recreating it if needed. */
-    private void updateDimLayer() {
-        DimLayer newDimLayer;
-        final boolean previousFullscreen =
-                mDimLayer != null && sSharedFullscreenDimLayers.indexOfValue(mDimLayer) > -1;
-        final int displayId = mStack.getDisplayContent().getDisplayId();
-        if (mFullscreen) {
-            if (previousFullscreen) {
-                // Nothing to do here...
-                return;
-            }
-            // Use shared fullscreen dim layer
-            newDimLayer = sSharedFullscreenDimLayers.get(displayId);
-            if (newDimLayer == null) {
-                if (mDimLayer != null) {
-                    // Re-purpose the previous dim layer.
-                    newDimLayer = mDimLayer;
-                } else {
-                    // Create new full screen dim layer.
-                    newDimLayer = new DimLayer(mService, this, displayId);
-                }
-                newDimLayer.setBounds(mBounds);
-                sSharedFullscreenDimLayers.put(displayId, newDimLayer);
-            } else if (mDimLayer != null) {
-                mDimLayer.destroySurface();
-            }
-        } else {
-            newDimLayer = (mDimLayer == null || previousFullscreen)
-                    ? new DimLayer(mService, this, displayId) : mDimLayer;
-            newDimLayer.setBounds(mBounds);
-        }
-        mDimLayer = newDimLayer;
-    }
-
-    boolean animateDimLayers() {
-        final int dimLayer;
-        final float dimAmount;
-        if (mDimWinAnimator == null) {
-            dimLayer = mDimLayer.getLayer();
-            dimAmount = 0;
-        } else {
-            dimLayer = mDimWinAnimator.mAnimLayer - WindowManagerService.LAYER_OFFSET_DIM;
-            dimAmount = mDimWinAnimator.mWin.mAttrs.dimAmount;
-        }
-        final float targetAlpha = mDimLayer.getTargetAlpha();
-        if (targetAlpha != dimAmount) {
-            if (mDimWinAnimator == null) {
-                mDimLayer.hide(DEFAULT_DIM_DURATION);
-            } else {
-                long duration = (mDimWinAnimator.mAnimating && mDimWinAnimator.mAnimation != null)
-                        ? mDimWinAnimator.mAnimation.computeDurationHint()
-                        : DEFAULT_DIM_DURATION;
-                if (targetAlpha > dimAmount) {
-                    duration = getDimBehindFadeDuration(duration);
-                }
-                mDimLayer.show(dimLayer, dimAmount, duration);
-            }
-        } else if (mDimLayer.getLayer() != dimLayer) {
-            mDimLayer.setLayer(dimLayer);
-        }
-        if (mDimLayer.isAnimating()) {
-            if (!mService.okToDisplay()) {
-                // Jump to the end of the animation.
-                mDimLayer.show();
-            } else {
-                return mDimLayer.stepAnimation();
-            }
-        }
-        return false;
-    }
-
-    private long getDimBehindFadeDuration(long duration) {
-        TypedValue tv = new TypedValue();
-        mService.mContext.getResources().getValue(
-                com.android.internal.R.fraction.config_dimBehindFadeDuration, tv, true);
-        if (tv.type == TypedValue.TYPE_FRACTION) {
-            duration = (long)tv.getFraction(duration, duration);
-        } else if (tv.type >= TypedValue.TYPE_FIRST_INT && tv.type <= TypedValue.TYPE_LAST_INT) {
-            duration = tv.data;
-        }
-        return duration;
-    }
-
-    void clearContinueDimming() {
-        mContinueDimming = false;
-    }
-
-    void setContinueDimming() {
-        mContinueDimming = true;
-    }
-
-    boolean getContinueDimming() {
-        return mContinueDimming;
-    }
-
-    boolean isDimming() {
-        return mDimLayer.isDimming();
-    }
-
-    boolean isDimming(WindowStateAnimator winAnimator) {
-        return mDimWinAnimator == winAnimator && isDimming();
-    }
-
-    void startDimmingIfNeeded(WindowStateAnimator newWinAnimator) {
-        // Only set dim params on the highest dimmed layer.
-        // Don't turn on for an unshown surface, or for any layer but the highest dimmed layer.
-        if (newWinAnimator.mSurfaceShown && (mDimWinAnimator == null
-                || !mDimWinAnimator.mSurfaceShown
-                || mDimWinAnimator.mAnimLayer < newWinAnimator.mAnimLayer)) {
-            mDimWinAnimator = newWinAnimator;
-            if (mDimWinAnimator.mWin.mAppToken == null
-                    && !mFullscreen && mStack.getDisplayContent() != null) {
-                // Dim should cover the entire screen for system windows.
-                mStack.getDisplayContent().getLogicalDisplayRect(mTmpRect);
-                mDimLayer.setBounds(mTmpRect);
-            }
-        }
-    }
-
-    void stopDimmingIfNeeded() {
-        if (!mContinueDimming && isDimming()) {
-            mDimWinAnimator = null;
-            mDimLayer.setBounds(mBounds);
-        }
-    }
-
-    void close() {
-        if (mDimLayer != null) {
-            mDimLayer.destroySurface();
-            mDimLayer = null;
-        }
-    }
-
     void resizeWindows() {
         final ArrayList<WindowState> resizingWindows = mService.mResizingWindows;
         for (int activityNdx = mAppTokens.size() - 1; activityNdx >= 0; --activityNdx) {
@@ -491,16 +349,14 @@
         return "{taskId=" + mTaskId + " appTokens=" + mAppTokens + " mdr=" + mDeferRemoval + "}";
     }
 
+    @Override
+    public String toShortString() {
+        return "Task=" + mTaskId;
+    }
+
     public void printTo(String prefix, PrintWriter pw) {
         pw.print(prefix); pw.print("taskId="); pw.print(mTaskId);
                 pw.print(prefix); pw.print("appTokens="); pw.print(mAppTokens);
                 pw.print(prefix); pw.print("mdr="); pw.println(mDeferRemoval);
-        if (mDimLayer.isDimming()) {
-            pw.print(prefix); pw.println("mDimLayer:");
-            mDimLayer.printTo(prefix + " ", pw);
-            pw.print(prefix); pw.print("mDimWinAnimator="); pw.println(mDimWinAnimator);
-        } else {
-            pw.println();
-        }
     }
 }