Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1420b93f authored by Craig Mautner's avatar Craig Mautner
Browse files

Combine DimAnimator and DimSurface into DimLayer

Replace two classes that did similar things in a complicated manner
with one class that does it more simply.

Bug 7064755 fixed.

Change-Id: I8c415671f60d1d2ece9da5916421f4d24aed2d65
parent a22f980f
Loading
Loading
Loading
Loading
+0 −248
Original line number Diff line number Diff line
/*
 * Copyright (C) 2011 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.content.res.Resources;
import android.graphics.PixelFormat;
import android.util.Slog;
import android.util.TypedValue;
import android.view.Surface;
import android.view.SurfaceSession;

import java.io.PrintWriter;

/**
 * DimAnimator class that controls the dim animation. This holds the surface and
 * all state used for dim animation.
 */
class DimAnimator {
    static final String TAG = "DimAnimator";

    Surface mDimSurface;
    boolean mDimShown = false;
    float mDimCurrentAlpha;
    float mDimTargetAlpha;
    float mDimDeltaPerMs;
    long mLastDimAnimTime;

    int mLastDimWidth, mLastDimHeight;

    DimAnimator (SurfaceSession session, final int layerStack) {
        try {
            if (WindowManagerService.DEBUG_SURFACE_TRACE) {
                mDimSurface = new WindowStateAnimator.SurfaceTrace(session,
                    "DimAnimator",
                    16, 16, PixelFormat.OPAQUE,
                    Surface.FX_SURFACE_DIM | Surface.HIDDEN);
            } else {
                mDimSurface = new Surface(session, "DimAnimator",
                    16, 16, PixelFormat.OPAQUE,
                    Surface.FX_SURFACE_DIM | Surface.HIDDEN);
            }
            if (WindowManagerService.SHOW_TRANSACTIONS ||
                    WindowManagerService.SHOW_SURFACE_ALLOC) Slog.i(WindowManagerService.TAG,
                            "  DIM " + mDimSurface + ": CREATE");
            mDimSurface.setLayerStack(layerStack);
            mDimSurface.setAlpha(0.0f);
            mDimSurface.show();
        } catch (Exception e) {
            Slog.e(WindowManagerService.TAG, "Exception creating Dim surface", e);
        }
    }

