OSDN Git Service

Reimplement DimLayer's using hierarchy.
authorRobert Carr <racarr@google.com>
Tue, 3 Oct 2017 01:58:36 +0000 (18:58 -0700)
committerRobert Carr <racarr@google.com>
Mon, 20 Nov 2017 17:14:12 +0000 (09:14 -0800)
Still missing the fade in/out animation. See Dimmer.java for details.

Bug: 64815723
Bug: 64816140
Test: DimmerTests.java. Existing tests pass. go/wm-smoke. Docked resizing Dim layer works, various dialog dim layers work.
Change-Id: I19a03f1b6b602475410fcfb2c9728aae1d0bed85

16 files changed:
services/core/java/com/android/server/wm/DimLayer.java [deleted file]
services/core/java/com/android/server/wm/DimLayerController.java [deleted file]
services/core/java/com/android/server/wm/Dimmer.java [new file with mode: 0644]
services/core/java/com/android/server/wm/DisplayContent.java
services/core/java/com/android/server/wm/DockedStackDividerController.java
services/core/java/com/android/server/wm/Task.java
services/core/java/com/android/server/wm/TaskPositioner.java
services/core/java/com/android/server/wm/TaskStack.java
services/core/java/com/android/server/wm/WindowAnimator.java
services/core/java/com/android/server/wm/WindowContainer.java
services/core/java/com/android/server/wm/WindowManagerService.java
services/core/java/com/android/server/wm/WindowState.java
services/core/java/com/android/server/wm/WindowStateAnimator.java
services/tests/servicestests/src/com/android/server/wm/DimLayerControllerTests.java [deleted file]
services/tests/servicestests/src/com/android/server/wm/DimmerTests.java [new file with mode: 0644]
services/tests/servicestests/src/com/android/server/wm/TaskStackTests.java

