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

Commit 8dab740d authored by Jordan Demeulenaere's avatar Jordan Demeulenaere Committed by Android (Google) Code Review
Browse files

Merge "Register the remote animation before starting an intent." into sc-dev

parents 35a18790 4e8dfa69
Loading
Loading
Loading
Loading
+39 −5
Original line number Diff line number Diff line
@@ -4,12 +4,14 @@ import android.animation.Animator
import android.animation.AnimatorListenerAdapter
import android.animation.ValueAnimator
import android.app.ActivityManager
import android.app.ActivityTaskManager
import android.app.PendingIntent
import android.content.Context
import android.graphics.Matrix
import android.graphics.Rect
import android.os.Looper
import android.os.RemoteException
import android.util.Log
import android.util.MathUtils
import android.view.IRemoteAnimationFinishedCallback
import android.view.IRemoteAnimationRunner
@@ -30,6 +32,8 @@ import kotlin.math.roundToInt
 * nicely into the starting window.
 */
class ActivityLaunchAnimator(context: Context) {
    private val TAG = this::class.java.simpleName

    companion object {
        const val ANIMATION_DURATION = 500L
        const val ANIMATION_DURATION_FADE_OUT_CONTENT = 183L
@@ -78,29 +82,49 @@ class ActivityLaunchAnimator(context: Context) {
     * If [controller] is null or [animate] is false, then the intent will be started and no
     * animation will run.
     *
     * If possible, you should pass the [packageName] of the intent that will be started so that
     * trampoline activity launches will also be animated.
     *
     * This method will throw any exception thrown by [intentStarter].
     */
    @JvmOverloads
    inline fun startIntentWithAnimation(
    fun startIntentWithAnimation(
        controller: Controller?,
        animate: Boolean = true,
        packageName: String? = null,
        intentStarter: (RemoteAnimationAdapter?) -> Int
    ) {
        if (controller == null || !animate) {
            Log.d(TAG, "Starting intent with no animation")
            intentStarter(null)
            controller?.callOnIntentStartedOnMainThread(willAnimate = false)
            return
        }

        Log.d(TAG, "Starting intent with a launch animation")
        val runner = Runner(controller)
        val animationAdapter = RemoteAnimationAdapter(
            runner,
            ANIMATION_DURATION,
            ANIMATION_DURATION - 150 /* statusBarTransitionDelay */
        )

        // Register the remote animation for the given package to also animate trampoline
        // activity launches.
        if (packageName != null) {
            try {
                ActivityTaskManager.getService().registerRemoteAnimationForNextActivityStart(
                    packageName, animationAdapter)
            } catch (e: RemoteException) {
                Log.w(TAG, "Unable to register the remote animation", e)
            }
        }

        val launchResult = intentStarter(animationAdapter)
        val willAnimate = launchResult == ActivityManager.START_TASK_TO_FRONT ||
            launchResult == ActivityManager.START_SUCCESS

        Log.d(TAG, "launchResult=$launchResult willAnimate=$willAnimate")
        controller.callOnIntentStartedOnMainThread(willAnimate)

        // If we expect an animation, post a timeout to cancel it in case the remote animation is
@@ -110,7 +134,6 @@ class ActivityLaunchAnimator(context: Context) {
        }
    }

    @PublishedApi
    internal fun Controller.callOnIntentStartedOnMainThread(willAnimate: Boolean) {
        if (Looper.myLooper() != Looper.getMainLooper()) {
            this.launchContainer.context.mainExecutor.execute {
@@ -125,15 +148,21 @@ class ActivityLaunchAnimator(context: Context) {
     * Same as [startIntentWithAnimation] but allows [intentStarter] to throw a
     * [PendingIntent.CanceledException] which must then be handled by the caller. This is useful
     * for Java caller starting a [PendingIntent].
     *
     * If possible, you should pass the [packageName] of the intent that will be started so that
     * trampoline activity launches will also be animated.
     */
    @Throws(PendingIntent.CanceledException::class)
    @JvmOverloads
    fun startPendingIntentWithAnimation(
        controller: Controller?,
        animate: Boolean = true,
        packageName: String? = null,
        intentStarter: PendingIntentStarter
    ) {
        startIntentWithAnimation(controller, animate) { intentStarter.startPendingIntent(it) }
        startIntentWithAnimation(controller, animate, packageName) {
            intentStarter.startPendingIntent(it)
        }
    }

    /** Create a new animation [Runner] controlled by [controller]. */
@@ -278,7 +307,7 @@ class ActivityLaunchAnimator(context: Context) {
    @VisibleForTesting
    inner class Runner(private val controller: Controller) : IRemoteAnimationRunner.Stub() {
        private val launchContainer = controller.launchContainer
        @PublishedApi internal val context = launchContainer.context
        private val context = launchContainer.context
        private val transactionApplier = SyncRtSurfaceTransactionApplier(launchContainer)
        private var animator: ValueAnimator? = null

@@ -294,7 +323,6 @@ class ActivityLaunchAnimator(context: Context) {
        // posting it.
        private var onTimeout = Runnable { onAnimationTimedOut() }

        @PublishedApi
        internal fun postTimeout() {
            launchContainer.postDelayed(onTimeout, LAUNCH_TIMEOUT)
        }
@@ -336,11 +364,13 @@ class ActivityLaunchAnimator(context: Context) {
            remoteAnimationNonAppTargets: Array<out RemoteAnimationTarget>,
            iCallback: IRemoteAnimationFinishedCallback
        ) {
            Log.d(TAG, "Remote animation started")
            val window = remoteAnimationTargets.firstOrNull {
                it.mode == RemoteAnimationTarget.MODE_OPENING
            }

            if (window == null) {
                Log.d(TAG, "Aborting the animation as no window is opening")
                removeTimeout()
                invokeCallback(iCallback)
                controller.onLaunchAnimationCancelled()
@@ -399,10 +429,12 @@ class ActivityLaunchAnimator(context: Context) {

            animator.addListener(object : AnimatorListenerAdapter() {
                override fun onAnimationStart(animation: Animator?, isReverse: Boolean) {
                    Log.d(TAG, "Animation started")
                    controller.onLaunchAnimationStart(isExpandingFullyAbove)
                }

                override fun onAnimationEnd(animation: Animator?) {
                    Log.d(TAG, "Animation ended")
                    invokeCallback(iCallback)
                    controller.onLaunchAnimationEnd(isExpandingFullyAbove)
                }
@@ -496,6 +528,7 @@ class ActivityLaunchAnimator(context: Context) {
                return
            }

            Log.d(TAG, "Remote animation timed out")
            timedOut = true
            controller.onLaunchAnimationCancelled()
        }
@@ -505,6 +538,7 @@ class ActivityLaunchAnimator(context: Context) {
                return
            }

            Log.d(TAG, "Remote animation was cancelled")
            cancelled = true
            removeTimeout()
            context.mainExecutor.execute {
+2 −2
Original line number Diff line number Diff line
@@ -2801,7 +2801,7 @@ public class StatusBar extends SystemUI implements DemoMode,
            int[] result = new int[]{ActivityManager.START_CANCELED};

            mActivityLaunchAnimator.startIntentWithAnimation(animController,
                    areLaunchAnimationsEnabled(), (adapter) -> {
                    areLaunchAnimationsEnabled(), intent.getPackage(), (adapter) -> {
                        ActivityOptions options = new ActivityOptions(
                                getActivityOptions(mDisplayId, adapter));
                        options.setDisallowEnterPictureInPictureWhileLaunching(
@@ -4565,7 +4565,7 @@ public class StatusBar extends SystemUI implements DemoMode,
                                animationController, this, intent.isActivity()) : null;

                mActivityLaunchAnimator.startPendingIntentWithAnimation(
                        controller, areLaunchAnimationsEnabled(),
                        controller, areLaunchAnimationsEnabled(), intent.getCreatorPackage(),
                        (animationAdapter) -> intent.sendAndReturnResult(null, 0, null, null, null,
                                null, getActivityOptions(mDisplayId, animationAdapter)));
            } catch (PendingIntent.CanceledException e) {
+3 −2
Original line number Diff line number Diff line
@@ -437,7 +437,7 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit

            mActivityLaunchAnimator.startPendingIntentWithAnimation(animationController,
                    !wasOccluded && mStatusBar.areLaunchAnimationsEnabled(),
                    (adapter) -> {
                    intent.getCreatorPackage(), (adapter) -> {
                        long eventTime = row.getAndResetLastActionUpTime();
                        Bundle options = eventTime > 0
                                ? getActivityOptions(
@@ -469,6 +469,7 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit

                mActivityLaunchAnimator.startIntentWithAnimation(
                        animationController, mStatusBar.areLaunchAnimationsEnabled(),
                        intent.getPackage(),
                        (adapter) -> TaskStackBuilder.create(mContext)
                                .addNextIntentWithParentStack(intent)
                                .startActivities(getActivityOptions(
@@ -499,7 +500,7 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit
                                true /* isActivityIntent */);

                mActivityLaunchAnimator.startIntentWithAnimation(animationController,
                        mStatusBar.areLaunchAnimationsEnabled(),
                        mStatusBar.areLaunchAnimationsEnabled(), intent.getPackage(),
                        (adapter) -> tsb.startActivities(
                                getActivityOptions(mStatusBar.getDisplayId(), adapter),
                                UserHandle.CURRENT));
+5 −1
Original line number Diff line number Diff line
@@ -51,7 +51,11 @@ class ActivityLaunchAnimatorTest : SysuiTestCase() {
        // We start in a new thread so that we can ensure that the callbacks are called in the main
        // thread.
        thread {
            activityLaunchAnimator.startIntentWithAnimation(controller, animate, intentStarter)
            activityLaunchAnimator.startIntentWithAnimation(
                    controller = controller,
                    animate = animate,
                    intentStarter = intentStarter
            )
        }.join()
    }

+1 −1
Original line number Diff line number Diff line
@@ -269,7 +269,7 @@ public class StatusBarNotificationActivityStarterTest extends SysuiTestCase {
        verify(mShadeController, atLeastOnce()).collapsePanel();

        verify(mActivityLaunchAnimator).startPendingIntentWithAnimation(any(),
                eq(false) /* animate */, any());
                eq(false) /* animate */, any(), any());

        verify(mAssistManager).hideAssist();