    /**
     * Set's the dim surface's layer and update dim parameters that will be used in
     * {@link #updateSurface} after all windows are examined.
     */
    void updateParameters(final Resources res, final Parameters params, final long currentTime) {
        if (mDimSurface == null) {
            Slog.e(TAG, "updateParameters: no Surface");
            return;
        }

        // Multiply by 1.5 so that rotating a frozen surface that includes this does not expose a
        // corner.
        final int dw = (int) (params.mDimWidth * 1.5);
        final int dh = (int) (params.mDimHeight * 1.5);
        final WindowStateAnimator winAnimator = params.mDimWinAnimator;
        final float target = params.mDimTarget;
        if (!mDimShown) {
            if (WindowManagerService.SHOW_TRANSACTIONS) Slog.i(WindowManagerService.TAG,
                "  DIM " + mDimSurface + ": SHOW pos=(0,0) (" + dw + "x" + dh + ")");
            mDimShown = true;
            try {
                mLastDimWidth = dw;
                mLastDimHeight = dh;
                // back off position so mDimXXX/4 is before and mDimXXX/4 is after
                mDimSurface.setPosition(-1 * dw / 6, -1 * dh /6);
                mDimSurface.setSize(dw, dh);
                mDimSurface.show();
            } catch (RuntimeException e) {
                Slog.w(WindowManagerService.TAG, "Failure showing dim surface", e);
            }
        } else if (mLastDimWidth != dw || mLastDimHeight != dh) {
            mLastDimWidth = dw;
            mLastDimHeight = dh;
            mDimSurface.setSize(dw, dh);
            // back off position so mDimXXX/4 is before and mDimXXX/4 is after
            mDimSurface.setPosition(-1 * dw / 6, -1 * dh /6);
        }

        mDimSurface.setLayer(winAnimator.mAnimLayer - WindowManagerService.LAYER_OFFSET_DIM);

        if (WindowManagerService.SHOW_TRANSACTIONS) Slog.i(WindowManagerService.TAG, "  DIM "
                + mDimSurface + ": layer=" + (winAnimator.mAnimLayer-1) + " target=" + target);
        if (mDimTargetAlpha != target) {
            // If the desired dim level has changed, then
            // start an animation to it.
            mLastDimAnimTime = currentTime;
            long duration = (winAnimator.mAnimating && winAnimator.mAnimation != null)
                    ? winAnimator.mAnimation.computeDurationHint()
                    : WindowManagerService.DEFAULT_DIM_DURATION;
            if (target > mDimTargetAlpha) {
                TypedValue tv = new TypedValue();
                res.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;
                }
            }
            if (duration < 1) {
                // Don't divide by zero
                duration = 1;
            }
            mDimTargetAlpha = target;
            mDimDeltaPerMs = (mDimTargetAlpha-mDimCurrentAlpha) / duration;
        }
    }

    /**
     * Updating the surface's alpha. Returns true if the animation continues, or returns
     * false when the animation is finished and the dim surface is hidden.
     */
    boolean updateSurface(boolean dimming, long currentTime, boolean displayFrozen) {
        if (mDimSurface == null) {
            Slog.e(TAG, "updateSurface: no Surface");
            return false;
        }

        if (!dimming) {
            if (mDimTargetAlpha != 0) {
                mLastDimAnimTime = currentTime;
                mDimTargetAlpha = 0;
                mDimDeltaPerMs = (-mDimCurrentAlpha) / WindowManagerService.DEFAULT_DIM_DURATION;
            }
        }

        boolean animating = mLastDimAnimTime != 0;
        if (animating) {
            mDimCurrentAlpha += mDimDeltaPerMs
                    * (currentTime-mLastDimAnimTime);
            if (displayFrozen) {
                // If the display is frozen, there is no reason to animate.
                animating = false;
            } else if (mDimDeltaPerMs > 0) {
                if (mDimCurrentAlpha > mDimTargetAlpha) {
                    animating = false;
                }
            } else if (mDimDeltaPerMs < 0) {
                if (mDimCurrentAlpha < mDimTargetAlpha) {
                    animating = false;
                }
            } else {
                animating = false;
            }

            // Do we need to continue animating?
            if (animating) {
                if (WindowManagerService.SHOW_TRANSACTIONS) Slog.i(WindowManagerService.TAG, "  DIM "
                        + mDimSurface + ": alpha=" + mDimCurrentAlpha);
                mLastDimAnimTime = currentTime;
                mDimSurface.setAlpha(mDimCurrentAlpha);
            } else {
                mDimCurrentAlpha = mDimTargetAlpha;
                mLastDimAnimTime = 0;
                if (WindowManagerService.SHOW_TRANSACTIONS) Slog.i(WindowManagerService.TAG, "  DIM "
                        + mDimSurface + ": final alpha=" + mDimCurrentAlpha);
                mDimSurface.setAlpha(mDimCurrentAlpha);
                if (!dimming) {
                    if (WindowManagerService.SHOW_TRANSACTIONS) Slog.i(WindowManagerService.TAG, "  DIM " + mDimSurface
                            + ": HIDE");
                    try {
                        mDimSurface.hide();
                    } catch (RuntimeException e) {
                        Slog.w(WindowManagerService.TAG, "Illegal argument exception hiding dim surface");
                    }
                    mDimShown = false;
                }
            }
        }
        return animating;
    }

    public void kill() {
        if (mDimSurface != null) {
            mDimSurface.destroy();
            mDimSurface = null;
        }
    }

    public void printTo(String prefix, PrintWriter pw) {
        pw.print(prefix);
        pw.print("mDimSurface="); pw.print(mDimSurface);
                pw.print(" "); pw.print(mLastDimWidth); pw.print(" x ");
                pw.println(mLastDimHeight);
        pw.print(prefix);
        pw.print("mDimShown="); pw.print(mDimShown);
        pw.print(" current="); pw.print(mDimCurrentAlpha);
        pw.print(" target="); pw.print(mDimTargetAlpha);
        pw.print(" delta="); pw.print(mDimDeltaPerMs);
        pw.print(" lastAnimTime="); pw.println(mLastDimAnimTime);
    }

    static class Parameters {
        final WindowStateAnimator mDimWinAnimator;
        final int mDimWidth;
        final int mDimHeight;
        final float mDimTarget;
        Parameters(final WindowStateAnimator dimWinAnimator, final int dimWidth,
                final int dimHeight, final float dimTarget) {
            mDimWinAnimator = dimWinAnimator;
            mDimWidth = dimWidth;
            mDimHeight = dimHeight;
            mDimTarget = dimTarget;
        }

        Parameters(Parameters o) {
            mDimWinAnimator = o.mDimWinAnimator;
            mDimWidth = o.mDimWidth;
            mDimHeight = o.mDimHeight;
            mDimTarget = o.mDimTarget;
        }

        public void printTo(String prefix, PrintWriter pw) {
            pw.print(prefix);
            pw.print("mDimWinAnimator="); pw.print(mDimWinAnimator.mWin.mAttrs.getTitle());
                    pw.print(" "); pw.print(mDimWidth); pw.print(" x ");
                    pw.print(mDimHeight);
            pw.print(" mDimTarget="); pw.println(mDimTarget);
        }
    }
}
+257 −0
Original line number Diff line number Diff line
// Copyright 2012 Google Inc. All Rights Reserved.

