Loading packages/SystemUI/aconfig/systemui.aconfig +10 −0 Original line number Diff line number Diff line Loading @@ -1974,3 +1974,13 @@ flag { purpose: PURPOSE_BUGFIX } } flag { name: "animation_library_delay_leash_cleanup" namespace: "systemui" description: "Clean up the transition leash with a delay to ensure that the finish callback happens first, avoiding flickers" bug: "356065603" metadata { purpose: PURPOSE_BUGFIX } } packages/SystemUI/animation/src/com/android/systemui/animation/ActivityTransitionAnimator.kt +33 −13 Original line number Diff line number Diff line Loading @@ -62,6 +62,7 @@ import com.android.app.animation.Interpolators import com.android.internal.annotations.VisibleForTesting import com.android.internal.policy.ScreenDecorationsUtils import com.android.systemui.Flags.activityTransitionUseLargestWindow import com.android.systemui.Flags.animationLibraryDelayLeashCleanup import com.android.systemui.Flags.moveTransitionAnimationLayer import com.android.systemui.Flags.translucentOccludingActivityFix import com.android.systemui.animation.TransitionAnimator.Companion.assertLongLivedReturnAnimations Loading Loading @@ -1596,20 +1597,39 @@ constructor( iCallback?.invoke() if (reparent) { val cleanUpTransitionLeash: () -> Unit = { // Relying on this try-catch is not great, but the existence of // RemoteAnimationRunnerCompat means that we can't reliably assume that // the transaction will be executed while the leash is still valid. // TODO(b/397180418): remove once the RemoteAnimation wrapper is cleaned // up. // RemoteAnimationRunnerCompat means that we can't reliably // assume that the transaction will be executed while the leash // is still valid. // TODO(b/397180418): remove once the RemoteAnimation wrapper is // cleaned up. try { // Reparent to null to avoid leaking the transition leash. // TODO(b/397180418): shouldn't be needed anymore once the // RemoteAnimation wrapper is cleaned up. SurfaceControl.Transaction().use { it.reparent(window.leash, null).apply() it.reparent(window.leash, null) it.apply(/* sync */ false) } } catch (e: IllegalStateException) { Log.e(TAG, "Failed to clean up transition leash: already released") Log.e( TAG, "Failed to clean up transition leash: already released", ) } } if (animationLibraryDelayLeashCleanup()) { // This cleanup is not time-sensitive as it is just to avoid leaking // leashes. By delaying it, we make (reasonably) sure that the // finish callback above is executed before the reparent // transaction, which avoids flaky flickers. Unfortunately both are // async, so we need to resort to this hacky solution. Fortunately // none of this will be necessary as soon as b/397180418 is done. Handler(Looper.getMainLooper()) .postDelayed(cleanUpTransitionLeash, 500L) } else { cleanUpTransitionLeash() } } Loading Loading
packages/SystemUI/aconfig/systemui.aconfig +10 −0 Original line number Diff line number Diff line Loading @@ -1974,3 +1974,13 @@ flag { purpose: PURPOSE_BUGFIX } } flag { name: "animation_library_delay_leash_cleanup" namespace: "systemui" description: "Clean up the transition leash with a delay to ensure that the finish callback happens first, avoiding flickers" bug: "356065603" metadata { purpose: PURPOSE_BUGFIX } }
packages/SystemUI/animation/src/com/android/systemui/animation/ActivityTransitionAnimator.kt +33 −13 Original line number Diff line number Diff line Loading @@ -62,6 +62,7 @@ import com.android.app.animation.Interpolators import com.android.internal.annotations.VisibleForTesting import com.android.internal.policy.ScreenDecorationsUtils import com.android.systemui.Flags.activityTransitionUseLargestWindow import com.android.systemui.Flags.animationLibraryDelayLeashCleanup import com.android.systemui.Flags.moveTransitionAnimationLayer import com.android.systemui.Flags.translucentOccludingActivityFix import com.android.systemui.animation.TransitionAnimator.Companion.assertLongLivedReturnAnimations Loading Loading @@ -1596,20 +1597,39 @@ constructor( iCallback?.invoke() if (reparent) { val cleanUpTransitionLeash: () -> Unit = { // Relying on this try-catch is not great, but the existence of // RemoteAnimationRunnerCompat means that we can't reliably assume that // the transaction will be executed while the leash is still valid. // TODO(b/397180418): remove once the RemoteAnimation wrapper is cleaned // up. // RemoteAnimationRunnerCompat means that we can't reliably // assume that the transaction will be executed while the leash // is still valid. // TODO(b/397180418): remove once the RemoteAnimation wrapper is // cleaned up. try { // Reparent to null to avoid leaking the transition leash. // TODO(b/397180418): shouldn't be needed anymore once the // RemoteAnimation wrapper is cleaned up. SurfaceControl.Transaction().use { it.reparent(window.leash, null).apply() it.reparent(window.leash, null) it.apply(/* sync */ false) } } catch (e: IllegalStateException) { Log.e(TAG, "Failed to clean up transition leash: already released") Log.e( TAG, "Failed to clean up transition leash: already released", ) } } if (animationLibraryDelayLeashCleanup()) { // This cleanup is not time-sensitive as it is just to avoid leaking // leashes. By delaying it, we make (reasonably) sure that the // finish callback above is executed before the reparent // transaction, which avoids flaky flickers. Unfortunately both are // async, so we need to resort to this hacky solution. Fortunately // none of this will be necessary as soon as b/397180418 is done. Handler(Looper.getMainLooper()) .postDelayed(cleanUpTransitionLeash, 500L) } else { cleanUpTransitionLeash() } } Loading