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

Commit 93755573 authored by Marzia Favaro's avatar Marzia Favaro
Browse files

Remove flag introduce_smoother_dimmer

SmoothDimmer is now the default Dimmer. We now only have Dimmer class.

Test: DimmerTests
Bug: 352522056
Flag: EXEMPT flag removal
Change-Id: Ic3c84cab861421d09e0a528d9213d165e81b2b68
parent 83afa9a9
Loading
Loading
Loading
Loading
+0 −8
Original line number Diff line number Diff line
@@ -79,14 +79,6 @@ flag {
  bug: "291870756"
}

flag {
  name: "introduce_smoother_dimmer"
  namespace: "windowing_frontend"
  description: "Refactor dim to fix flickers"
  bug: "295291019"
  is_fixed_read_only: true
}

flag {
  name: "transit_ready_tracking"
  namespace: "windowing_frontend"
+213 −48
Original line number Diff line number Diff line
@@ -16,56 +16,170 @@

package com.android.server.wm;

import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_DIMMER;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;

import android.annotation.NonNull;
import android.graphics.Rect;
import android.util.Log;
import android.view.Surface;
import android.view.SurfaceControl;

import com.android.internal.annotations.VisibleForTesting;
import com.android.window.flags.Flags;
import com.android.internal.protolog.ProtoLog;

class Dimmer {

    /**
 * 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.
     * The {@link WindowContainer} that our Dims are bounded to. We may be dimming on behalf of the
     * host, some controller of it, or one of the hosts children.
     */
public abstract class Dimmer {
    private final WindowContainer<?> mHost;

    static final boolean DIMMER_REFACTOR = Flags.introduceSmootherDimmer();
    private static final String TAG = TAG_WITH_CLASS_NAME ? "Dimmer" : TAG_WM;
    DimState mDimState;
    final DimmerAnimationHelper.AnimationAdapterFactory mAnimationAdapterFactory;

    /**
     * The {@link WindowContainer} that our Dims are bounded to. We may be dimming on behalf of the
     * host, some controller of it, or one of the hosts children.
     * Controls the dim behaviour
     */
    protected final WindowContainer mHost;
    protected class DimState {
        /** Related objects */
        SurfaceControl mDimSurface;
        final WindowContainer<?> mHostContainer;
        // The last container to request to dim
        private WindowContainer<?> mLastRequestedDimContainer;
        /** Animation */
        private final DimmerAnimationHelper mAnimationHelper;
        boolean mSkipAnimation = false;
        // Determines whether the dim layer should animate before destroying.
        boolean mAnimateExit = true;
        /** Surface visibility and bounds */
        private boolean mIsVisible = false;
        // TODO(b/64816140): Remove after confirming dimmer layer always matches its container.
        final Rect mDimBounds = new Rect();

    protected Dimmer(WindowContainer host) {
        mHost = host;
        DimState() {
            mHostContainer = mHost;
            mAnimationHelper = new DimmerAnimationHelper(mAnimationAdapterFactory);
            try {
                mDimSurface = makeDimLayer();
            } catch (Surface.OutOfResourcesException e) {
                Log.w(TAG, "OutOfResourcesException creating dim surface");
            }
        }

    // Constructs the correct type of dimmer
    static Dimmer create(WindowContainer host) {
        return DIMMER_REFACTOR ? new SmoothDimmer(host) : new LegacyDimmer(host);
        void ensureVisible(@NonNull SurfaceControl.Transaction t) {
            if (!mIsVisible) {
                t.show(mDimSurface);
                t.setAlpha(mDimSurface, 0f);
                mIsVisible = true;
            }
        }

    @NonNull
    WindowContainer<?> getHost() {
        return mHost;
        void adjustSurfaceLayout(@NonNull SurfaceControl.Transaction t) {
            // TODO: Once we use geometry from hierarchy this falls away.
            t.setPosition(mDimSurface, mDimBounds.left, mDimBounds.top);
            t.setWindowCrop(mDimSurface, mDimBounds.width(), mDimBounds.height());
        }

        /**
     * Position the dim relatively to the dimming container.
     * Normally called together with #setAppearance, it can be called alone to keep the dim parented
     * to a visible container until the next dimming container is ready.
     * If multiple containers call this method, only the changes relative to the topmost will be
     * applied.
         * Set the parameters to prepare the dim to change its appearance
         */
        void prepareLookChange(float alpha, int blurRadius) {
            mAnimationHelper.setRequestedAppearance(alpha, blurRadius);
        }

        /**
         * Prepare the dim for the exit animation
         */
        void exit(@NonNull SurfaceControl.Transaction t) {
            if (!mAnimateExit) {
                remove(t);
            } else {
                mAnimationHelper.setExitParameters();
                setReady(t);
            }
        }

        void remove(@NonNull SurfaceControl.Transaction t) {
            mAnimationHelper.stopCurrentAnimation(mDimSurface);
            if (mDimSurface.isValid()) {
                t.remove(mDimSurface);
                ProtoLog.d(WM_DEBUG_DIMMER,
                        "Removing dim surface %s on transaction %s", this, t);
            } else {
                Log.w(TAG, "Tried to remove " + mDimSurface + " multiple times\n");
            }
        }

        @Override
        public String toString() {
            return "Dimmer#DimState with host=" + mHostContainer + ", surface=" + mDimSurface;
        }

        /**
         * Set the parameters to prepare the dim to be relative parented to the dimming container
         */
        void prepareReparent(@NonNull WindowContainer<?> relativeParent, int relativeLayer) {
            mAnimationHelper.setRequestedRelativeParent(relativeParent, relativeLayer);
        }

        /**
         * Call when all the changes have been requested to have them applied
         * @param t The transaction in which to apply the changes
         */
        void setReady(@NonNull SurfaceControl.Transaction t) {
            mAnimationHelper.applyChanges(t, this);
        }

        /**
         * Whether anyone is currently requesting the dim
         */
        boolean isDimming() {
            return mLastRequestedDimContainer != null;
        }

        private SurfaceControl makeDimLayer() {
            return mHost.makeChildSurface(null)
                    .setParent(mHost.getSurfaceControl())
                    .setColorLayer()
                    .setName("Dim Layer for - " + mHost.getName())
                    .setCallsite("DimLayer.makeDimLayer")
                    .build();
        }
    }

    protected Dimmer(@NonNull WindowContainer<?> host) {
        this(host, new DimmerAnimationHelper.AnimationAdapterFactory());
    }

    @VisibleForTesting
    Dimmer(@NonNull WindowContainer host,
                 @NonNull DimmerAnimationHelper.AnimationAdapterFactory animationFactory) {
        mHost = host;
        mAnimationAdapterFactory = animationFactory;
    }

    public boolean hostIsTask() {
        return mHost.asTask() != null;
    }

    /**
     * Mark all dims as pending completion on the next call to {@link #updateDims}
     *
     * For each call to {@link WindowContainer#prepareSurfaces()} the DimState will be reset, and
     * the child of the host should call adjustRelativeLayer and {@link Dimmer#adjustAppearance} to
     * continue dimming. Indeed, this method won't be able to keep dimming or get a new DimState
     * without also adjusting the appearance.
     * @param container      The container which to dim above. Should be a child of the host.
     * @param relativeLayer  The position of the dim wrt the container
     * Called before iterating on mHost's children, first step of dimming.
     * 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 its children to give them
     * a chance to request dims to continue.
     */
    protected abstract void adjustRelativeLayer(WindowContainer container, int relativeLayer);
    void resetDimStates() {
        if (mDimState != null) {
            mDimState.mLastRequestedDimContainer = null;
        }
    }

    /**
     * Set the aspect of the dim layer, and request to keep dimming.
@@ -73,31 +187,36 @@ public abstract class Dimmer {
     * child should call setAppearance again to request the Dim to continue.
     * If multiple containers call this method, only the changes relative to the topmost will be
     * applied.
     * @param container  Container requesting the dim
     * @param dimmingContainer  Container requesting the dim
     * @param alpha      Dim amount
     * @param blurRadius Blur amount
     */
    protected abstract void adjustAppearance(
            WindowContainer container, float alpha, int blurRadius);
    protected void adjustAppearance(@NonNull WindowContainer<?> dimmingContainer,
                                    float alpha, int blurRadius) {
        final DimState d = obtainDimState(dimmingContainer);
        d.prepareLookChange(alpha, blurRadius);
    }

    /**
     * Mark all dims as pending completion on the next call to {@link #updateDims}
     * Position the dim relatively to the dimming container.
     * Normally called together with #setAppearance, it can be called alone to keep the dim parented
     * to a visible container until the next dimming container is ready.
     * If multiple containers call this method, only the changes relative to the topmost will be
     * applied.
     *
     * Called before iterating on mHost's children, first step of dimming.
     * 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.
     * For each call to {@link WindowContainer#prepareSurfaces()} the DimState will be reset, and
     * the child of the host should call adjustRelativeLayer and {@link Dimmer#adjustAppearance} to
     * continue dimming. Indeed, this method won't be able to keep dimming or get a new DimState
     * without also adjusting the appearance.
     * @param dimmingContainer      The container which to dim above. Should be a child of the host.
     * @param relativeLayer  The position of the dim wrt the container
     */
    abstract void resetDimStates();

    /** Returns non-null bounds if the dimmer is showing. */
    abstract Rect getDimBounds();

    abstract void dontAnimateExit();

    @VisibleForTesting
    abstract SurfaceControl getDimLayer();
    public void adjustRelativeLayer(@NonNull WindowContainer<?> dimmingContainer,
                                    int relativeLayer) {
        if (mDimState != null) {
            mDimState.prepareReparent(dimmingContainer, relativeLayer);
        }
    }

    /**
     * Call after invoking {@link WindowContainer#prepareSurfaces} on children as
@@ -106,5 +225,51 @@ public abstract class Dimmer {
     * @param t      A transaction in which to update the dims.
     * @return true if any Dims were updated.
     */
    abstract boolean updateDims(SurfaceControl.Transaction t);
    boolean updateDims(@NonNull SurfaceControl.Transaction t) {
        if (mDimState == null) {
            return false;
        }
        if (!mDimState.isDimming()) {
            // No one is dimming, fade out and remove the dim
            mDimState.exit(t);
            mDimState = null;
            return false;
        } else {
            // Someone is dimming, show the requested changes
            mDimState.adjustSurfaceLayout(t);
            final WindowState ws = mDimState.mLastRequestedDimContainer.asWindowState();
            if (!mDimState.mIsVisible && ws != null && ws.mActivityRecord != null
                    && ws.mActivityRecord.mStartingData != null) {
                // Skip enter animation while starting window is on top of its activity
                mDimState.mSkipAnimation = true;
            }
            mDimState.setReady(t);
            return true;
        }
    }

    @NonNull
    private DimState obtainDimState(@NonNull WindowContainer<?> container) {
        if (mDimState == null) {
            mDimState = new DimState();
        }
        mDimState.mLastRequestedDimContainer = container;
        return mDimState;
    }

    /** Returns non-null bounds if the dimmer is showing. */
    @VisibleForTesting
    SurfaceControl getDimLayer() {
        return mDimState != null ? mDimState.mDimSurface : null;
    }

    Rect getDimBounds() {
        return mDimState != null ? mDimState.mDimBounds : null;
    }

    void dontAnimateExit() {
        if (mDimState != null) {
            mDimState.mAnimateExit = false;
        }
    }
}
+18 −14
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@ import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_DIMMER;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;

import android.annotation.NonNull;
import android.util.Log;
import android.util.proto.ProtoOutputStream;
import android.view.SurfaceControl;
@@ -46,13 +47,13 @@ public class DimmerAnimationHelper {
    static class Change {
        private float mAlpha = -1f;
        private int mBlurRadius = -1;
        private WindowContainer mDimmingContainer = null;
        private WindowContainer<?> mDimmingContainer = null;
        private int mRelativeLayer = -1;
        private static final float EPSILON = 0.0001f;

        Change() {}

        Change(Change other) {
        Change(@NonNull Change other) {
            mAlpha = other.mAlpha;
            mBlurRadius = other.mBlurRadius;
            mDimmingContainer = other.mDimmingContainer;
@@ -60,15 +61,15 @@ public class DimmerAnimationHelper {
        }

        // Same alpha and blur
        boolean hasSameVisualProperties(Change other) {
        boolean hasSameVisualProperties(@NonNull Change other) {
            return Math.abs(mAlpha - other.mAlpha) < EPSILON && mBlurRadius == other.mBlurRadius;
        }

        boolean hasSameDimmingContainer(Change other) {
        boolean hasSameDimmingContainer(@NonNull Change other) {
            return mDimmingContainer != null && mDimmingContainer == other.mDimmingContainer;
        }

        void inheritPropertiesFromAnimation(AnimationSpec anim) {
        void inheritPropertiesFromAnimation(@NonNull AnimationSpec anim) {
            mAlpha = anim.mCurrentAlpha;
            mBlurRadius = anim.mCurrentBlur;
        }
@@ -97,7 +98,7 @@ public class DimmerAnimationHelper {
    }

    // Sets a requested change without applying it immediately
    void setRequestedRelativeParent(WindowContainer relativeParent, int relativeLayer) {
    void setRequestedRelativeParent(@NonNull WindowContainer<?> relativeParent, int relativeLayer) {
        mRequestedProperties.mDimmingContainer = relativeParent;
        mRequestedProperties.mRelativeLayer = relativeLayer;
    }
@@ -114,7 +115,7 @@ public class DimmerAnimationHelper {
     * {@link Change#setRequestedRelativeParent(WindowContainer, int)}, or
     * {@link Change#setRequestedAppearance(float, int)}
     */
    void applyChanges(SurfaceControl.Transaction t, SmoothDimmer.DimState dim) {
    void applyChanges(@NonNull SurfaceControl.Transaction t, @NonNull Dimmer.DimState dim) {
        if (mRequestedProperties.mDimmingContainer == null) {
            Log.e(TAG, this + " does not have a dimming container. Have you forgotten to "
                    + "call adjustRelativeLayer?");
@@ -160,7 +161,7 @@ public class DimmerAnimationHelper {
    }

    private void startAnimation(
            SurfaceControl.Transaction t, SmoothDimmer.DimState dim) {
            @NonNull SurfaceControl.Transaction t, @NonNull Dimmer.DimState dim) {
        ProtoLog.v(WM_DEBUG_DIMMER, "Starting animation on %s", dim);
        mAlphaAnimationSpec = getRequestedAnimationSpec();
        mLocalAnimationAdapter = mAnimationAdapterFactory.get(mAlphaAnimationSpec,
@@ -186,7 +187,7 @@ public class DimmerAnimationHelper {
        return mAlphaAnimationSpec != null;
    }

    void stopCurrentAnimation(SurfaceControl surface) {
    void stopCurrentAnimation(@NonNull SurfaceControl surface) {
        if (mLocalAnimationAdapter != null && isAnimating()) {
            // Save the current animation progress and cancel the animation
            mCurrentProperties.inheritPropertiesFromAnimation(mAlphaAnimationSpec);
@@ -196,6 +197,7 @@ public class DimmerAnimationHelper {
        }
    }

    @NonNull
    private AnimationSpec getRequestedAnimationSpec() {
        final float startAlpha = Math.max(mCurrentProperties.mAlpha, 0f);
        final int startBlur = Math.max(mCurrentProperties.mBlurRadius, 0);
@@ -214,8 +216,8 @@ public class DimmerAnimationHelper {
    /**
     * Change the relative parent of this dim layer
     */
    void relativeReparent(SurfaceControl dimLayer, SurfaceControl relativeParent,
                          int relativePosition, SurfaceControl.Transaction t) {
    void relativeReparent(@NonNull SurfaceControl dimLayer, @NonNull SurfaceControl relativeParent,
                          int relativePosition, @NonNull SurfaceControl.Transaction t) {
        try {
            t.setRelativeLayer(dimLayer, relativeParent, relativePosition);
        } catch (NullPointerException e) {
@@ -223,7 +225,8 @@ public class DimmerAnimationHelper {
        }
    }

    void setAlphaBlur(SurfaceControl sc, float alpha, int blur, SurfaceControl.Transaction t) {
    void setAlphaBlur(@NonNull SurfaceControl sc, float alpha, int blur,
                      @NonNull SurfaceControl.Transaction t) {
        try {
            t.setAlpha(sc, alpha);
            t.setBackgroundBlurRadius(sc, blur);
@@ -232,7 +235,7 @@ public class DimmerAnimationHelper {
        }
    }

    private long getDimDuration(WindowContainer container) {
    private long getDimDuration(@NonNull WindowContainer<?> container) {
        // Use the same duration as the animation on the WindowContainer
        AnimationAdapter animationAdapter = container.mSurfaceAnimator.getAnimation();
        final float durationScale = container.mWmService.getTransitionAnimationScaleLocked();
@@ -282,7 +285,8 @@ public class DimmerAnimationHelper {
        }

        @Override
        public void apply(SurfaceControl.Transaction t, SurfaceControl sc, long currentPlayTime) {
        public void apply(@NonNull SurfaceControl.Transaction t, @NonNull SurfaceControl sc,
                          long currentPlayTime) {
            if (!mStarted) {
                // The first frame would end up in the sync transaction, and since this could be
                // applied after the animation transaction, we avoid putting visible changes here.
+1 −1
Original line number Diff line number Diff line
@@ -817,7 +817,7 @@ public class DisplayArea<T extends WindowContainer> extends WindowContainer<T> {
     * DisplayArea that can be dimmed.
     */
    static class Dimmable extends DisplayArea<DisplayArea> {
        private final Dimmer mDimmer = Dimmer.create(this);
        private final Dimmer mDimmer = new Dimmer(this);

        Dimmable(WindowManagerService wms, Type type, String name, int featureId) {
            super(wms, type, name, featureId);
+0 −348

File deleted.

Preview size limit exceeded, changes collapsed.

Loading