package com.android.server.wm;

import android.graphics.PixelFormat;
import android.os.SystemClock;
import android.util.Slog;
import android.view.DisplayInfo;
import android.view.Surface;

import java.io.PrintWriter;

public class DimLayer {
    private static final String TAG = "DimLayer";
    private static final boolean DEBUG = true;

    /** Reference to the owner of this object. */
    final DisplayContent mDisplayContent;

    /** Actual surface that dims */
    Surface mDimSurface;

    /** Last value passed to mDimSurface.setAlpha() */
    float mAlpha = 0;

    /** Last value passed to mDimSurface.setLayer() */
    int mLayer = -1;

    /** Last values passed to mDimSurface.setSize() */
    int mLastDimWidth, mLastDimHeight;

    /** True after mDimSurface.show() has been called, false after mDimSurface.hide(). */
    private boolean mShowing = false;

    /** Value of mAlpha when beginning transition to mTargetAlpha */
    float mStartAlpha = 0;

    /** Final value of mAlpha following transition */
    float mTargetAlpha = 0;

    /** Time in units of SystemClock.uptimeMillis() at which the current transition started */
    long mStartTime;

    /** Time in milliseconds to take to transition from mStartAlpha to mTargetAlpha */
    long mDuration;

    DimLayer(WindowManagerService service, int displayId) {
        if (DEBUG) Slog.v(TAG, "Ctor: displayId=" + displayId);
        mDisplayContent = service.getDisplayContentLocked(displayId);
        Surface.openTransaction();
        try {
            if (WindowManagerService.DEBUG_SURFACE_TRACE) {
                mDimSurface = new WindowStateAnimator.SurfaceTrace(service.mFxSession,
                    "DimSurface",
                    16, 16, PixelFormat.OPAQUE,
                    Surface.FX_SURFACE_DIM | Surface.HIDDEN);
            } else {
                mDimSurface = new Surface(service.mFxSession, TAG,
                    16, 16, PixelFormat.OPAQUE,
                    Surface.FX_SURFACE_DIM | Surface.HIDDEN);
            }
            if (WindowManagerService.SHOW_TRANSACTIONS ||
                    WindowManagerService.SHOW_SURFACE_ALLOC) Slog.i(TAG,
                            "  DIM " + mDimSurface + ": CREATE");
            mDimSurface.setLayerStack(displayId);
        } catch (Exception e) {
            Slog.e(WindowManagerService.TAG, "Exception creating Dim surface", e);
        } finally {
            Surface.closeTransaction();
        }
    }