diff --git a/services/core/java/com/android/server/wm/DimLayer.java b/services/core/java/com/android/server/wm/DimLayer.java
deleted file mode 100644 (file)
index 3f360e2..0000000
+++ /dev/null
@@ -1,378 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.wm;
-
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_DIM_LAYER;
-import static com.android.server.wm.WindowManagerDebugConfig.SHOW_SURFACE_ALLOC;
-import static com.android.server.wm.WindowManagerDebugConfig.SHOW_TRANSACTIONS;
-import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
-import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
-
-import android.graphics.PixelFormat;
-import android.graphics.Rect;
-import android.os.SystemClock;
-import android.util.Slog;
-import android.view.DisplayInfo;
-import android.view.SurfaceControl;
-
-import java.io.PrintWriter;
-
-public class DimLayer {
-    private static final String TAG = TAG_WITH_CLASS_NAME ? "DimLayer" : TAG_WM;
-    private final WindowManagerService mService;
-
-    /** Actual surface that dims */
-    private SurfaceControl mDimSurface;
-
-    /** Last value passed to mDimSurface.setAlpha() */
-    private float mAlpha = 0;
-
-    /** Last value passed to mDimSurface.setLayer() */
-    private int mLayer = -1;
-
-    /** Next values to pass to mDimSurface.setPosition() and mDimSurface.setSize() */
-    private final Rect mBounds = new Rect();
-
-    /** Last values passed to mDimSurface.setPosition() and mDimSurface.setSize() */
-    private final Rect mLastBounds = new Rect();
-
-    /** True after mDimSurface.show() has been called, false after mDimSurface.hide(). */
-    private boolean mShowing = false;
-
-    /** Value of mAlpha when beginning transition to mTargetAlpha */
-    private float mStartAlpha = 0;
-
-    /** Final value of mAlpha following transition */
-    private float mTargetAlpha = 0;
-
-    /** Time in units of SystemClock.uptimeMillis() at which the current transition started */
-    private long mStartTime;
-
-    /** Time in milliseconds to take to transition from mStartAlpha to mTargetAlpha */
-    private long mDuration;
-
-    private boolean mDestroyed = false;
-
-    private final DisplayContent mDisplayContent;
-
-    /** Interface implemented by users of the dim layer */
-    interface DimLayerUser {
-        /** Returns true if the  dim should be fullscreen. */
-        boolean dimFullscreen();
-        /** Returns the display info. of the dim layer user. */
-        DisplayInfo getDisplayInfo();
-        /** Returns true if the dim layer user is currently attached to a display */
-        boolean isAttachedToDisplay();
-        /** Gets the bounds of the dim layer user. */
-        void getDimBounds(Rect outBounds);
-        /** Returns the layer to place a dim layer. */
-        default int getLayerForDim(WindowStateAnimator animator, int layerOffset,
-                int defaultLayer) {
-            return defaultLayer;
-        }
-
-        String toShortString();
-    }
-    /** The user of this dim layer. */
-    private final DimLayerUser mUser;
-
-    private final String mName;
-
-    DimLayer(WindowManagerService service, DimLayerUser user, DisplayContent dc, String name) {
-        mUser = user;
-        mDisplayContent = dc;
-        mService = service;
-        mName = name;
-        if (DEBUG_DIM_LAYER) Slog.v(TAG, "Ctor: dc=" + dc);
-    }
-
-    private void constructSurface(WindowManagerService service) {
-        service.openSurfaceTransaction();
-        try {
-            mDimSurface = mDisplayContent.makeSurface()
-                    .setName(mName)
-                    .setSize(16, 16)
-                    .setColorLayer(true)
-                    .build();
-
-            if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) Slog.i(TAG,
-                    "  DIM " + mDimSurface + ": CREATE");
-            adjustBounds();
-            adjustAlpha(mAlpha);
-            adjustLayer(mLayer);
-        } catch (Exception e) {
-            Slog.e(TAG_WM, "Exception creating Dim surface", e);
-        } finally {
-            service.closeSurfaceTransaction("DimLayer.constructSurface");
-        }
-    }
-
-    /** Return true if dim layer is showing */
-    boolean isDimming() {
-        return mTargetAlpha != 0;
-    }
-
-    /** Return true if in a transition period */
-    boolean isAnimating() {
-        return mTargetAlpha != mAlpha;
-    }
-
-    float getTargetAlpha() {
-        return mTargetAlpha;
-    }
-
-    void setLayer(int layer) {
-        if (mLayer == layer) {
-            return;
-        }
-        mLayer = layer;
-        adjustLayer(layer);
-    }
-
-    private void adjustLayer(int layer) {
-        if (mDimSurface != null) {
-            mDimSurface.setLayer(layer);
-        }
-    }
-
-    int getLayer() {
-        return mLayer;
-    }
-
-    private void setAlpha(float alpha) {
-        if (mAlpha == alpha) {
-            return;
-        }
-        mAlpha = alpha;
-        adjustAlpha(alpha);
-    }
-
-    private void adjustAlpha(float alpha) {
-        if (DEBUG_DIM_LAYER) Slog.v(TAG, "setAlpha alpha=" + alpha);
-        try {
-            if (mDimSurface != null) {
-                mDimSurface.setAlpha(alpha);
-            }
-            if (alpha == 0 && mShowing) {
-                if (DEBUG_DIM_LAYER) Slog.v(TAG, "setAlpha hiding");
-                if (mDimSurface != null) {
-                    mDimSurface.hide();
-                    mShowing = false;
-                }
-            } else if (alpha > 0 && !mShowing) {
-                if (DEBUG_DIM_LAYER) Slog.v(TAG, "setAlpha showing");
-                if (mDimSurface != null) {
-                    mDimSurface.show();
-                    mShowing = true;
-                }
-            }
-        } catch (RuntimeException e) {
-            Slog.w(TAG, "Failure setting alpha immediately", e);
-        }
-    }
-
-    /**
-     * NOTE: Must be called with Surface transaction open.
-     */
-    private void adjustBounds() {
-        if (mUser.dimFullscreen()) {
-            getBoundsForFullscreen(mBounds);
-        }
-
-        if (mDimSurface != null) {
-            mDimSurface.setPosition(mBounds.left, mBounds.top);
-            mDimSurface.setSize(mBounds.width(), mBounds.height());
-            if (DEBUG_DIM_LAYER) Slog.v(TAG,
-                    "adjustBounds user=" + mUser.toShortString() + " mBounds=" + mBounds);
-        }
-
-        mLastBounds.set(mBounds);
-    }
-
-    private void getBoundsForFullscreen(Rect outBounds) {
-        final int dw, dh;
-        final float xPos, yPos;
-        // Set surface size to screen size.
-        final DisplayInfo info = mUser.getDisplayInfo();
-        // Multiply by 1.5 so that rotating a frozen surface that includes this does not expose
-        // a corner.
-        dw = (int) (info.logicalWidth * 1.5);
-        dh = (int) (info.logicalHeight * 1.5);
-        // back off position so 1/4 of Surface is before and 1/4 is after.
-        xPos = -1 * dw / 6;
-        yPos = -1 * dh / 6;
-        outBounds.set((int) xPos, (int) yPos, (int) xPos + dw, (int) yPos + dh);
-    }
-
-    void setBoundsForFullscreen() {
-        getBoundsForFullscreen(mBounds);
-        setBounds(mBounds);
-    }
-
-    /** @param bounds The new bounds to set */
-    void setBounds(Rect bounds) {
-        mBounds.set(bounds);
-        if (isDimming() && !mLastBounds.equals(bounds)) {
-            try {
-                mService.openSurfaceTransaction();
-                adjustBounds();
-            } catch (RuntimeException e) {
-                Slog.w(TAG, "Failure setting size", e);
-            } finally {
-                mService.closeSurfaceTransaction("DimLayer.setBounds");
-            }
-        }
-    }
-
-    /**
-     * @param duration The time to test.
-     * @return True if the duration would lead to an earlier end to the current animation.
-     */
-    private boolean durationEndsEarlier(long duration) {
-        return SystemClock.uptimeMillis() + duration < mStartTime + mDuration;
-    }
-
-    /** Jump to the end of the animation.
-     * NOTE: Must be called with Surface transaction open. */
-    void show() {
-        if (isAnimating()) {
-            if (DEBUG_DIM_LAYER) Slog.v(TAG, "show: immediate");
-            show(mLayer, mTargetAlpha, 0);
-        }
-    }
-
-    /**
-     * Begin an animation to a new dim value.
-     * NOTE: Must be called with Surface transaction open.
-     *
-     * @param layer The layer to set the surface to.
-     * @param alpha The dim value to end at.
-     * @param duration How long to take to get there in milliseconds.
-     */
-    void show(int layer, float alpha, long duration) {
-        if (DEBUG_DIM_LAYER) Slog.v(TAG, "show: layer=" + layer + " alpha=" + alpha
-                + " duration=" + duration + ", mDestroyed=" + mDestroyed);
-        if (mDestroyed) {
-            Slog.e(TAG, "show: no Surface");
-            // Make sure isAnimating() returns false.
-            mTargetAlpha = mAlpha = 0;
-            return;
-        }
-
-        if (mDimSurface == null) {
-            constructSurface(mService);
-        }
-
-        if (!mLastBounds.equals(mBounds)) {
-            adjustBounds();
-        }
-        setLayer(layer);
-
-        long curTime = SystemClock.uptimeMillis();
-        final boolean animating = isAnimating();
-        if ((animating && (mTargetAlpha != alpha || durationEndsEarlier(duration)))
-                || (!animating && mAlpha != alpha)) {
-            if (duration <= 0) {
-                // No animation required, just set values.
-                setAlpha(alpha);
-            } else {
-                // Start or continue animation with new parameters.
-                mStartAlpha = mAlpha;
-                mStartTime = curTime;
-                mDuration = duration;
-            }
-        }
-        mTargetAlpha = alpha;
-        if (DEBUG_DIM_LAYER) Slog.v(TAG, "show: mStartAlpha=" + mStartAlpha + " mStartTime="
-                + mStartTime + " mTargetAlpha=" + mTargetAlpha);
-    }
-
-    /** Immediate hide.
-     * NOTE: Must be called with Surface transaction open. */
-    void hide() {
-        if (mShowing) {
-            if (DEBUG_DIM_LAYER) Slog.v(TAG, "hide: immediate");
-            hide(0);
-        }
-    }
-
-    /**
-     * Gradually fade to transparent.
-     * NOTE: Must be called with Surface transaction open.
-     *
-     * @param duration Time to fade in milliseconds.
-     */
-    void hide(long duration) {
-        if (mShowing && (mTargetAlpha != 0 || durationEndsEarlier(duration))) {
-            if (DEBUG_DIM_LAYER) Slog.v(TAG, "hide: duration=" + duration);
-            show(mLayer, 0, duration);
-        }
-    }
-
-    /**
-     * Advance the dimming per the last #show(int, float, long) call.
-     * NOTE: Must be called with Surface transaction open.
-     *
-     * @return True if animation is still required after this step.
-     */
-    boolean stepAnimation() {
-        if (mDestroyed) {
-            Slog.e(TAG, "stepAnimation: surface destroyed");
-            // Ensure that isAnimating() returns false;
-            mTargetAlpha = mAlpha = 0;
-            return false;
-        }
-        if (isAnimating()) {
-            final long curTime = SystemClock.uptimeMillis();
-            final float alphaDelta = mTargetAlpha - mStartAlpha;
-            float alpha = mStartAlpha + alphaDelta * (curTime - mStartTime) / mDuration;
-            if (alphaDelta > 0 && alpha > mTargetAlpha ||
-                    alphaDelta < 0 && alpha < mTargetAlpha) {
-                // Don't exceed limits.
-                alpha = mTargetAlpha;
-            }
-            if (DEBUG_DIM_LAYER) Slog.v(TAG, "stepAnimation: curTime=" + curTime + " alpha=" + alpha);
-            setAlpha(alpha);
-        }
-
-        return isAnimating();
-    }
-
-    /** Cleanup */
-    void destroySurface() {
-        if (DEBUG_DIM_LAYER) Slog.v(TAG, "destroySurface.");
-        if (mDimSurface != null) {
-            mDimSurface.destroy();
-            mDimSurface = null;
-        }
-        mDestroyed = true;
-    }
-
-    public void printTo(String prefix, PrintWriter pw) {
-        pw.print(prefix); pw.print("mDimSurface="); pw.print(mDimSurface);
-                pw.print(" mLayer="); pw.print(mLayer);
-                pw.print(" mAlpha="); pw.println(mAlpha);
-        pw.print(prefix); pw.print("mLastBounds="); pw.print(mLastBounds.toShortString());
-                pw.print(" mBounds="); pw.println(mBounds.toShortString());
-        pw.print(prefix); pw.print("Last animation: ");
-                pw.print(" mDuration="); pw.print(mDuration);
-                pw.print(" mStartTime="); pw.print(mStartTime);
-                pw.print(" curTime="); pw.println(SystemClock.uptimeMillis());
-        pw.print(prefix); pw.print(" mStartAlpha="); pw.print(mStartAlpha);
-                pw.print(" mTargetAlpha="); pw.println(mTargetAlpha);
-    }
-}
diff --git a/services/core/java/com/android/server/wm/DimLayerController.java b/services/core/java/com/android/server/wm/DimLayerController.java
deleted file mode 100644 (file)
index a1a10d8..0000000
+++ /dev/null
@@ -1,402 +0,0 @@
-package com.android.server.wm;
-
-import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_DIM_LAYER;
-import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
-import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
-import static com.android.server.wm.WindowManagerService.LAYER_OFFSET_DIM;
-
-import android.graphics.Rect;
-import android.util.ArrayMap;
-import android.util.Slog;
-import android.util.TypedValue;
-
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.server.wm.DimLayer.DimLayerUser;
-
-import java.io.PrintWriter;
-
-/**
- * Centralizes the control of dim layers used for
- * {@link android.view.WindowManager.LayoutParams#FLAG_DIM_BEHIND}
- * as well as other use cases (such as dimming above a dead window).
- */
-class DimLayerController {
-    private static final String TAG_LOCAL = "DimLayerController";
-    private static final String TAG = TAG_WITH_CLASS_NAME ? TAG_LOCAL : TAG_WM;
-
-    /** 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;
-
-    /**
-     * The default amount of dim applied over a dead window
-     */
-    private static final float DEFAULT_DIM_AMOUNT_DEAD_WINDOW = 0.5f;
-
-    // Shared dim layer for fullscreen users. {@link DimLayerState#dimLayer} will point to this
-    // instead of creating a new object per fullscreen task on a display.
-    private DimLayer mSharedFullScreenDimLayer;
-
-    private ArrayMap<DimLayer.DimLayerUser, DimLayerState> mState = new ArrayMap<>();
-
-    private DisplayContent mDisplayContent;
-
-    private Rect mTmpBounds = new Rect();
-
-    DimLayerController(DisplayContent displayContent) {
-        mDisplayContent = displayContent;
-    }
-
-    /** Updates the dim layer bounds, recreating it if needed. */
-    void updateDimLayer(DimLayer.DimLayerUser dimLayerUser) {
-        final DimLayerState state = getOrCreateDimLayerState(dimLayerUser);
-        final boolean previousFullscreen = state.dimLayer != null
-                && state.dimLayer == mSharedFullScreenDimLayer;
-        DimLayer newDimLayer;
-        if (dimLayerUser.dimFullscreen()) {
-            if (previousFullscreen && mSharedFullScreenDimLayer != null) {
-                // Update the bounds for fullscreen in case of rotation.
-                mSharedFullScreenDimLayer.setBoundsForFullscreen();
-                return;
-            }
-            // Use shared fullscreen dim layer
-            newDimLayer = mSharedFullScreenDimLayer;
-            if (newDimLayer == null) {
-                if (state.dimLayer != null) {
-                    // Re-purpose the previous dim layer.
-                    newDimLayer = state.dimLayer;
-                } else {
-                    // Create new full screen dim layer.
-                    newDimLayer = new DimLayer(mDisplayContent.mService, dimLayerUser,
-                            mDisplayContent, getDimLayerTag(dimLayerUser));
-                }
-                dimLayerUser.getDimBounds(mTmpBounds);
-                newDimLayer.setBounds(mTmpBounds);
-                mSharedFullScreenDimLayer = newDimLayer;
-            } else if (state.dimLayer != null) {
-                state.dimLayer.destroySurface();
-            }
-        } else {
-            newDimLayer = (state.dimLayer == null || previousFullscreen)
-                    ? new DimLayer(mDisplayContent.mService, dimLayerUser, mDisplayContent,
-                            getDimLayerTag(dimLayerUser))
-                    : state.dimLayer;
-            dimLayerUser.getDimBounds(mTmpBounds);
-            newDimLayer.setBounds(mTmpBounds);
-        }
-        state.dimLayer = newDimLayer;
-    }
-
-    private static String getDimLayerTag(DimLayerUser dimLayerUser) {
-        return TAG_LOCAL + "/" + dimLayerUser.toShortString();
-    }
-
-    private DimLayerState getOrCreateDimLayerState(DimLayer.DimLayerUser dimLayerUser) {
-        if (DEBUG_DIM_LAYER) Slog.v(TAG, "getOrCreateDimLayerState, dimLayerUser="
-                + dimLayerUser.toShortString());
-        DimLayerState state = mState.get(dimLayerUser);
-        if (state == null) {
-            state = new DimLayerState();
-            mState.put(dimLayerUser, state);
-        }
-        return state;
-    }
-
-    private void setContinueDimming(DimLayer.DimLayerUser dimLayerUser) {
-        DimLayerState state = mState.get(dimLayerUser);
-        if (state == null) {
-            if (DEBUG_DIM_LAYER) Slog.w(TAG, "setContinueDimming, no state for: "
-                    + dimLayerUser.toShortString());
-            return;
-        }
-        state.continueDimming = true;
-    }
-
-    boolean isDimming() {
-        for (int i = mState.size() - 1; i >= 0; i--) {
-            DimLayerState state = mState.valueAt(i);
-            if (state.dimLayer != null && state.dimLayer.isDimming()) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    void resetDimming() {
-        for (int i = mState.size() - 1; i >= 0; i--) {
-            mState.valueAt(i).continueDimming = false;
-        }
-    }
-
-    private boolean getContinueDimming(DimLayer.DimLayerUser dimLayerUser) {
-        DimLayerState state = mState.get(dimLayerUser);
-        return state != null && state.continueDimming;
-    }
-
-    void startDimmingIfNeeded(DimLayer.DimLayerUser dimLayerUser,
-            WindowStateAnimator newWinAnimator, boolean aboveApp) {
-        // 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.
-        DimLayerState state = getOrCreateDimLayerState(dimLayerUser);
-        state.dimAbove = aboveApp;
-        if (DEBUG_DIM_LAYER) Slog.v(TAG, "startDimmingIfNeeded,"
-                + " dimLayerUser=" + dimLayerUser.toShortString()
-                + " newWinAnimator=" + newWinAnimator
-                + " state.animator=" + state.animator);
-        if (newWinAnimator.getShown() && (state.animator == null
-                || !state.animator.getShown()
-                || state.animator.mAnimLayer <= newWinAnimator.mAnimLayer)) {
-            state.animator = newWinAnimator;
-            if (state.animator.mWin.mAppToken == null && !dimLayerUser.dimFullscreen()) {
-                // Dim should cover the entire screen for system windows.
-                mDisplayContent.getLogicalDisplayRect(mTmpBounds);
-            } else {
-                dimLayerUser.getDimBounds(mTmpBounds);
-            }
-            state.dimLayer.setBounds(mTmpBounds);
-        }
-    }
-
-    void stopDimmingIfNeeded() {
-        if (DEBUG_DIM_LAYER) Slog.v(TAG, "stopDimmingIfNeeded, mState.size()=" + mState.size());
-        for (int i = mState.size() - 1; i >= 0; i--) {
-            DimLayer.DimLayerUser dimLayerUser = mState.keyAt(i);
-            stopDimmingIfNeeded(dimLayerUser);
-        }
-    }
-
-    private void stopDimmingIfNeeded(DimLayer.DimLayerUser dimLayerUser) {
-        // No need to check if state is null, we know the key has a value.
-        DimLayerState state = mState.get(dimLayerUser);
-        if (DEBUG_DIM_LAYER) Slog.v(TAG, "stopDimmingIfNeeded,"
-                + " dimLayerUser=" + dimLayerUser.toShortString()
-                + " state.continueDimming=" + state.continueDimming
-                + " state.dimLayer.isDimming=" + state.dimLayer.isDimming());
-        if (state.animator != null && state.animator.mWin.mWillReplaceWindow) {
-            return;
-        }
-
-        if (!state.continueDimming && state.dimLayer.isDimming()) {
-            state.animator = null;
-            dimLayerUser.getDimBounds(mTmpBounds);
-            state.dimLayer.setBounds(mTmpBounds);
-        }
-    }
-
-    boolean animateDimLayers() {
-        int fullScreen = -1;
-        int fullScreenAndDimming = -1;
-        int topFullScreenUserLayer = 0;
-        boolean result = false;
-
-        for (int i = mState.size() - 1; i >= 0; i--) {
-            final DimLayer.DimLayerUser user = mState.keyAt(i);
-            final DimLayerState state = mState.valueAt(i);
-
-            if (!user.isAttachedToDisplay()) {
-                // Leaked dim user that is no longer attached to the display. Go ahead and clean it
-                // clean-up and log what happened.
-                // TODO: This is a work around for b/34395537 as the dim user should have cleaned-up
-                // it self when it was detached from the display. Need to investigate how the dim
-                // user is leaking...
-                //Slog.wtfStack(TAG_WM, "Leaked dim user=" + user.toShortString()
-                //        + " state=" + state);
-                Slog.w(TAG_WM, "Leaked dim user=" + user.toShortString() + " state=" + state);
-                removeDimLayerUser(user);
-                continue;
-            }
-
-            // We have to check that we are actually the shared fullscreen layer
-            // for this path. If we began as non fullscreen and became fullscreen
-            // (e.g. Docked stack closing), then we may not be the shared layer
-            // and we have to make sure we always animate the layer.
-            if (user.dimFullscreen() && state.dimLayer == mSharedFullScreenDimLayer) {
-                fullScreen = i;
-                if (!state.continueDimming) {
-                    continue;
-                }
-
-                // When choosing which user to assign the shared fullscreen layer to
-                // we need to look at Z-order.
-                if (topFullScreenUserLayer == 0 ||
-                        (state.animator != null && state.animator.mAnimLayer > topFullScreenUserLayer)) {
-                    fullScreenAndDimming = i;
-                    if (state.animator != null) {
-                        topFullScreenUserLayer = state.animator.mAnimLayer;
-                    }
-                }
-            } else {
-                // We always want to animate the non fullscreen windows, they don't share their
-                // dim layers.
-                result |= animateDimLayers(user);
-            }
-        }
-        // For the shared, full screen dim layer, we prefer the animation that is causing it to
-        // appear.
-        if (fullScreenAndDimming != -1) {
-            result |= animateDimLayers(mState.keyAt(fullScreenAndDimming));
-        } else if (fullScreen != -1) {
-            // If there is no animation for the full screen dim layer to appear, we can use any of
-            // the animators that will cause it to disappear.
-            result |= animateDimLayers(mState.keyAt(fullScreen));
-        }
-        return result;
-    }
-
-    private boolean animateDimLayers(DimLayer.DimLayerUser dimLayerUser) {
-        DimLayerState state = mState.get(dimLayerUser);
-        if (DEBUG_DIM_LAYER) Slog.v(TAG, "animateDimLayers,"
-                + " dimLayerUser=" + dimLayerUser.toShortString()
-                + " state.animator=" + state.animator
-                + " state.continueDimming=" + state.continueDimming);
-        final int dimLayer;
-        final float dimAmount;
-        if (state.animator == null) {
-            dimLayer = state.dimLayer.getLayer();
-            dimAmount = 0;
-        } else {
-            if (state.dimAbove) {
-                dimLayer = state.animator.mAnimLayer + LAYER_OFFSET_DIM;
-                dimAmount = DEFAULT_DIM_AMOUNT_DEAD_WINDOW;
-            } else {
-                dimLayer = dimLayerUser.getLayerForDim(state.animator, LAYER_OFFSET_DIM,
-                        state.animator.mAnimLayer - LAYER_OFFSET_DIM);
-                dimAmount = state.animator.mWin.mAttrs.dimAmount;
-            }
-        }
-        final float targetAlpha = state.dimLayer.getTargetAlpha();
-        if (targetAlpha != dimAmount) {
-            if (state.animator == null) {
-                state.dimLayer.hide(DEFAULT_DIM_DURATION);
-            } else {
-                long duration = (state.animator.mAnimating && state.animator.mAnimation != null)
-                        ? state.animator.mAnimation.computeDurationHint()
-                        : DEFAULT_DIM_DURATION;
-                if (targetAlpha > dimAmount) {
-                    duration = getDimLayerFadeDuration(duration);
-                }
-                state.dimLayer.show(dimLayer, dimAmount, duration);
-
-                // If we showed a dim layer, make sure to redo the layout because some things depend
-                // on whether a dim layer is showing or not.
-                if (targetAlpha == 0) {
-                    mDisplayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_LAYOUT;
-                    mDisplayContent.setLayoutNeeded();
-                }
-            }
-        } else if (state.dimLayer.getLayer() != dimLayer) {
-            state.dimLayer.setLayer(dimLayer);
-        }
-        if (state.dimLayer.isAnimating()) {
-            if (!mDisplayContent.okToAnimate()) {
-                // Jump to the end of the animation.
-                state.dimLayer.show();
-            } else {
-                return state.dimLayer.stepAnimation();
-            }
-        }
-        return false;
-    }
-
-    boolean isDimming(DimLayer.DimLayerUser dimLayerUser, WindowStateAnimator winAnimator) {
-        DimLayerState state = mState.get(dimLayerUser);
-        return state != null && state.animator == winAnimator && state.dimLayer.isDimming();
-    }
-
-    private long getDimLayerFadeDuration(long duration) {
-        TypedValue tv = new TypedValue();
-        mDisplayContent.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 close() {
-        for (int i = mState.size() - 1; i >= 0; i--) {
-            DimLayerState state = mState.valueAt(i);
-            state.dimLayer.destroySurface();
-        }
-        mState.clear();
-        mSharedFullScreenDimLayer = null;
-    }
-
-    void removeDimLayerUser(DimLayer.DimLayerUser dimLayerUser) {
-        DimLayerState state = mState.get(dimLayerUser);
-        if (state != null) {
-            // Destroy the surface, unless it's the shared fullscreen dim.
-            if (state.dimLayer != mSharedFullScreenDimLayer) {
-                state.dimLayer.destroySurface();
-            }
-            mState.remove(dimLayerUser);
-        }
-        if (mState.isEmpty()) {
-            mSharedFullScreenDimLayer = null;
-        }
-    }
-
-    @VisibleForTesting
-    boolean hasDimLayerUser(DimLayer.DimLayerUser dimLayerUser) {
-        return mState.containsKey(dimLayerUser);
-    }
-
-    @VisibleForTesting
-    boolean hasSharedFullScreenDimLayer() {
-        return mSharedFullScreenDimLayer != null;
-    }
-
-    void applyDimBehind(DimLayer.DimLayerUser dimLayerUser, WindowStateAnimator animator) {
-        applyDim(dimLayerUser, animator, false /* aboveApp */);
-    }
-
-    void applyDimAbove(DimLayer.DimLayerUser dimLayerUser, WindowStateAnimator animator) {
-        applyDim(dimLayerUser, animator, true /* aboveApp */);
-    }
-
-    void applyDim(
-            DimLayer.DimLayerUser dimLayerUser, WindowStateAnimator animator, boolean aboveApp) {
-        if (dimLayerUser == null) {
-            Slog.e(TAG, "Trying to apply dim layer for: " + this
-                    + ", but no dim layer user found.");
-            return;
-        }
-        if (!getContinueDimming(dimLayerUser)) {
-            setContinueDimming(dimLayerUser);
-            if (!isDimming(dimLayerUser, animator)) {
-                if (DEBUG_DIM_LAYER) Slog.v(TAG, "Win " + this + " start dimming.");
-                startDimmingIfNeeded(dimLayerUser, animator, aboveApp);
-            }
-        }
-    }
-
-    private static class DimLayerState {
-        // The particular window requesting a dim layer. If null, hide dimLayer.
-        WindowStateAnimator animator;
-        // Set to false at the start of performLayoutAndPlaceSurfaces. If it is still false by the
-        // end then stop any dimming.
-        boolean continueDimming;
-        DimLayer dimLayer;
-        boolean dimAbove;
-    }
-
-    void dump(String prefix, PrintWriter pw) {
-        pw.println(prefix + "DimLayerController");
-        final String doubleSpace = "  ";
-        final String prefixPlusDoubleSpace = prefix + doubleSpace;
-
-        for (int i = 0, n = mState.size(); i < n; i++) {
-            pw.println(prefixPlusDoubleSpace + mState.keyAt(i).toShortString());
-            DimLayerState state = mState.valueAt(i);
-            pw.println(prefixPlusDoubleSpace + doubleSpace + "dimLayer="
-                    + (state.dimLayer == mSharedFullScreenDimLayer ? "shared" : state.dimLayer)
-                    + ", animator=" + state.animator + ", continueDimming=" + state.continueDimming);
-            if (state.dimLayer != null) {
-                state.dimLayer.printTo(prefixPlusDoubleSpace + doubleSpace, pw);
-            }
-        }
-    }
-}
diff --git a/services/core/java/com/android/server/wm/Dimmer.java b/services/core/java/com/android/server/wm/Dimmer.java
new file mode 100644 (file)
index 0000000..9fe16ae
--- /dev/null
@@ -0,0 +1,195 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.wm;
+
+import android.util.ArrayMap;
+import android.util.Slog;
+import android.view.SurfaceControl;
+import android.graphics.Rect;
+
+/**
+ * Utility class for use by a WindowContainer implementation to add "DimLayer" support, that is
+ * black layers of varying opacity at various Z-levels which create the effect of a Dim.
+ */
+class Dimmer {
+    private static final String TAG = "WindowManager";
+
+    private class DimState {
+        SurfaceControl mSurfaceControl;
+        boolean mDimming;
+
+        /**
+         * Used for Dims not assosciated with a WindowContainer. See {@link Dimmer#dimAbove} for
+         * details on Dim lifecycle.
+         */
+        boolean mDontReset;
+
+        DimState(SurfaceControl ctl) {
+            mSurfaceControl = ctl;
+            mDimming = true;
+        }
+    };
+
+    private ArrayMap<WindowContainer, DimState> mDimLayerUsers = new ArrayMap<>();
+
+    /**
+     * The {@link WindowContainer} that our Dim's are bounded to. We may be dimming on behalf of the
+     * host, some controller of it, or one of the hosts children.
+     */
+    private WindowContainer mHost;
+
+    Dimmer(WindowContainer host) {
+        mHost = host;
+    }
+
+    SurfaceControl makeDimLayer() {
+        final SurfaceControl control = mHost.makeChildSurface(null)
+                .setParent(mHost.getSurfaceControl())
+                .setColorLayer(true)
+                .setName("Dim Layer for - " + mHost.getName())
+                .build();
+        return control;
+    }
+
+    /**
+     * Retreive the DimState for a given child of the host.
+     */
+    DimState getDimState(WindowContainer container) {
+        DimState state = mDimLayerUsers.get(container);
+        if (state == null) {
+            final SurfaceControl ctl = makeDimLayer();
+            state = new DimState(ctl);
+            /**
+             * See documentation on {@link #dimAbove} to understand lifecycle management of Dim's
+             * via state resetting for Dim's with containers.
+             */
+            if (container == null) {
+                state.mDontReset = true;
+            }
+            mDimLayerUsers.put(container, state);
+        }
+        return state;
+    }
+
+    private void dim(SurfaceControl.Transaction t, WindowContainer container, int relativeLayer,
+            float alpha) {
+        final DimState d = getDimState(container);
+        t.show(d.mSurfaceControl);
+        if (container != null) {
+            t.setRelativeLayer(d.mSurfaceControl,
+                    container.getSurfaceControl(), relativeLayer);
+        } else {
+            t.setLayer(d.mSurfaceControl, Integer.MAX_VALUE);
+        }
+        t.setAlpha(d.mSurfaceControl, alpha);
+
+        d.mDimming = true;
+    }
+
+    /**
+     * Finish a dim started by dimAbove in the case there was no call to dimAbove.
+     *
+     * @param t A Transaction in which to finish the dim.
+     */
+    void stopDim(SurfaceControl.Transaction t) {
+        DimState d = getDimState(null);
+        t.hide(d.mSurfaceControl);
+        d.mDontReset = false;
+    }
+    /**
+     * Place a Dim above the entire host container. The caller is responsible for calling stopDim to
+     * remove this effect. If the Dim can be assosciated with a particular child of the host
+     * consider using the other variant of dimAbove which ties the Dim lifetime to the child
+     * lifetime more explicitly.
+     *
+     * @param t A transaction in which to apply the Dim.
+     * @param alpha The alpha at which to Dim.
+     */
+    void dimAbove(SurfaceControl.Transaction t, float alpha) {
+        dim(t, null, 1, alpha);
+    }
+
+    /**
+     * Place a dim above the given container, which should be a child of the host container.
+     * for each call to {@link WindowContainer#prepareSurfaces} the Dim state will be reset
+     * and the child should call dimAbove again to request the Dim to continue.
+     *
+     * @param t A transaction in which to apply the Dim.
+     * @param container The container which to dim above. Should be a child of our host.
+     * @param alpha The alpha at which to Dim.
+     */
+    void dimAbove(SurfaceControl.Transaction t, WindowContainer container, float alpha) {
+        dim(t, container, 1, alpha);
+    }
+
+    /**
+     * Like {@link #dimAbove} but places the dim below the given container.
+     *
+     * @param t A transaction in which to apply the Dim.
+     * @param container The container which to dim below. Should be a child of our host.
+     * @param alpha The alpha at which to Dim.
+     */
+
+    void dimBelow(SurfaceControl.Transaction t, WindowContainer container, float alpha) {
+        dim(t, container, -1, alpha);
+    }
+
+    /**
+     * Mark all dims as pending completion on the next call to {@link #updateDims}
+     *
+     * This is intended for us by the host container, to be called at the beginning of
+     * {@link WindowContainer#prepareSurfaces}. After calling this, the container should
+     * chain {@link WindowContainer#prepareSurfaces} down to it's children to give them
+     * a chance to request dims to continue.
+     */
+    void resetDimStates() {
+        for (int i = mDimLayerUsers.size() - 1; i >= 0; i--) {
+            final DimState state = mDimLayerUsers.valueAt(i);
+            if (state.mDontReset == false) {
+                state.mDimming = false;
+            }
+        }
+    }
+
+    /**
+     * Call after invoking {@link WindowContainer#prepareSurfaces} on children as
+     * described in {@link #resetDimStates}.
+     *
+     * @param t A transaction in which to update the dims.
+     * @param bounds The bounds at which to dim.
+     * @return true if any Dims were updated.
+     */
+    boolean updateDims(SurfaceControl.Transaction t, Rect bounds) {
+        boolean didSomething = false;
+        for (int i = mDimLayerUsers.size() - 1; i >= 0; i--) {
+            DimState state = mDimLayerUsers.valueAt(i);
+            // TODO: We want to animate the addition and removal of Dim's instead of immediately
+            // acting. When we do this we need to take care to account for the "Replacing Windows"
+            // case (and seamless dim transfer).
+            if (state.mDimming == false) {
+                mDimLayerUsers.removeAt(i);
+                state.mSurfaceControl.destroy();
+            } else {
+                didSomething = true;
+                // TODO: Once we use geometry from hierarchy this falls away.
+                t.setSize(state.mSurfaceControl, bounds.width(), bounds.height());
+                t.setPosition(state.mSurfaceControl, bounds.left, bounds.top);
+            }
+        }
+        return didSomething;
+    }
+}
index 9494ade..17312b2 100644 (file)
@@ -323,8 +323,6 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
     final DockedStackDividerController mDividerControllerLocked;
     final PinnedStackController mPinnedStackControllerLocked;
 
-    DimLayerController mDimLayerController;
-
     final ArrayList<WindowState> mTapExcludedWindows = new ArrayList<>();
 
     private boolean mHaveBootMsg = false;
@@ -584,12 +582,6 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
                     w.updateLastInsetValues();
                 }
 
-                // Window frames may have changed. Update dim layer with the new bounds.
-                final Task task = w.getTask();
-                if (task != null) {
-                    mDimLayerController.updateDimLayer(task);
-                }
-
                 if (DEBUG_LAYOUT) Slog.v(TAG, "  LAYOUT: mFrame=" + w.mFrame
                         + " mContainingFrame=" + w.mContainingFrame
                         + " mDisplayFrame=" + w.mDisplayFrame);
@@ -683,8 +675,6 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
             }
         }
 
