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

Commit 73164dc7 authored by Craig Mautner's avatar Craig Mautner Committed by Android (Google) Code Review
Browse files

Merge "Combine DimAnimator and DimSurface into DimLayer"

parents 58106813 1420b93f
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