    /** 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;
    }

    private void setAlpha(float alpha) {
        if (mAlpha != alpha) {
            if (DEBUG) Slog.v(TAG, "setAlpha alpha=" + alpha);
            try {
                mDimSurface.setAlpha(alpha);
                if (alpha == 0 && mShowing) {
                    if (DEBUG) Slog.v(TAG, "setAlpha hiding");
                    mDimSurface.hide();
                    mShowing = false;
                } else if (alpha > 0 && !mShowing) {
                    if (DEBUG) Slog.v(TAG, "setAlpha showing");
                    mDimSurface.show();
                    mShowing = true;
                }
            } catch (RuntimeException e) {
                Slog.w(TAG, "Failure setting alpha immediately", e);
            }
            mAlpha = alpha;
        }
    }

    /**
     * @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) 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) Slog.v(TAG, "show: layer=" + layer + " alpha=" + alpha
                + " duration=" + duration);
        if (mDimSurface == null) {
            Slog.e(TAG, "show: no Surface");
            // Make sure isAnimating() returns false.
            mTargetAlpha = mAlpha = 0;
            return;
        }

        // Set surface size to screen size.
        final DisplayInfo info = mDisplayContent.getDisplayInfo();
        // Multiply by 1.5 so that rotating a frozen surface that includes this does not expose a
        // corner.
        final int dw = (int) (info.logicalWidth * 1.5);
        final int dh = (int) (info.logicalHeight * 1.5);
        // back off position so 1/4 of Surface is before and 1/4 is after.
        final float xPos = -1 * dw / 6;
        final float yPos = -1 * dh / 6;

        if (mLastDimWidth != dw || mLastDimHeight != dh || mLayer != layer) {
            try {
                mDimSurface.setPosition(xPos, yPos);
                mDimSurface.setSize(dw, dh);
                mDimSurface.setLayer(layer);
            } catch (RuntimeException e) {
                Slog.w(TAG, "Failure setting size or layer", e);
            }
            mLastDimWidth = dw;
            mLastDimHeight = dh;
            mLayer = 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;
            }
        }
        if (DEBUG) Slog.v(TAG, "show: mStartAlpha=" + mStartAlpha + " mStartTime=" + mStartTime);
        mTargetAlpha = alpha;
    }

    /** Immediate hide.
     * NOTE: Must be called with Surface transaction open. */
    void hide() {
        if (mShowing) {
            if (DEBUG) 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) 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 (mDimSurface == null) {
            Slog.e(TAG, "stepAnimation: null Surface");
            // 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) Slog.v(TAG, "stepAnimation: curTime=" + curTime + " alpha=" + alpha);
            setAlpha(alpha);
        }

        return isAnimating();
    }

    /** Cleanup */
    void destroySurface() {
        if (DEBUG) Slog.v(TAG, "destroySurface.");
        if (mDimSurface != null) {
            mDimSurface.destroy();
            mDimSurface = null;
        }
    }