-        w.applyDimLayerIfNeeded();
-
         if (isDefaultDisplay && obscuredChanged && w.isVisibleLw()
                 && mWallpaperController.isWallpaperTarget(w)) {
             // This is the wallpaper target and its obscured state changed... make sure the
@@ -789,7 +779,6 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
         initializeDisplayBaseInfo();
         mDividerControllerLocked = new DockedStackDividerController(service, this);
         mPinnedStackControllerLocked = new PinnedStackController(service, this);
-        mDimLayerController = new DimLayerController(this);
 
         mSurfaceSize = Math.max(mBaseDisplayHeight, mBaseDisplayWidth);
 
@@ -799,13 +788,13 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
         mWindowingLayer = b.setName("Display Root").build();
         mOverlayLayer = b.setName("Display Overlays").build();
 
-        mPendingTransaction.setLayer(mWindowingLayer, 0)
+        getPendingTransaction().setLayer(mWindowingLayer, 0)
                 .setLayerStack(mWindowingLayer, mDisplayId)
                 .show(mWindowingLayer)
                 .setLayer(mOverlayLayer, 1)
                 .setLayerStack(mOverlayLayer, mDisplayId)
                 .show(mOverlayLayer);
-        mPendingTransaction.apply();
+        getPendingTransaction().apply();
 
         // These are the only direct children we should ever have and they are permanent.
         super.addChild(mBelowAppWindowsContainers, null);
@@ -1069,11 +1058,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
 
         setLayoutNeeded();
         final int[] anim = new int[2];
-        if (isDimming()) {
-            anim[0] = anim[1] = 0;
-        } else {
-            mService.mPolicy.selectRotationAnimationLw(anim);
-        }
+        mService.mPolicy.selectRotationAnimationLw(anim);
 
         if (!rotateSeamlessly) {
             mService.startFreezingDisplayLocked(inTransaction, anim[0], anim[1], this);
@@ -1945,22 +1930,6 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
         }
     }
 
