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

Commit 652b1c70 authored by Jordan Demeulenaere's avatar Jordan Demeulenaere Committed by Android Build Coastguard Worker
Browse files

Post ActivityLaunchAnimator timeout on Looper.mainLooper()

This CL fixes weird shade state bugs that can happen during Activity
launches animated by the ActivityLaunchAnimator.

Before this CL, if a WindowManager timeout happened (i.e. WM never
starts or cancels the remote animation) *and* that the launchContainer
(the ViewRootImpl where the launch started) was detached, then the
timeout would never be triggered, leaving our UI in an invalid state.
This bug is currently easily reproducible using the steps from
b/300056100#comment4, where we incorrectly animate an activity launch
from a dialog then instantly dismiss that dialog.

This CL fixes this bug by posting the timeout on Looper.getMainLooper()
instead of using launchContainer.postDelayed(). That way, the timeout is
always called after 1s if WM didn't start or cancel the remote
animation.

I suspect that this is somehow what is also happening with b/288507023,
but I was not able to confirm this theory yet.

Bug: b/300056100
Bug: b/288507023
Test: Manual, made sure that b/300056100#comment4 is not reproducible
 with this CL. Unfortunately ActivityLaunchAnimator is in a separate
 library so it can't use our DelayableExecutor (that is testable), so
 I don't think there is a good way to write a unit test for this.
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:df830e17f80b4d1e1f9d2334aa164baa31c49f85)
Merged-In: Iaa019d6d0aabdf97af0cb6995ad81270f275f3e7
Change-Id: Iaa019d6d0aabdf97af0cb6995ad81270f275f3e7
parent 5927619e
Loading
Loading
Loading
Loading
+28 −6
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@ import android.graphics.Path
import android.graphics.Rect
import android.graphics.RectF
import android.os.Build
import android.os.Handler
import android.os.Looper
import android.os.RemoteException
import android.util.Log
@@ -58,7 +59,14 @@ class ActivityLaunchAnimator(
    /** The animator used when animating a Dialog into an app. */
    // TODO(b/218989950): Remove this animator and instead set the duration of the dim fade out to
    // TIMINGS.contentBeforeFadeOutDuration.
    private val dialogToAppAnimator: LaunchAnimator = DEFAULT_DIALOG_TO_APP_ANIMATOR
    private val dialogToAppAnimator: LaunchAnimator = DEFAULT_DIALOG_TO_APP_ANIMATOR,

    /**
     * Whether we should disable the WindowManager timeout. This should be set to true in tests
     * only.
     */
    // TODO(b/301385865): Remove this flag.
    private val disableWmTimeout: Boolean = false,
) {
    companion object {
        /** The timings when animating a View into an app. */
@@ -431,7 +439,8 @@ class ActivityLaunchAnimator(
        internal val delegate: AnimationDelegate

        init {
            delegate = AnimationDelegate(controller, callback, listener, launchAnimator)
            delegate =
                AnimationDelegate(controller, callback, listener, launchAnimator, disableWmTimeout)
        }

        @BinderThread
@@ -461,13 +470,26 @@ class ActivityLaunchAnimator(
        /** Listener for animation lifecycle events. */
        private val listener: Listener? = null,
        /** The animator to use to animate the window launch. */
        private val launchAnimator: LaunchAnimator = DEFAULT_LAUNCH_ANIMATOR
        private val launchAnimator: LaunchAnimator = DEFAULT_LAUNCH_ANIMATOR,

        /**
         * Whether we should disable the WindowManager timeout. This should be set to true in tests
         * only.
         */
        // TODO(b/301385865): Remove this flag.
        disableWmTimeout: Boolean = false,
    ) : RemoteAnimationDelegate<IRemoteAnimationFinishedCallback> {
        private val launchContainer = controller.launchContainer
        private val context = launchContainer.context
        private val transactionApplierView =
            controller.openingWindowSyncView ?: controller.launchContainer
        private val transactionApplier = SyncRtSurfaceTransactionApplier(transactionApplierView)
        private val timeoutHandler =
            if (!disableWmTimeout) {
                Handler(Looper.getMainLooper())
            } else {
                null
            }

        private val matrix = Matrix()
        private val invertMatrix = Matrix()
@@ -487,11 +509,11 @@ class ActivityLaunchAnimator(

        @UiThread
        internal fun postTimeout() {
            launchContainer.postDelayed(onTimeout, LAUNCH_TIMEOUT)
            timeoutHandler?.postDelayed(onTimeout, LAUNCH_TIMEOUT)
        }

        private fun removeTimeout() {
            launchContainer.removeCallbacks(onTimeout)
            timeoutHandler?.removeCallbacks(onTimeout)
        }

        @UiThread
+2 −1
Original line number Diff line number Diff line
@@ -57,7 +57,8 @@ class ActivityLaunchAnimatorTest : SysuiTestCase() {

    @Before
    fun setup() {
        activityLaunchAnimator = ActivityLaunchAnimator(testLaunchAnimator, testLaunchAnimator)
        activityLaunchAnimator =
            ActivityLaunchAnimator(testLaunchAnimator, testLaunchAnimator, disableWmTimeout = true)
        activityLaunchAnimator.callback = callback
        activityLaunchAnimator.addListener(listener)
    }