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

Commit 7d830825 authored by Jordan Demeulenaere's avatar Jordan Demeulenaere
Browse files

Animate the media activity launch.

This CL animates the activity launched when clicking the media player in
the shade. See b/174236650#comment3 for before/after videos.

Bug: 174236650
Test: Tap the media player when the shade is open and unlocked.
Change-Id: I147d627f07023e0d06d25a7ebec42d14cbbc314a
parent a867af2d
Loading
Loading
Loading
Loading
+44 −5
Original line number Diff line number Diff line
@@ -28,6 +28,7 @@ import android.graphics.ColorFilter
import android.graphics.Outline
import android.graphics.Paint
import android.graphics.PixelFormat
import android.graphics.Xfermode
import android.graphics.drawable.Drawable
import android.util.AttributeSet
import android.util.MathUtils
@@ -48,7 +49,15 @@ private const val BACKGROUND_ANIM_DURATION = 370L
class IlluminationDrawable : Drawable() {

    private var themeAttrs: IntArray? = null
    private var cornerRadius = 0f
    private var cornerRadiusOverride = -1f
    var cornerRadius = 0f
    get() {
        return if (cornerRadiusOverride >= 0) {
            cornerRadiusOverride
        } else {
            field
        }
    }
    private var highlightColor = Color.TRANSPARENT
    private var tmpHsl = floatArrayOf(0f, 0f, 0f)
    private var paint = Paint()
@@ -122,8 +131,28 @@ class IlluminationDrawable : Drawable() {
        throw UnsupportedOperationException("Color filters are not supported")
    }

    override fun setAlpha(value: Int) {
        throw UnsupportedOperationException("Alpha is not supported")
    override fun setAlpha(alpha: Int) {
        if (alpha == paint.alpha) {
            return
        }

        paint.alpha = alpha
        invalidateSelf()

        lightSources.forEach { it.alpha = alpha }
    }

    override fun getAlpha(): Int {
        return paint.alpha
    }

    override fun setXfermode(mode: Xfermode?) {
        if (mode == paint.xfermode) {
            return
        }

        paint.xfermode = mode
        invalidateSelf()
    }

    /**
@@ -171,9 +200,19 @@ class IlluminationDrawable : Drawable() {

    fun registerLightSource(lightSource: View) {
        if (lightSource.background is LightSourceDrawable) {
            lightSources.add(lightSource.background as LightSourceDrawable)
            registerLightSource(lightSource.background as LightSourceDrawable)
        } else if (lightSource.foreground is LightSourceDrawable) {
            lightSources.add(lightSource.foreground as LightSourceDrawable)
            registerLightSource(lightSource.foreground as LightSourceDrawable)
        }
    }

    private fun registerLightSource(lightSource: LightSourceDrawable) {
        lightSource.alpha = paint.alpha
        lightSources.add(lightSource)
    }

    /** Set or remove the corner radius override. This is typically set during animations. */
    fun setCornerRadiusOverride(cornerRadius: Float?) {
        cornerRadiusOverride = cornerRadius ?: -1f
    }
}
 No newline at end of file
+7 −2
Original line number Diff line number Diff line
@@ -184,8 +184,13 @@ class LightSourceDrawable : Drawable() {
        throw UnsupportedOperationException("Color filters are not supported")
    }