    public void printTo(String prefix, PrintWriter pw) {
        pw.print(prefix); pw.print("mDimSurface="); pw.println(mDimSurface);
        pw.print(prefix); pw.print(" mLayer="); pw.print(mLayer);
                pw.print(" mAlpha="); pw.println(mAlpha);
        pw.print(prefix); pw.print("mLastDimWidth="); pw.print(mLastDimWidth);
                pw.print(" mLastDimWidth="); pw.println(mLastDimWidth);
        pw.print(prefix); pw.print("Last animation: mStartTime="); pw.print(mStartTime);
                pw.print(" mDuration="); pw.print(mDuration);
                pw.print(" curTime="); pw.println(SystemClock.uptimeMillis());
        pw.print(" mStartAlpha="); pw.println(mStartAlpha);
                pw.print(" mTargetAlpha="); pw.print(mTargetAlpha);
    }
}
+0 −134
Original line number Diff line number Diff line
/*
 * Copyright (C) 2011 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.graphics.PixelFormat;
import android.util.Slog;
import android.view.DisplayInfo;
import android.view.Surface;
import android.view.SurfaceSession;

import java.io.PrintWriter;

class DimSurface {
    static final String TAG = "DimSurface";

    Surface mDimSurface;
    boolean mDimShown = false;
    int mDimColor = 0;
    int mLayer = -1;
    int mLastDimWidth, mLastDimHeight;
    final DisplayContent mDisplayContent;

    DimSurface(SurfaceSession session, DisplayContent displayContent) {
        mDisplayContent = displayContent;
        final int layerStack = displayContent.getDisplayId();
        try {
            if (WindowManagerService.DEBUG_SURFACE_TRACE) {
                mDimSurface = new WindowStateAnimator.SurfaceTrace(session,
                    "DimSurface",
                    16, 16, PixelFormat.OPAQUE,
                    Surface.FX_SURFACE_DIM | Surface.HIDDEN);
            } else {
                mDimSurface = new Surface(session, "DimSurface",
                    16, 16, PixelFormat.OPAQUE,
                    Surface.FX_SURFACE_DIM | Surface.HIDDEN);
            }
            if (WindowManagerService.SHOW_TRANSACTIONS ||
                    WindowManagerService.SHOW_SURFACE_ALLOC) Slog.i(WindowManagerService.TAG,
                            "  DIM " + mDimSurface + ": CREATE");
            mDimSurface.setLayerStack(layerStack);
            mDimSurface.setAlpha(0.0f);
            mDimSurface.show();
        } catch (Exception e) {
            Slog.e(WindowManagerService.TAG, "Exception creating Dim surface", e);
        }
    }

    /**
     * Show the dim surface.
     */
    void show(int layer, int color) {
        final DisplayInfo info = mDisplayContent.getDisplayInfo();
        final int dw = info.logicalWidth;
        final int dh = info.logicalHeight;
        if (mDimSurface == null) {
            Slog.e(TAG, "show: no Surface");
            return;
        }

        if (!mDimShown) {
            if (WindowManagerService.SHOW_TRANSACTIONS) Slog.i(WindowManagerService.TAG, "  DIM " + mDimSurface + ": SHOW pos=(0,0) (" +
                    dw + "x" + dh + " layer=" + layer + ")");
            mDimShown = true;
            try {
                mLastDimWidth = dw;
                mLastDimHeight = dh;
                mDimSurface.setPosition(0, 0);
                mDimSurface.setSize(dw, dh);
                mDimSurface.setLayer(layer);
                mDimSurface.show();
            } catch (RuntimeException e) {
                Slog.w(WindowManagerService.TAG, "Failure showing dim surface", e);
            }
        } else if (mLastDimWidth != dw || mLastDimHeight != dh || mDimColor != color
                || mLayer != layer) {
            if (WindowManagerService.SHOW_TRANSACTIONS) Slog.i(WindowManagerService.TAG, "  DIM " + mDimSurface + ": pos=(0,0) (" +
                    dw + "x" + dh + " layer=" + layer + ")");
            mLastDimWidth = dw;
            mLastDimHeight = dh;
            mLayer = layer;
            mDimColor = color;
            mDimSurface.setSize(dw, dh);
            mDimSurface.setLayer(layer);
            mDimSurface.setAlpha(((color>>24)&0xff)/255.0f);
        }
    }

    void hide() {
        if (mDimSurface == null) {
            Slog.e(TAG, "hide: no Surface");
            return;
        }

        if (mDimShown) {
            mDimShown = false;
            try {
                if (WindowManagerService.SHOW_TRANSACTIONS) Slog.i(WindowManagerService.TAG, "  HIDE " + mDimSurface);
                mDimSurface.hide();
            } catch (RuntimeException e) {
                Slog.w(WindowManagerService.TAG, "Illegal argument exception hiding dim surface");
            }
        }
    }

    void kill() {
        if (mDimSurface != null) {
            mDimSurface.destroy();
            mDimSurface = null;
        }
    }

    public void printTo(String prefix, PrintWriter pw) {
        pw.print(prefix); pw.print("mDimSurface="); pw.println(mDimSurface);
        pw.print(prefix); pw.print("mDimShown="); pw.print(mDimShown);
                pw.print(" mLayer="); pw.print(mLayer);
                pw.print(" mDimColor=0x"); pw.println(Integer.toHexString(mDimColor));
        pw.print(prefix); pw.print("mLastDimWidth="); pw.print(mLastDimWidth);
                pw.print(" mLastDimWidth="); pw.println(mLastDimWidth);
    }
}
+80 −56

File changed.

Preview size limit exceeded, changes collapsed.

+4 −21

File changed.

Preview size limit exceeded, changes collapsed.

Loading