-    boolean animateDimLayers() {
-        return mDimLayerController.animateDimLayers();
-    }
-
-    private void resetDimming() {
-        mDimLayerController.resetDimming();
-    }
-
-    boolean isDimming() {
-        return mDimLayerController.isDimming();
-    }
-
-    private void stopDimmingIfNeeded() {
-        mDimLayerController.stopDimmingIfNeeded();
-    }
-
     @Override
     void removeIfPossible() {
         if (isAnimating()) {
@@ -1976,7 +1945,6 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
         try {
             super.removeImmediately();
             if (DEBUG_DISPLAY) Slog.v(TAG_WM, "Removing display=" + this);
-            mDimLayerController.close();
             if (mService.canDispatchPointerEvents()) {
                 if (mTapDetector != null) {
                     mService.unregisterPointerEventListener(mTapDetector);
@@ -2269,8 +2237,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
                 token.dump(pw, "    ");
             }
         }
-        pw.println();
-        mDimLayerController.dump(prefix, pw);
+
         pw.println();
 
         // Dump stack references
@@ -2383,12 +2350,12 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
 
     /** Updates the layer assignment of windows on this display. */
     void assignWindowLayers(boolean setLayoutNeeded) {
-        assignChildLayers(mPendingTransaction);
+        assignChildLayers(getPendingTransaction());
         if (setLayoutNeeded) {
             setLayoutNeeded();
         }
 
-        // We accumlate the layer changes in-to "mPendingTransaction" but we defer
+        // We accumlate the layer changes in-to "getPendingTransaction()" but we defer
         // the application of this transaction until the animation pass triggers
         // prepareSurfaces. This allows us to synchronize Z-ordering changes with
         // the hiding and showing of surfaces.
@@ -2889,7 +2856,6 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
         } while (pendingLayoutChanges != 0);
 
         mTmpApplySurfaceChangesTransactionState.reset();
-        resetDimming();
 
         mTmpRecoveringMemory = recoveringMemory;
         forAllWindows(mApplySurfaceChangesTransaction, true /* traverseTopToBottom */);
@@ -2900,8 +2866,6 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
                 mTmpApplySurfaceChangesTransactionState.preferredModeId,
                 true /* inTraversal, must call performTraversalInTrans... below */);
 
-        stopDimmingIfNeeded();
-
         final boolean wallpaperVisible = mWallpaperController.isWallpaperVisible();
         if (wallpaperVisible != mLastWallpaperVisible) {
             mLastWallpaperVisible = wallpaperVisible;
@@ -3850,10 +3814,15 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
 
     @Override
     SurfaceControl.Builder makeChildSurface(WindowContainer child) {
-        final SurfaceControl.Builder b = mService.makeSurfaceBuilder(child.getSession());
-        b.setName(child.getName());
-
+        SurfaceSession s = child != null ? child.getSession() : getSession();
+        final SurfaceControl.Builder b = mService.makeSurfaceBuilder(s);
         b.setSize(mSurfaceSize, mSurfaceSize);
+
+        if (child == null) {
+            return b;
+        }
+
+        b.setName(child.getName());
         if (child.isScreenOverlay()) {
             return b.setParent(mOverlayLayer);
         } else {
@@ -3873,8 +3842,8 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
     }
 
     void applyMagnificationSpec(MagnificationSpec spec) {
-        applyMagnificationSpec(mPendingTransaction, spec);
-        mPendingTransaction.apply();
+        applyMagnificationSpec(getPendingTransaction(), spec);
+        getPendingTransaction().apply();
     }
 
     @Override
index 4b18d59..8308417 100644 (file)
@@ -54,7 +54,6 @@ import android.view.inputmethod.InputMethodManagerInternal;
 import com.android.internal.policy.DividerSnapAlgorithm;
 import com.android.internal.policy.DockedDividerUtils;
 import com.android.server.LocalServices;
-import com.android.server.wm.DimLayer.DimLayerUser;
 import com.android.server.wm.WindowManagerService.H;
 
 import java.io.PrintWriter;
@@ -62,7 +61,7 @@ import java.io.PrintWriter;
 /**
  * Keeps information about the docked stack divider.
  */
-public class DockedStackDividerController implements DimLayerUser {
+public class DockedStackDividerController {
 
     private static final String TAG = TAG_WITH_CLASS_NAME ? "DockedStackDividerController" : TAG_WM;
 
@@ -114,7 +113,6 @@ public class DockedStackDividerController implements DimLayerUser {
     private boolean mLastVisibility = false;
     private final RemoteCallbackList<IDockedStackListener> mDockedStackListeners
             = new RemoteCallbackList<>();
-    private final DimLayer mDimLayer;
 
     private boolean mMinimizedDock;
     private int mOriginalDockedSide = DOCKED_INVALID;
@@ -141,13 +139,12 @@ public class DockedStackDividerController implements DimLayerUser {
     private boolean mImeHideRequested;
     private final Rect mLastDimLayerRect = new Rect();
     private float mLastDimLayerAlpha;
+    private TaskStack mDimmedStack;
 
     DockedStackDividerController(WindowManagerService service, DisplayContent displayContent) {
         mService = service;
         mDisplayContent = displayContent;
         final Context context = service.mContext;
-        mDimLayer = new DimLayer(displayContent.mService, this, displayContent,
-                "DockedStackDim");
         mMinimizedDockInterpolator = AnimationUtils.loadInterpolator(
                 context, android.R.interpolator.fast_out_slow_in);
         loadDimens();
@@ -463,6 +460,11 @@ public class DockedStackDividerController implements DimLayerUser {
         }
         mOriginalDockedSide = DOCKED_INVALID;
         setMinimizedDockedStack(false /* minimizedDock */, false /* animate */);
+
+        if (mDimmedStack != null) {
+            mDimmedStack.stopDimming();
+            mDimmedStack = null;
+        }
     }
 
     /**
@@ -564,34 +566,12 @@ public class DockedStackDividerController implements DimLayerUser {
         final TaskStack dockedStack = mDisplayContent.getSplitScreenPrimaryStack();
         boolean visibleAndValid = visible && stack != null && dockedStack != null;
         if (visibleAndValid) {
-            stack.getDimBounds(mTmpRect);
-            if (mTmpRect.height() > 0 && mTmpRect.width() > 0) {
-                if (!mLastDimLayerRect.equals(mTmpRect) || mLastDimLayerAlpha != alpha) {
-                    try {
-                        // TODO: This should use the regular animation transaction - here and below
-                        mService.openSurfaceTransaction();
-                        mDimLayer.setBounds(mTmpRect);
-                        mDimLayer.show(getResizeDimLayer(), alpha, 0 /* duration */);
-                    } finally {
-                        mService.closeSurfaceTransaction("setResizeDimLayer");
-                    }
-                }
-                mLastDimLayerRect.set(mTmpRect);
-                mLastDimLayerAlpha = alpha;
-            } else {
-                visibleAndValid = false;
-            }
+            mDimmedStack = stack;
+            stack.dim(alpha);
         }
-        if (!visibleAndValid) {
-            if (mLastDimLayerAlpha != 0f) {
-                try {
-                    mService.openSurfaceTransaction();
-                    mDimLayer.hide();
-                } finally {
-                    mService.closeSurfaceTransaction("setResizeDimLayer");
-                }
-            }
-            mLastDimLayerAlpha = 0f;
+        if (!visibleAndValid && stack != null) {
+            mDimmedStack = null;
+            stack.stopDimming();
         }
     }
 
@@ -829,12 +809,8 @@ public class DockedStackDividerController implements DimLayerUser {
             return animateForMinimizedDockedStack(now);
         } else if (mAnimatingForIme) {
             return animateForIme(now);
-        } else {
-            if (mDimLayer != null && mDimLayer.isDimming()) {
-                mDimLayer.setLayer(getResizeDimLayer());
-            }
-            return false;
         }
+        return false;
     }
 
     private boolean animateForIme(long now) {
@@ -942,27 +918,6 @@ public class DockedStackDividerController implements DimLayerUser {
                 + (1 - t) * (CLIP_REVEAL_MEET_LAST - CLIP_REVEAL_MEET_EARLIEST);
     }
 
-    @Override
-    public boolean dimFullscreen() {
-        return false;
-    }
-
-    @Override
-    public DisplayInfo getDisplayInfo() {
-        return mDisplayContent.getDisplayInfo();
-    }
-
-    @Override
-    public boolean isAttachedToDisplay() {
-        return mDisplayContent != null;
-    }
-
-    @Override
-    public void getDimBounds(Rect outBounds) {
-        // This dim layer user doesn't need this.
-    }
-
-    @Override
     public String toShortString() {
         return TAG;
     }
@@ -977,10 +932,6 @@ public class DockedStackDividerController implements DimLayerUser {
         pw.println(prefix + "  mMinimizedDock=" + mMinimizedDock);
         pw.println(prefix + "  mAdjustedForIme=" + mAdjustedForIme);
         pw.println(prefix + "  mAdjustedForDivider=" + mAdjustedForDivider);
-        if (mDimLayer.isDimming()) {
-            pw.println(prefix + "  Dim layer is dimming: ");
-            mDimLayer.printTo(prefix + "    ", pw);
-        }
     }
 
     void writeToProto(ProtoOutputStream proto, long fieldId) {
index a7ba9c7..f70845e 100644 (file)
@@ -51,7 +51,7 @@ import com.android.internal.annotations.VisibleForTesting;
 import java.io.PrintWriter;
 import java.util.function.Consumer;
 
-class Task extends WindowContainer<AppWindowToken> implements DimLayer.DimLayerUser {
+class Task extends WindowContainer<AppWindowToken> {
     static final String TAG = TAG_WITH_CLASS_NAME ? "Task" : TAG_WM;
     // Return value from {@link setBounds} indicating no change was made to the Task bounds.
     private static final int BOUNDS_CHANGE_NONE = 0;
@@ -105,6 +105,9 @@ class Task extends WindowContainer<AppWindowToken> implements DimLayer.DimLayerU
     // stack moves and we in fact do so when moving from full screen to pinned.
     private boolean mPreserveNonFloatingState = false;
 
+    private Dimmer mDimmer = new Dimmer(this);
+    private final Rect mTmpDimBoundsRect = new Rect();
+
     Task(int taskId, TaskStack stack, int userId, WindowManagerService service, Rect bounds,
             int resizeMode, boolean supportsPictureInPicture, TaskDescription taskDescription,
             TaskWindowContainerController controller) {
@@ -188,12 +191,6 @@ class Task extends WindowContainer<AppWindowToken> implements DimLayer.DimLayerU
         EventLog.writeEvent(WM_TASK_REMOVED, mTaskId, "removeTask");
         mDeferRemoval = false;
 
-        // Make sure to remove dim layer user first before removing task its from parent.
-        DisplayContent content = getDisplayContent();
-        if (content != null) {
-            content.mDimLayerController.removeDimLayerUser(this);
-        }
-
         super.removeImmediately();
     }
 
@@ -314,9 +311,7 @@ class Task extends WindowContainer<AppWindowToken> implements DimLayer.DimLayerU
         mBounds.set(bounds);
 
         mRotation = rotation;
-        if (displayContent != null) {
-            displayContent.mDimLayerController.updateDimLayer(this);
-        }
+
         onOverrideConfigurationChanged(overrideConfig);
         return boundsChange;
     }
@@ -484,7 +479,6 @@ class Task extends WindowContainer<AppWindowToken> implements DimLayer.DimLayerU
     }
 
     /** Bounds of the task to be used for dimming, as well as touch related tests. */
-    @Override
     public void getDimBounds(Rect out) {
         final DisplayContent displayContent = mStack.getDisplayContent();
         // It doesn't matter if we in particular are part of the resize, since we couldn't have
@@ -636,23 +630,6 @@ class Task extends WindowContainer<AppWindowToken> implements DimLayer.DimLayerU
         return null;
     }
 
-    @Override
-    public boolean dimFullscreen() {
-        return isFullscreen();
-    }
-
-    @Override
-    public int getLayerForDim(WindowStateAnimator animator, int layerOffset, int defaultLayer) {
-        // If the dim layer is for a starting window, move the dim layer back in the z-order behind
-        // the lowest activity window to ensure it does not occlude the main window if it is
-        // translucent
-        final AppWindowToken appToken = animator.mWin.mAppToken;
-        if (animator.mAttrType == TYPE_APPLICATION_STARTING && hasChild(appToken) ) {
-            return Math.min(defaultLayer, appToken.getLowestAnimLayer() - layerOffset);
-        }
-        return defaultLayer;
-    }
-
     boolean isFullscreen() {
         if (useCurrentBounds()) {
             return mFillsParent;
@@ -663,16 +640,6 @@ class Task extends WindowContainer<AppWindowToken> implements DimLayer.DimLayerU
         return true;
     }
 
-    @Override
-    public DisplayInfo getDisplayInfo() {
-        return getDisplayContent().getDisplayInfo();
-    }
-
-    @Override
-    public boolean isAttachedToDisplay() {
-        return getDisplayContent() != null;
-    }
-
     void forceWindowsScaleable(boolean force) {
         mService.openSurfaceTransaction();
         try {
@@ -720,9 +687,18 @@ class Task extends WindowContainer<AppWindowToken> implements DimLayer.DimLayerU
         mPreserveNonFloatingState = false;
     }
 
+    Dimmer getDimmer() {
+        return mDimmer;
+    }
+
     @Override
-    public String toShortString() {
-        return "Task=" + mTaskId;
+    void prepareSurfaces() {
+        mDimmer.resetDimStates();
+        super.prepareSurfaces();
+        getDimBounds(mTmpDimBoundsRect);
+        if (mDimmer.updateDims(getPendingTransaction(), mTmpDimBoundsRect)) {
+            scheduleAnimation();
+        }
     }
 
     @CallSuper
@@ -759,4 +735,8 @@ class Task extends WindowContainer<AppWindowToken> implements DimLayer.DimLayerU
             wtoken.dump(pw, triplePrefix);
         }
     }
+
+    String toShortString() {
+        return "Task=" + mTaskId;
+    }
 }
index f2bd898..5d4ba09 100644 (file)
@@ -59,7 +59,7 @@ import com.android.server.wm.WindowManagerService.H;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 
-class TaskPositioner implements DimLayer.DimLayerUser {
+class TaskPositioner {
     private static final boolean DEBUG_ORIENTATION_VIOLATIONS = false;
     private static final String TAG_LOCAL = "TaskPositioner";
     private static final String TAG = TAG_WITH_CLASS_NAME ? TAG_LOCAL : TAG_WM;
@@ -99,9 +99,6 @@ class TaskPositioner implements DimLayer.DimLayerUser {
     private WindowPositionerEventReceiver mInputEventReceiver;
     private Display mDisplay;
     private final DisplayMetrics mDisplayMetrics = new DisplayMetrics();
-    private DimLayer mDimLayer;
-    @CtrlType
-    private int mCurrentDimSide;
     private Rect mTmpRect = new Rect();
     private int mSideMargin;
     private int mMinVisibleWidth;
@@ -207,15 +204,6 @@ class TaskPositioner implements DimLayer.DimLayerUser {
                             mService.mActivityManager.resizeTask(
                                     mTask.mTaskId, mWindowDragBounds, RESIZE_MODE_USER_FORCED);
                         }
-
-                        if (mCurrentDimSide != CTRL_NONE) {
-                            final int createMode = mCurrentDimSide == CTRL_LEFT
-                                    ? SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT
-                                    : SPLIT_SCREEN_CREATE_MODE_BOTTOM_OR_RIGHT;
-                            mService.mActivityManager.setTaskWindowingModeSplitScreenPrimary(
-                                    mTask.mTaskId, createMode, true /*toTop*/, true /* animate */,
-                                    null /* initialBounds */);
-                        }
                     } catch(RemoteException e) {}
 
                     // Post back to WM to handle clean-ups. We still need the input
@@ -307,7 +295,6 @@ class TaskPositioner implements DimLayer.DimLayerUser {
         }
         mService.pauseRotationLocked();
 
-        mDimLayer = new DimLayer(mService, this, displayContent, TAG_LOCAL);
         mSideMargin = dipToPixel(SIDE_MARGIN_DIP, mDisplayMetrics);
         mMinVisibleWidth = dipToPixel(MINIMUM_VISIBLE_WIDTH_IN_DP, mDisplayMetrics);
         mMinVisibleHeight = dipToPixel(MINIMUM_VISIBLE_HEIGHT_IN_DP, mDisplayMetrics);
@@ -338,12 +325,6 @@ class TaskPositioner implements DimLayer.DimLayerUser {
         mDragWindowHandle = null;
         mDragApplicationHandle = null;
         mDisplay = null;
-
-        if (mDimLayer != null) {
-            mDimLayer.destroySurface();
-            mDimLayer = null;
-        }
-        mCurrentDimSide = CTRL_NONE;
         mDragEnded = true;
 
         // Resume rotations after a drag.
@@ -436,7 +417,6 @@ class TaskPositioner implements DimLayer.DimLayerUser {
         }
 
         updateWindowDragBounds(nX, nY, mTmpRect);
-        updateDimLayerVisibility(nX);
         return false;
     }
 
@@ -623,88 +603,6 @@ class TaskPositioner implements DimLayer.DimLayerUser {
                 "updateWindowDragBounds: " + mWindowDragBounds);
     }
 
-    private void updateDimLayerVisibility(int x) {
-        @CtrlType
-        int dimSide = getDimSide(x);
-        if (dimSide == mCurrentDimSide) {
-            return;
-        }
-
-        mCurrentDimSide = dimSide;
-
-        if (SHOW_TRANSACTIONS) Slog.i(TAG, ">>> OPEN TRANSACTION updateDimLayerVisibility");
-        mService.openSurfaceTransaction();
-        if (mCurrentDimSide == CTRL_NONE) {
-            mDimLayer.hide();
-        } else {
-            showDimLayer();
-        }
-        mService.closeSurfaceTransaction("updateDimLayerVisibility");
-    }
-
-    /**
-     * Returns the side of the screen the dim layer should be shown.
-     * @param x horizontal coordinate used to determine if the dim layer should be shown
-     * @return Returns {@link #CTRL_LEFT} if the dim layer should be shown on the left half of the
-     * screen, {@link #CTRL_RIGHT} if on the right side, or {@link #CTRL_NONE} if the dim layer
-     * shouldn't be shown.
-     */
-    private int getDimSide(int x) {
-        if (!mTask.mStack.inFreeformWindowingMode()
-                || !mTask.mStack.fillsParent()
-                || mTask.mStack.getConfiguration().orientation != ORIENTATION_LANDSCAPE) {
-            return CTRL_NONE;
-        }
-
-        mTask.mStack.getDimBounds(mTmpRect);
-        if (x - mSideMargin <= mTmpRect.left) {
-            return CTRL_LEFT;
-        }
-        if (x + mSideMargin >= mTmpRect.right) {
-            return CTRL_RIGHT;
-        }
-
-        return CTRL_NONE;
-    }
-
-    private void showDimLayer() {
-        mTask.mStack.getDimBounds(mTmpRect);
-        if (mCurrentDimSide == CTRL_LEFT) {
-            mTmpRect.right = mTmpRect.centerX();
-        } else if (mCurrentDimSide == CTRL_RIGHT) {
-            mTmpRect.left = mTmpRect.centerX();
-        }
-
-        mDimLayer.setBounds(mTmpRect);
-        mDimLayer.show(mService.getDragLayerLocked(), RESIZING_HINT_ALPHA,
-                RESIZING_HINT_DURATION_MS);
-    }
-
-    @Override /** {@link DimLayer.DimLayerUser} */
-    public boolean dimFullscreen() {
-        return isFullscreen();
-    }
-
-    boolean isFullscreen() {
-        return false;
-    }
-
-    @Override /** {@link DimLayer.DimLayerUser} */
-    public DisplayInfo getDisplayInfo() {
-        return mTask.mStack.getDisplayInfo();
-    }
-
-    @Override
-    public boolean isAttachedToDisplay() {
-        return mTask != null && mTask.getDisplayContent() != null;
-    }
-
-    @Override
-    public void getDimBounds(Rect out) {
-        // This dim layer user doesn't need this.
-    }
-
-    @Override
     public String toShortString() {
         return TAG;
     }
index 112643b..f9062a8 100644 (file)
@@ -55,6 +55,7 @@ import android.util.SparseArray;
 import android.util.proto.ProtoOutputStream;
 import android.view.DisplayInfo;
 import android.view.Surface;
+import android.view.SurfaceControl;
 
 import com.android.internal.policy.DividerSnapAlgorithm;
 import com.android.internal.policy.DividerSnapAlgorithm.SnapTarget;
@@ -63,7 +64,7 @@ import com.android.server.EventLogTags;
 
 import java.io.PrintWriter;
 
-public class TaskStack extends WindowContainer<Task> implements DimLayer.DimLayerUser,
+public class TaskStack extends WindowContainer<Task> implements
         BoundsAnimationTarget {
     /** Minimum size of an adjusted stack bounds relative to original stack bounds. Used to
      * restrict IME adjustment so that a min portion of top stack remains visible.*/
@@ -108,8 +109,8 @@ public class TaskStack extends WindowContainer<Task> implements DimLayer.DimLaye
     /** Density as of last time {@link #mBounds} was set. */
     private int mDensity;
 
-    /** Support for non-zero {@link android.view.animation.Animation#getBackgroundColor()} */
-    private DimLayer mAnimationBackgroundSurface;
+    private SurfaceControl mAnimationBackgroundSurface;
+    private boolean mAnimationBackgroundSurfaceIsShown = false;
 
     /** The particular window with an Animation with non-zero background color. */
     private WindowStateAnimator mAnimationBackgroundAnimator;
@@ -149,6 +150,13 @@ public class TaskStack extends WindowContainer<Task> implements DimLayer.DimLaye
 
     Rect mPreAnimationBounds = new Rect();
 
+    private Dimmer mDimmer = new Dimmer(this);
+
+    /**
+     * For {@link #prepareSurfaces}.
+     */
+    final Rect mTmpDimBoundsRect = new Rect();
+
     TaskStack(WindowManagerService service, int stackId, StackWindowController controller) {
         mService = service;
         mStackId = stackId;
@@ -245,6 +253,35 @@ public class TaskStack extends WindowContainer<Task> implements DimLayer.DimLaye
         }
     }
 
+    private void setAnimationBackgroundBounds(Rect bounds) {
+        if (mAnimationBackgroundSurface == null) {
+            return;
+        }
+        getPendingTransaction().setSize(mAnimationBackgroundSurface, bounds.width(), bounds.height())
+                .setPosition(mAnimationBackgroundSurface, 0, 0);
+        scheduleAnimation();
+    }
+
+    private void hideAnimationSurface() {
+        if (mAnimationBackgroundSurface == null) {
+            return;
+        }
+        getPendingTransaction().hide(mAnimationBackgroundSurface);
+        mAnimationBackgroundSurfaceIsShown = false;
+        scheduleAnimation();
+    }
+
+    private void showAnimationSurface(float alpha) {
+        if (mAnimationBackgroundSurface == null) {
+            return;
+        }
+        getPendingTransaction().setLayer(mAnimationBackgroundSurface, Integer.MIN_VALUE)
+                .setAlpha(mAnimationBackgroundSurface, alpha)
+                .show(mAnimationBackgroundSurface);
+        mAnimationBackgroundSurfaceIsShown = true;
+        scheduleAnimation();
+    }
+
     private boolean setBounds(Rect bounds) {
         boolean oldFullscreen = mFillsParent;
         int rotation = Surface.ROTATION_0;
@@ -267,10 +304,7 @@ public class TaskStack extends WindowContainer<Task> implements DimLayer.DimLaye
             return false;
         }
 
-        if (mDisplayContent != null) {
-            mDisplayContent.mDimLayerController.updateDimLayer(this);
-            mAnimationBackgroundSurface.setBounds(bounds);
-        }
+        setAnimationBackgroundBounds(bounds);
 
         mBounds.set(bounds);
         mRotation = rotation;
@@ -368,7 +402,6 @@ public class TaskStack extends WindowContainer<Task> implements DimLayer.DimLaye
     }
 
     /** Bounds of the stack with other system factors taken into consideration. */
-    @Override
     public void getDimBounds(Rect out) {
         getBounds(out);
     }
@@ -700,9 +733,12 @@ public class TaskStack extends WindowContainer<Task> implements DimLayer.DimLaye
         }
 
         mDisplayContent = dc;
-        mAnimationBackgroundSurface = new DimLayer(mService, this, mDisplayContent,
-                "animation background stackId=" + mStackId);
+
         updateBoundsForWindowModeChange();
+        mAnimationBackgroundSurface = makeChildSurface(null).setColorLayer(true)
+            .setName("animation background stackId=" + mStackId)
+            .build();
+
         super.onDisplayChanged(dc);
     }
 
@@ -920,12 +956,10 @@ public class TaskStack extends WindowContainer<Task> implements DimLayer.DimLaye
             return;
         }
 
-        // Looks like the stack was removed from the display. Go ahead and clean things up.
-        mDisplayContent.mDimLayerController.removeDimLayerUser(this);
         EventLog.writeEvent(EventLogTags.WM_STACK_REMOVED, mStackId);
 
         if (mAnimationBackgroundSurface != null) {
-            mAnimationBackgroundSurface.destroySurface();
+            mAnimationBackgroundSurface.destroy();
             mAnimationBackgroundSurface = null;
         }
 
@@ -935,9 +969,7 @@ public class TaskStack extends WindowContainer<Task> implements DimLayer.DimLaye
 
     void resetAnimationBackgroundAnimator() {
         mAnimationBackgroundAnimator = null;
-        if (mAnimationBackgroundSurface != null) {
-            mAnimationBackgroundSurface.hide();
-        }
+        hideAnimationSurface();
     }
 
     void setAnimationBackground(WindowStateAnimator winAnimator, int color) {
@@ -946,8 +978,7 @@ public class TaskStack extends WindowContainer<Task> implements DimLayer.DimLaye
                 || animLayer < mAnimationBackgroundAnimator.mAnimLayer) {
             mAnimationBackgroundAnimator = winAnimator;
             animLayer = mDisplayContent.getLayerForAnimationBackground(winAnimator);
-            mAnimationBackgroundSurface.show(animLayer - LAYER_OFFSET_DIM,
-                    ((color >> 24) & 0xff) / 255f, 0);
+            showAnimationSurface(((color >> 24) & 0xff) / 255f);
         }
     }
 
