From 982c56f6613e5a5058550141296f7a8310dbf960 Mon Sep 17 00:00:00 2001 From: Nick Chameyev Date: Thu, 17 Nov 2022 12:32:42 +0000 Subject: [PATCH] [Unfold animation] Get animation scale from content provider ValueAnimator#areAnimationsEnabled() method does not reflect the latest state of the animation scale at the time when content provider emitted an update. It led to a bug after disabling and enabling animations: we added the unfold overlay in the UnfoldLightRevealOverlayAnimation (as animations enabled) but didn't remove it because the transition progress provider never reported animation start, progress and finish events. Changed to use the content provider to get the latest state of the animation scale. Bug: 256072006 Test: manual fold/unfolds after enabling/disabling talkback Test: com.android.systemui.unfold.util.ScaleAwareUnfoldProgressProviderTest Change-Id: If5d982791b9f8103ecfd8db44e24d2486560d4f5 --- .../UnfoldLightRevealOverlayAnimation.kt | 19 ++++---- .../ScaleAwareUnfoldProgressProviderTest.kt | 45 ++++++++++--------- .../ScaleAwareTransitionProgressProvider.kt | 23 ++++++++-- 3 files changed, 53 insertions(+), 34 deletions(-) diff --git a/packages/SystemUI/src/com/android/systemui/unfold/UnfoldLightRevealOverlayAnimation.kt b/packages/SystemUI/src/com/android/systemui/unfold/UnfoldLightRevealOverlayAnimation.kt index 6ed3a093c8e38..d411e34603d95 100644 --- a/packages/SystemUI/src/com/android/systemui/unfold/UnfoldLightRevealOverlayAnimation.kt +++ b/packages/SystemUI/src/com/android/systemui/unfold/UnfoldLightRevealOverlayAnimation.kt @@ -15,7 +15,7 @@ */ package com.android.systemui.unfold -import android.animation.ValueAnimator +import android.content.ContentResolver import android.content.Context import android.graphics.PixelFormat import android.hardware.devicestate.DeviceStateManager @@ -39,6 +39,7 @@ import com.android.systemui.statusbar.LightRevealScrim import com.android.systemui.statusbar.LinearLightRevealEffect import com.android.systemui.unfold.UnfoldTransitionProgressProvider.TransitionProgressListener import com.android.systemui.unfold.updates.RotationChangeProvider +import com.android.systemui.unfold.util.ScaleAwareTransitionProgressProvider.Companion.areAnimationsEnabled import com.android.systemui.util.traceSection import com.android.wm.shell.displayareahelper.DisplayAreaHelper import java.util.Optional @@ -52,6 +53,7 @@ class UnfoldLightRevealOverlayAnimation constructor( private val context: Context, private val deviceStateManager: DeviceStateManager, + private val contentResolver: ContentResolver, private val displayManager: DisplayManager, private val unfoldTransitionProgressProvider: UnfoldTransitionProgressProvider, private val displayAreaHelper: Optional, @@ -117,7 +119,7 @@ constructor( Trace.beginSection("UnfoldLightRevealOverlayAnimation#onScreenTurningOn") try { // Add the view only if we are unfolding and this is the first screen on - if (!isFolded && !isUnfoldHandled && ValueAnimator.areAnimatorsEnabled()) { + if (!isFolded && !isUnfoldHandled && contentResolver.areAnimationsEnabled()) { addView(onOverlayReady) isUnfoldHandled = true } else { @@ -162,11 +164,10 @@ constructor( // blocker (turn on the brightness) only when the content is actually visible as it // might be presented only in the next frame. // See b/197538198 - transaction - .setFrameTimelineVsync(vsyncId) - .apply() + transaction.setFrameTimelineVsync(vsyncId).apply() - transaction.setFrameTimelineVsync(vsyncId + 1) + transaction + .setFrameTimelineVsync(vsyncId + 1) .addTransactionCommittedListener(backgroundExecutor) { Trace.endAsyncSection("UnfoldLightRevealOverlayAnimation#relayout", 0) callback.run() @@ -218,8 +219,7 @@ constructor( } private fun getUnfoldedDisplayInfo(): DisplayInfo = - displayManager - .displays + displayManager.displays .asSequence() .map { DisplayInfo().apply { it.getDisplayInfo(this) } } .filter { it.type == Display.TYPE_INTERNAL } @@ -266,5 +266,6 @@ constructor( isUnfoldHandled = false } this.isFolded = isFolded - }) + } + ) } diff --git a/packages/SystemUI/tests/src/com/android/systemui/unfold/util/ScaleAwareUnfoldProgressProviderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/unfold/util/ScaleAwareUnfoldProgressProviderTest.kt index fc2a78a5ee7f4..e1e54a9039176 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/unfold/util/ScaleAwareUnfoldProgressProviderTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/unfold/util/ScaleAwareUnfoldProgressProviderTest.kt @@ -15,14 +15,13 @@ */ package com.android.systemui.unfold.util -import android.animation.ValueAnimator import android.content.ContentResolver import android.database.ContentObserver +import android.provider.Settings import android.testing.AndroidTestingRunner import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.unfold.TestUnfoldTransitionProvider -import com.android.systemui.unfold.UnfoldTransitionProgressProvider import com.android.systemui.unfold.UnfoldTransitionProgressProvider.TransitionProgressListener import com.android.systemui.util.mockito.any import org.junit.Before @@ -30,6 +29,7 @@ import org.junit.Test import org.junit.runner.RunWith import org.mockito.ArgumentCaptor import org.mockito.Mock +import org.mockito.Mockito.spy import org.mockito.Mockito.verify import org.mockito.Mockito.verifyNoMoreInteractions import org.mockito.MockitoAnnotations @@ -38,30 +38,25 @@ import org.mockito.MockitoAnnotations @SmallTest class ScaleAwareUnfoldProgressProviderTest : SysuiTestCase() { - @Mock - lateinit var contentResolver: ContentResolver - - @Mock - lateinit var sinkProvider: TransitionProgressListener + @Mock lateinit var sinkProvider: TransitionProgressListener private val sourceProvider = TestUnfoldTransitionProvider() - lateinit var progressProvider: ScaleAwareTransitionProgressProvider + private lateinit var contentResolver: ContentResolver + private lateinit var progressProvider: ScaleAwareTransitionProgressProvider private val animatorDurationScaleListenerCaptor = - ArgumentCaptor.forClass(ContentObserver::class.java) + ArgumentCaptor.forClass(ContentObserver::class.java) @Before fun setUp() { MockitoAnnotations.initMocks(this) + contentResolver = spy(context.contentResolver) - progressProvider = ScaleAwareTransitionProgressProvider( - sourceProvider, - contentResolver - ) + progressProvider = ScaleAwareTransitionProgressProvider(sourceProvider, contentResolver) - verify(contentResolver).registerContentObserver(any(), any(), - animatorDurationScaleListenerCaptor.capture()) + verify(contentResolver) + .registerContentObserver(any(), any(), animatorDurationScaleListenerCaptor.capture()) progressProvider.addCallback(sinkProvider) } @@ -121,12 +116,20 @@ class ScaleAwareUnfoldProgressProviderTest : SysuiTestCase() { } private fun setAnimationsEnabled(enabled: Boolean) { - val durationScale = if (enabled) { - 1f - } else { - 0f - } - ValueAnimator.setDurationScale(durationScale) + val durationScale = + if (enabled) { + 1f + } else { + 0f + } + + // It uses [TestableSettingsProvider] and it will be cleared after the test + Settings.Global.putString( + contentResolver, + Settings.Global.ANIMATOR_DURATION_SCALE, + durationScale.toString() + ) + animatorDurationScaleListenerCaptor.value.dispatchChange(/* selfChange= */false) } } diff --git a/packages/SystemUI/unfold/src/com/android/systemui/unfold/util/ScaleAwareTransitionProgressProvider.kt b/packages/SystemUI/unfold/src/com/android/systemui/unfold/util/ScaleAwareTransitionProgressProvider.kt index 5c92b34998354..06ca153b694b1 100644 --- a/packages/SystemUI/unfold/src/com/android/systemui/unfold/util/ScaleAwareTransitionProgressProvider.kt +++ b/packages/SystemUI/unfold/src/com/android/systemui/unfold/util/ScaleAwareTransitionProgressProvider.kt @@ -14,7 +14,6 @@ */ package com.android.systemui.unfold.util -import android.animation.ValueAnimator import android.content.ContentResolver import android.database.ContentObserver import android.provider.Settings @@ -46,13 +45,15 @@ constructor( contentResolver.registerContentObserver( Settings.Global.getUriFor(Settings.Global.ANIMATOR_DURATION_SCALE), /* notifyForDescendants= */ false, - animatorDurationScaleObserver) + animatorDurationScaleObserver + ) onAnimatorScaleChanged() } private fun onAnimatorScaleChanged() { - val animationsEnabled = ValueAnimator.areAnimatorsEnabled() - scopedUnfoldTransitionProgressProvider.setReadyToHandleTransition(animationsEnabled) + scopedUnfoldTransitionProgressProvider.setReadyToHandleTransition( + contentResolver.areAnimationsEnabled() + ) } override fun addCallback(listener: TransitionProgressListener) { @@ -74,4 +75,18 @@ constructor( progressProvider: UnfoldTransitionProgressProvider ): ScaleAwareTransitionProgressProvider } + + companion object { + fun ContentResolver.areAnimationsEnabled(): Boolean { + val animationScale = + Settings.Global.getStringForUser( + this, + Settings.Global.ANIMATOR_DURATION_SCALE, + this.userId + ) + ?.toFloatOrNull() + ?: 1f + return animationScale != 0f + } + } }