    override fun setAlpha(value: Int) {
        throw UnsupportedOperationException("Alpha is not supported")
    override fun setAlpha(alpha: Int) {
        if (alpha == paint.alpha) {
            return
        }

        paint.alpha = alpha
        invalidateSelf()
    }

    /**
+50 −6
Original line number Diff line number Diff line
@@ -49,6 +49,8 @@ import com.android.systemui.R;
import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.media.dialog.MediaOutputDialogFactory;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.animation.ActivityLaunchAnimator;
import com.android.systemui.plugins.animation.GhostedViewLaunchAnimatorController;
import com.android.systemui.statusbar.phone.KeyguardDismissUtil;
import com.android.systemui.util.animation.TransitionLayout;

@@ -101,9 +103,10 @@ public class MediaControlPanel {
    // This will provide the corners for the album art.
    private final ViewOutlineProvider mViewOutlineProvider;
    private final MediaOutputDialogFactory mMediaOutputDialogFactory;

    /**
     * Initialize a new control panel
     * @param context
     *
     * @param backgroundExecutor background executor, used for processing artwork
     * @param activityStarter    activity starter
     */
@@ -147,6 +150,7 @@ public class MediaControlPanel {

    /**
     * Get the view holder used to display media controls
     *
     * @return the view holder
     */
    @Nullable
@@ -156,6 +160,7 @@ public class MediaControlPanel {

    /**
     * Get the view controller used to display media controls
     *
     * @return the media view controller
     */
    @NonNull
@@ -165,7 +170,7 @@ public class MediaControlPanel {

    /**
     * Sets the listening state of the player.
     *
     * <p>
     * Should be set to true when the QS panel is open. Otherwise, false. This is a signal to avoid
     * unnecessary work when the QS panel is closed.
     *
@@ -177,6 +182,7 @@ public class MediaControlPanel {

    /**
     * Get the context
     *
     * @return context
     */
    public Context getContext() {
@@ -244,7 +250,8 @@ public class MediaControlPanel {
        if (clickIntent != null) {
            mViewHolder.getPlayer().setOnClickListener(v -> {
                if (mMediaViewController.isGutsVisible()) return;
                mActivityStarter.postStartActivityDismissingKeyguard(clickIntent);
                mActivityStarter.postStartActivityDismissingKeyguard(clickIntent,
                        buildLaunchAnimatorController(mViewHolder.getPlayer()));
            });
        }

@@ -396,8 +403,42 @@ public class MediaControlPanel {
        mMediaViewController.refreshState();
    }

    @Nullable
    private ActivityLaunchAnimator.Controller buildLaunchAnimatorController(
            TransitionLayout player) {
        // TODO(b/174236650): Make sure that the carousel indicator also fades out.
        // TODO(b/174236650): Instrument the animation to measure jank.
        return new GhostedViewLaunchAnimatorController(player) {
            @Override
            protected float getCurrentTopCornerRadius() {
                return ((IlluminationDrawable) player.getBackground()).getCornerRadius();
            }

            @Override
            protected float getCurrentBottomCornerRadius() {
                // TODO(b/184121838): Make IlluminationDrawable support top and bottom radius.
                return getCurrentTopCornerRadius();
            }

            @Override
            protected void setBackgroundCornerRadius(Drawable background, float topCornerRadius,
                    float bottomCornerRadius) {
                // TODO(b/184121838): Make IlluminationDrawable support top and bottom radius.
                float radius = Math.min(topCornerRadius, bottomCornerRadius);
                ((IlluminationDrawable) background).setCornerRadiusOverride(radius);
            }

            @Override
            public void onLaunchAnimationEnd(boolean isExpandingFullyAbove) {
                super.onLaunchAnimationEnd(isExpandingFullyAbove);
                ((IlluminationDrawable) player.getBackground()).setCornerRadiusOverride(null);
            }
        };
    }

    /**
     * Close the guts for this player.
     *
     * @param immediate {@code true} if it should be closed without animation
     */
    public void closeGuts(boolean immediate) {
@@ -435,6 +476,7 @@ public class MediaControlPanel {

    /**
     * Get the current media controller
     *
     * @return the controller
     */
    public MediaController getController() {
@@ -443,6 +485,7 @@ public class MediaControlPanel {

    /**
     * Check whether the media controlled by this player is currently playing
     *
     * @return whether it is playing, or false if no controller information
     */
    public boolean isPlaying() {
@@ -451,6 +494,7 @@ public class MediaControlPanel {

    /**
     * Check whether the given controller is currently playing
     *
     * @param controller media controller to check
     * @return whether it is playing, or false if no controller information
     */