@@ -1252,7 +1283,7 @@ public class TaskStack extends WindowContainer<Task> implements DimLayer.DimLaye
         }
         proto.write(FILLS_PARENT, mFillsParent);
         mBounds.writeToProto(proto, BOUNDS);
-        proto.write(ANIMATION_BACKGROUND_SURFACE_IS_DIMMING, mAnimationBackgroundSurface.isDimming());
+        proto.write(ANIMATION_BACKGROUND_SURFACE_IS_DIMMING, mAnimationBackgroundSurfaceIsShown);
         proto.end(token);
     }
 
@@ -1275,9 +1306,8 @@ public class TaskStack extends WindowContainer<Task> implements DimLayer.DimLaye
         for (int taskNdx = mChildren.size() - 1; taskNdx >= 0; taskNdx--) {
             mChildren.get(taskNdx).dump(prefix + "  ", pw);
         }
-        if (mAnimationBackgroundSurface.isDimming()) {
-            pw.println(prefix + "mWindowAnimationBackgroundSurface:");
-            mAnimationBackgroundSurface.printTo(prefix + "  ", pw);
+        if (mAnimationBackgroundSurfaceIsShown) {
+            pw.println(prefix + "mWindowAnimationBackgroundSurface is shown");
         }
         if (!mExitingAppTokens.isEmpty()) {
             pw.println();
@@ -1301,11 +1331,6 @@ public class TaskStack extends WindowContainer<Task> implements DimLayer.DimLaye
     }
 
     @Override
-    public boolean dimFullscreen() {
-        return !isActivityTypeStandard() || fillsParent();
-    }
-
-    @Override
     boolean fillsParent() {
         if (useCurrentBounds()) {
             return mFillsParent;
@@ -1317,16 +1342,6 @@ public class TaskStack extends WindowContainer<Task> implements DimLayer.DimLaye
     }
 
     @Override
-    public DisplayInfo getDisplayInfo() {
-        return mDisplayContent.getDisplayInfo();
-    }
-
-    @Override
-    public boolean isAttachedToDisplay() {
-        return mDisplayContent != null;
-    }
-
-    @Override
     public String toString() {
         return "{stackId=" + mStackId + " tasks=" + mChildren + "}";
     }
@@ -1335,7 +1350,6 @@ public class TaskStack extends WindowContainer<Task> implements DimLayer.DimLaye
         return toShortString();
     }
 
-    @Override
     public String toShortString() {
         return "Stack=" + mStackId;
     }
@@ -1693,4 +1707,32 @@ public class TaskStack extends WindowContainer<Task> implements DimLayer.DimLaye
                 || activityType == ACTIVITY_TYPE_RECENTS
                 || activityType == ACTIVITY_TYPE_ASSISTANT;
     }
+
+    Dimmer getDimmer() {
+        return mDimmer;
+    }
+
+    @Override
+    void prepareSurfaces() {
+        mDimmer.resetDimStates();
+        super.prepareSurfaces();
+        getDimBounds(mTmpDimBoundsRect);
+        if (mDimmer.updateDims(getPendingTransaction(), mTmpDimBoundsRect)) {
+            scheduleAnimation();
+        }
+    }
+
+    public DisplayInfo getDisplayInfo() {
+        return mDisplayContent.getDisplayInfo();
+    }
+
+    void dim(float alpha) {
+        mDimmer.dimAbove(getPendingTransaction(), alpha);
+        scheduleAnimation();
+    }
+
+    void stopDimming() {
+        mDimmer.stopDim(getPendingTransaction());
+        scheduleAnimation();
+    }
 }
index 4a70a15..20bade6 100644 (file)
@@ -214,8 +214,6 @@ public class WindowAnimator {
                     if (screenRotationAnimation != null) {
                         screenRotationAnimation.updateSurfacesInTransaction();
                     }
-
-                    orAnimating(dc.animateDimLayers());
                     orAnimating(dc.getDockedDividerController().animate(mCurrentTime));
                     //TODO (multidisplay): Magnification is supported only for the default display.
                     if (accessibilityController != null && dc.isDefaultDisplay) {
index a32a7f7..a5e6288 100644 (file)
@@ -75,7 +75,7 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<
     /**
      * Applied as part of the animation pass in "prepareSurfaces".
      */
-    protected Transaction mPendingTransaction = new Transaction();
+    private Transaction mPendingTransaction = new Transaction();
 
     @Override
     final protected WindowContainer getParent() {
@@ -119,10 +119,10 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<
             // If we don't yet have a surface, but we now have a parent, we should
             // build a surface.
             mSurfaceControl = makeSurface().build();
-            mPendingTransaction.show(mSurfaceControl);
+            getPendingTransaction().show(mSurfaceControl);
         } else {
             // If we have a surface but a new parent, we just need to perform a reparent.
-            mPendingTransaction.reparent(mSurfaceControl, mParent.mSurfaceControl.getHandle());
+            getPendingTransaction().reparent(mSurfaceControl, mParent.mSurfaceControl.getHandle());
         }
 
         // Either way we need to ask the parent to assign us a Z-order.
@@ -710,12 +710,16 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<
         return p.makeChildSurface(this);
     }
 
+    /**
+     * @param child The WindowContainer this child surface is for, or null if the Surface
+     *              is not assosciated with a WindowContainer (e.g. a surface used for Dimming).
+     */
     SurfaceControl.Builder makeChildSurface(WindowContainer child) {
         final WindowContainer p = getParent();
         // Give the parent a chance to set properties. In hierarchy v1 we rely
         // on this to set full-screen dimensions on all our Surface-less Layers.
         final SurfaceControl.Builder b = p.makeChildSurface(child);
-        if (child.isScreenOverlay()) {
+        if (child != null && child.isScreenOverlay()) {
             // If it's a screen overlay it's been promoted in the hierarchy (wrt to the
             // WindowContainer hierarchy vs the SurfaceControl hierarchy)
             // and we shouldn't set ourselves as the parent.
@@ -786,7 +790,7 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<
     }
 
     void assignChildLayers() {
-        assignChildLayers(mPendingTransaction);
+        assignChildLayers(getPendingTransaction());
     }
 
     boolean needsZBoost() {
@@ -864,7 +868,7 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<
      * rather than merging to global.
      */
     void prepareSurfaces() {
-        SurfaceControl.mergeToGlobalTransaction(mPendingTransaction);
+        SurfaceControl.mergeToGlobalTransaction(getPendingTransaction());
         for (int i = 0; i < mChildren.size(); i++) {
             mChildren.get(i).prepareSurfaces();
         }
@@ -895,4 +899,8 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<
             mParent.destroyAfterPendingTransaction(surface);
         }
     }
+    
+    Transaction getPendingTransaction() {
+        return mPendingTransaction;
+    }
 }
index 7257cc7..4656539 100644 (file)
@@ -2483,11 +2483,8 @@ public class WindowManagerService extends IWindowManager.Stub
                 mWaitingForConfig = true;
                 displayContent.setLayoutNeeded();
                 int anim[] = new int[2];
-                if (displayContent.isDimming()) {
-                    anim[0] = anim[1] = 0;
-                } else {
-                    mPolicy.selectRotationAnimationLw(anim);
-                }
+                mPolicy.selectRotationAnimationLw(anim);
+
                 startFreezingDisplayLocked(false, anim[0], anim[1], displayContent);
                 config = new Configuration(mTempConfiguration);
             }
@@ -5955,8 +5952,7 @@ public class WindowManagerService extends IWindowManager.Stub
             // TODO(multidisplay): rotation on main screen only.
             DisplayInfo displayInfo = displayContent.getDisplayInfo();
             // Get rotation animation again, with new top window
-            boolean isDimming = displayContent.isDimming();
-            if (!mPolicy.validateRotationAnimationLw(mExitAnimId, mEnterAnimId, isDimming)) {
+            if (!mPolicy.validateRotationAnimationLw(mExitAnimId, mEnterAnimId, false)) {
                 mExitAnimId = mEnterAnimId = 0;
             }
             if (screenRotationAnimation.dismiss(MAX_ANIMATION_DURATION,
index 7f07281..9f77886 100644 (file)
@@ -609,6 +609,14 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
                 };
             };
 
+    /**
+     * Indicates whether we have requested a Dim (in the sense of {@link Dimmer}) from our host
+     * container.
+     */
+    private boolean mIsDimming = false;
+
+    private static final float DEFAULT_DIM_AMOUNT_DEAD_WINDOW = 0.5f;
+
     WindowState(WindowManagerService service, Session s, IWindow c, WindowToken token,
            WindowState parentWindow, int appOp, int seq, WindowManager.LayoutParams a,
            int viewVisibility, int ownerId, boolean ownerCanAddInternalSystemWindow) {
@@ -2041,23 +2049,6 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
         return isVisibleOrAdding();
     }
 
-    void scheduleAnimationIfDimming() {
-        final DisplayContent dc = getDisplayContent();
-        if (dc == null) {
-            return;
-        }
-
-        // If layout is currently deferred, we want to hold of with updating the layers.
-        if (mService.mWindowPlacerLocked.isLayoutDeferred()) {
-            return;
-        }
-        final DimLayer.DimLayerUser dimLayerUser = getDimLayerUser();
-        if (dimLayerUser != null && dc.mDimLayerController.isDimming(dimLayerUser, mWinAnimator)) {
-            // Force an animation pass just to update the mDimLayer layer.
-            mService.scheduleAnimationLocked();
-        }
-    }
-
     private final class DeadWindowEventReceiver extends InputEventReceiver {
         DeadWindowEventReceiver(InputChannel inputChannel) {
             super(inputChannel, mService.mH.getLooper());
@@ -2113,31 +2104,12 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
         mInputWindowHandle.inputChannel = null;
     }
 
-    void applyDimLayerIfNeeded() {
-        // When the app is terminated (eg. from Recents), the task might have already been
-        // removed with the window pending removal. Don't apply dim in such cases, as there
-        // will be no more updateDimLayer() calls, which leaves the dimlayer invalid.
-        final AppWindowToken token = mAppToken;
-        if (token != null && token.removed) {
-            return;
-        }
-
-        final DisplayContent dc = getDisplayContent();
-        if (!mAnimatingExit && mAppDied) {
-            // If app died visible, apply a dim over the window to indicate that it's inactive
-            dc.mDimLayerController.applyDimAbove(getDimLayerUser(), mWinAnimator);
-        } else if ((mAttrs.flags & FLAG_DIM_BEHIND) != 0
-                && dc != null && !mAnimatingExit && isVisible()) {
-            dc.mDimLayerController.applyDimBehind(getDimLayerUser(), mWinAnimator);
-        }
-    }
-
-    private DimLayer.DimLayerUser getDimLayerUser() {
+    private Dimmer getDimmer() {
         Task task = getTask();
         if (task != null) {
-            return task;
+            return task.getDimmer();
         }
-        return getStack();
+        return getStack().getDimmer();
     }
 
     /** Returns true if the replacement window was removed. */
@@ -2159,9 +2131,6 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
 
     private void removeReplacedWindow() {
         if (DEBUG_ADD_REMOVE) Slog.d(TAG, "Removing replaced window: " + this);
-        if (isDimming()) {
-            transferDimToReplacement();
-        }
         mWillReplaceWindow = false;
         mAnimateReplacingWindow = false;
         mReplacingRemoveRequested = false;
@@ -2224,11 +2193,11 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
             // need to intercept touches outside of that window. The dim layer user
             // associated with the window (task or stack) will give us the good bounds, as
             // they would be used to display the dim layer.
-            final DimLayer.DimLayerUser dimLayerUser = getDimLayerUser();
-            if (dimLayerUser != null) {
-                dimLayerUser.getDimBounds(mTmpRect);
+            final Task task = getTask();
+            if (task != null) {
+                task.getDimBounds(mTmpRect);
             } else {
-                getVisibleBounds(mTmpRect);
+                getStack().getDimBounds(mTmpRect);
             }
             if (inFreeformWindowingMode()) {
                 // For freeform windows we the touch region to include the whole surface for the
@@ -2736,14 +2705,6 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
         return displayContent.isDefaultDisplay;
     }
 
-    @Override
-    public boolean isDimming() {
-        final DimLayer.DimLayerUser dimLayerUser = getDimLayerUser();
-        final DisplayContent dc = getDisplayContent();
-        return dimLayerUser != null && dc != null
-                && dc.mDimLayerController.isDimming(dimLayerUser, mWinAnimator);
-    }
-
     void setShowToOwnerOnlyLocked(boolean showToOwnerOnly) {
         mShowToOwnerOnly = showToOwnerOnly;
     }
@@ -3598,15 +3559,6 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
         return winY;
     }
 
-    private void transferDimToReplacement() {
-        final DimLayer.DimLayerUser dimLayerUser = getDimLayerUser();
-        final DisplayContent dc = getDisplayContent();
-        if (dimLayerUser != null && dc != null) {
-            dc.mDimLayerController.applyDim(dimLayerUser,
-                    mReplacementWindow.mWinAnimator, (mAttrs.flags & FLAG_DIM_BEHIND) != 0);
-        }
-    }
-
     // During activity relaunch due to resize, we sometimes use window replacement
     // for only child windows (as the main window is handled by window preservation)
     // and the big surface.
@@ -4438,8 +4390,19 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
         return mToken.makeChildSurface(this);
     }
 
+
     @Override
     void prepareSurfaces() {
+        mIsDimming = false;
+        if (!mAnimatingExit && mAppDied) {
+            mIsDimming = true;
+            getDimmer().dimAbove(getPendingTransaction(), this, DEFAULT_DIM_AMOUNT_DEAD_WINDOW);
+        } else if ((mAttrs.flags & FLAG_DIM_BEHIND) != 0
+                && !mAnimatingExit && isVisible()) {
+            mIsDimming = true;
+            getDimmer().dimBelow(getPendingTransaction(), this, mAttrs.dimAmount);
+        }
+
         mWinAnimator.prepareSurfaceLocked(true);
         super.prepareSurfaces();
     }
@@ -4455,4 +4418,9 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
         }
         getDisplayContent().assignRelativeLayerForImeTargetChild(t, this);
     }
+
+    @Override
+    public boolean isDimming() {
+        return mIsDimming;
+    }
 }
index ec08988..840cc40 100644 (file)
@@ -1444,7 +1444,6 @@ class WindowStateAnimator {
             mReportSurfaceResized = true;
             mAnimator.setPendingLayoutChanges(w.getDisplayId(),
                     WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER);
-            w.applyDimLayerIfNeeded();
         }
     }
 
diff --git a/services/tests/servicestests/src/com/android/server/wm/DimLayerControllerTests.java b/services/tests/servicestests/src/com/android/server/wm/DimLayerControllerTests.java
deleted file mode 100644 (file)
index c3a471a..0000000
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.server.wm;
-
-import static android.view.DisplayAdjustments.DEFAULT_DISPLAY_ADJUSTMENTS;
-
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-
-import android.hardware.display.DisplayManagerGlobal;
-import android.platform.test.annotations.Presubmit;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
-import android.view.Display;
-import android.view.DisplayInfo;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-/**
- * Tests for the {@link DimLayerController} class.
- *
- * Build/Install/Run:
- *  bit FrameworksServicesTests:com.android.server.wm.DimLayerControllerTests
- */
-@SmallTest
-@Presubmit
-@org.junit.runner.RunWith(AndroidJUnit4.class)
-public class DimLayerControllerTests extends WindowTestsBase {
-
-    /**
-     * This tests if shared fullscreen dim layer is added when stack is added to display
-     * and is removed when the only stack on the display is removed.
-     */
-    @Test
-    public void testSharedFullScreenDimLayer() throws Exception {
-        // Create a display.
-        final DisplayContent dc = createNewDisplay();
-        assertFalse(dc.mDimLayerController.hasSharedFullScreenDimLayer());
-
-        // Add stack with activity.
-        final TaskStack stack = createTaskStackOnDisplay(dc);
-        assertTrue(dc.mDimLayerController.hasDimLayerUser(stack));
-        assertTrue(dc.mDimLayerController.hasSharedFullScreenDimLayer());
-
-        // Remove the only stack on the display and check if the shared dim layer clears.
-        stack.removeImmediately();
-        assertFalse(dc.mDimLayerController.hasDimLayerUser(stack));
-        assertFalse(dc.mDimLayerController.hasSharedFullScreenDimLayer());
-    }
-}
diff --git a/services/tests/servicestests/src/com/android/server/wm/DimmerTests.java b/services/tests/servicestests/src/com/android/server/wm/DimmerTests.java
new file mode 100644 (file)
index 0000000..f069d49
--- /dev/null
@@ -0,0 +1,207 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.wm;
+
+import java.util.HashMap;
+
+import org.junit.Test;
+import org.junit.Before;
+import org.junit.runner.RunWith;
+
+import android.graphics.Rect;
+import android.platform.test.annotations.Presubmit;
+import android.support.test.runner.AndroidJUnit4;
+import android.view.SurfaceControl;
+import android.view.SurfaceSession;
+
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.eq;
+
+/**
+ * Build/Install/Run:
+ *  bit FrameworksServicesTests:com.android.server.wm.DimmerTests;
+ */
+@Presubmit
+@RunWith(AndroidJUnit4.class)
+public class DimmerTests extends WindowTestsBase {
+    private class TestWindowContainer extends WindowContainer<TestWindowContainer> {
+        final SurfaceControl mControl = mock(SurfaceControl.class);
+        final SurfaceControl.Transaction mTransaction = mock(SurfaceControl.Transaction.class);
+
+        @Override
+        SurfaceControl getSurfaceControl() {
+            return mControl;
+        }
+
+        @Override
+        SurfaceControl.Transaction getPendingTransaction() {
+            return mTransaction;
+        }
+    }
+
+    private class MockSurfaceBuildingContainer extends WindowContainer<TestWindowContainer> {
+        final SurfaceSession mSession = new SurfaceSession();
+        SurfaceControl mBuiltSurface = null;
+        final SurfaceControl mHostControl = mock(SurfaceControl.class);
+        final SurfaceControl.Transaction mHostTransaction = mock(SurfaceControl.Transaction.class);
+
+        class MockSurfaceBuilder extends SurfaceControl.Builder {
+            MockSurfaceBuilder(SurfaceSession ss) {
+                super(ss);
+            }
+
+            @Override
+            public SurfaceControl build() {
+                SurfaceControl sc = mock(SurfaceControl.class);
+                mBuiltSurface = sc;
+                return sc;
+            }
+        }
+
+        @Override
+        SurfaceControl.Builder makeChildSurface(WindowContainer child) {
+            return new MockSurfaceBuilder(mSession);
+        }
+
+        @Override
+        SurfaceControl getSurfaceControl() {
+            return mHostControl;
+        }
+
+        @Override
+        SurfaceControl.Transaction getPendingTransaction() {
+            return mHostTransaction;
+        }
+    }
+
+    MockSurfaceBuildingContainer mHost;
+    Dimmer mDimmer;
+    SurfaceControl.Transaction mTransaction;
+
+    @Before
+    public void setUp() throws Exception {
+        super.setUp();
+
+        mHost = new MockSurfaceBuildingContainer();
+        mTransaction = mock(SurfaceControl.Transaction.class);
+        mDimmer = new Dimmer(mHost);
+    }
+
+    @Test
+    public void testDimAboveNoChildCreatesSurface() throws Exception {
+        final float alpha = 0.8f;
+        mDimmer.dimAbove(mTransaction, alpha);
+        assertNotNull("Dimmer should have created a surface", mHost.mBuiltSurface);
+
+        verify(mTransaction).setAlpha(mHost.mBuiltSurface, alpha);
+        verify(mTransaction).show(mHost.mBuiltSurface);
+        verify(mTransaction).setLayer(mHost.mBuiltSurface, Integer.MAX_VALUE);
+    }
+
+    @Test
+    public void testDimAboveNoChildRedundantlyUpdatesAlphaOnExistingSurface() throws Exception {
+        float alpha = 0.8f;
+        mDimmer.dimAbove(mTransaction, alpha);
+        final SurfaceControl firstSurface = mHost.mBuiltSurface;
+
+        alpha = 0.9f;
+        mDimmer.dimAbove(mTransaction, alpha);
+
+        assertEquals(firstSurface, mHost.mBuiltSurface);
+        verify(mTransaction).setAlpha(firstSurface, 0.9f);
+    }
+
+    @Test
+    public void testUpdateDimsAppliesSize() throws Exception {
+        mDimmer.dimAbove(mTransaction, 0.8f);
+
+        int width = 100;
+        int height = 300;
+        Rect bounds = new Rect(0, 0, width, height);
+        mDimmer.updateDims(mTransaction, bounds);
+        verify(mTransaction).setSize(mHost.mBuiltSurface, width, height);
+    }
+
+    @Test
+    public void testDimAboveNoChildNotReset() throws Exception {
+        mDimmer.dimAbove(mTransaction, 0.8f);
+        mDimmer.resetDimStates();
+
+        mDimmer.updateDims(mTransaction, new Rect());
+        verify(mHost.mBuiltSurface, never()).destroy();
+    }
+
+    @Test
+    public void testDimAboveWithChildCreatesSurfaceAboveChild() throws Exception {
+        TestWindowContainer child = new TestWindowContainer();
+        mHost.addChild(child, 0);
+
+        final float alpha = 0.8f;
+        mDimmer.dimAbove(mTransaction, child, alpha);
+        assertNotNull("Dimmer should have created a surface", mHost.mBuiltSurface);
+
+        verify(mTransaction).setAlpha(mHost.mBuiltSurface, alpha);
+        verify(mTransaction).show(mHost.mBuiltSurface);
+        verify(mTransaction).setRelativeLayer(mHost.mBuiltSurface, child.mControl, 1);
+    }
+
+    @Test
+    public void testDimBelowWithChildSurfaceCreatesSurfaceBelowChild() throws Exception {
+        TestWindowContainer child = new TestWindowContainer();
+        mHost.addChild(child, 0);
+
+        final float alpha = 0.8f;
+        mDimmer.dimBelow(mTransaction, child, alpha);
+        assertNotNull("Dimmer should have created a surface", mHost.mBuiltSurface);
+
+        verify(mTransaction).setAlpha(mHost.mBuiltSurface, alpha);
+        verify(mTransaction).show(mHost.mBuiltSurface);
+        verify(mTransaction).setRelativeLayer(mHost.mBuiltSurface, child.mControl, -1);
+    }
+
+    @Test
+    public void testDimBelowWithChildSurfaceDestroyedWhenReset() throws Exception {
+        TestWindowContainer child = new TestWindowContainer();
+        mHost.addChild(child, 0);
+
+        final float alpha = 0.8f;
+        mDimmer.dimAbove(mTransaction, child, alpha);
+        mDimmer.resetDimStates();
+        mDimmer.updateDims(mTransaction, new Rect());
+        verify(mHost.mBuiltSurface).destroy();
+    }
+
+    @Test
+    public void testDimBelowWithChildSurfaceNotDestroyedWhenPersisted() throws Exception {
+        TestWindowContainer child = new TestWindowContainer();
+        mHost.addChild(child, 0);
+
+        final float alpha = 0.8f;
+        mDimmer.dimAbove(mTransaction, child, alpha);
+        mDimmer.resetDimStates();
+        mDimmer.dimAbove(mTransaction, child, alpha);
+
+        mDimmer.updateDims(mTransaction, new Rect());
+        verify(mHost.mBuiltSurface, never()).destroy();
+    }
+}
index b846fd0..0ef78f4 100644 (file)
@@ -105,14 +105,10 @@ public class TaskStackTests extends WindowTestsBase {
         final TaskStack stack = createTaskStackOnDisplay(mDisplayContent);
         final Task task = createTaskInStack(stack, 0 /* userId */);
         assertEquals(stack, task.mStack);
-        assertTrue(mDisplayContent.mDimLayerController.hasDimLayerUser(stack));
-        assertTrue(mDisplayContent.mDimLayerController.hasDimLayerUser(task));
 
         // Remove stack and check if its child is also removed.
         stack.removeImmediately();
         assertNull(stack.getDisplayContent());
         assertNull(task.mStack);
-        assertFalse(mDisplayContent.mDimLayerController.hasDimLayerUser(stack));
-        assertFalse(mDisplayContent.mDimLayerController.hasDimLayerUser(task));
     }
 }