diff options
author | 2022-12-19 11:20:03 +0000 | |
---|---|---|
committer | 2022-12-19 11:20:03 +0000 | |
commit | 596e3f9025a9fdd048a76b0988954a2eb518b142 (patch) | |
tree | 81337dde0e2cf2d3c5fda60a36a69e3acfd278a0 | |
parent | 7908948853f6eba407e2c7ebf0683b79c944af78 (diff) | |
parent | 8874ab952f8fc29b18bd202064413a977d080172 (diff) |
Merge "[Unfold transition] Update latency tracker to listen for animation start" into tm-qpr-dev
4 files changed, 185 insertions, 11 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/LifecycleScreenStatusProvider.kt b/packages/SystemUI/src/com/android/systemui/keyguard/LifecycleScreenStatusProvider.kt index 0b04fb43c2d7..6063ce27ca16 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/LifecycleScreenStatusProvider.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/LifecycleScreenStatusProvider.kt @@ -17,6 +17,7 @@ package com.android.systemui.keyguard import com.android.systemui.unfold.updates.screen.ScreenStatusProvider import com.android.systemui.unfold.updates.screen.ScreenStatusProvider.ScreenListener +import com.android.systemui.util.traceSection import javax.inject.Inject import javax.inject.Singleton @@ -39,14 +40,22 @@ class LifecycleScreenStatusProvider @Inject constructor(screenLifecycle: ScreenL } override fun onScreenTurnedOn() { - listeners.forEach(ScreenListener::onScreenTurnedOn) + traceSection("$TRACE_TAG#onScreenTurnedOn") { + listeners.forEach(ScreenListener::onScreenTurnedOn) + } } override fun onScreenTurningOff() { - listeners.forEach(ScreenListener::onScreenTurningOff) + traceSection("$TRACE_TAG#onScreenTurningOff") { + listeners.forEach(ScreenListener::onScreenTurningOff) + } } override fun onScreenTurningOn() { - listeners.forEach(ScreenListener::onScreenTurningOn) + traceSection("$TRACE_TAG#onScreenTurningOn") { + listeners.forEach(ScreenListener::onScreenTurningOn) + } } } + +private const val TRACE_TAG = "LifecycleScreenStatusProvider"
\ No newline at end of file diff --git a/packages/SystemUI/src/com/android/systemui/unfold/UnfoldLatencyTracker.kt b/packages/SystemUI/src/com/android/systemui/unfold/UnfoldLatencyTracker.kt index 79b42b8daab1..9269df31e37e 100644 --- a/packages/SystemUI/src/com/android/systemui/unfold/UnfoldLatencyTracker.kt +++ b/packages/SystemUI/src/com/android/systemui/unfold/UnfoldLatencyTracker.kt @@ -16,12 +16,18 @@ package com.android.systemui.unfold +import android.content.ContentResolver import android.content.Context import android.hardware.devicestate.DeviceStateManager +import android.util.Log import com.android.internal.util.LatencyTracker import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.UiBackground import com.android.systemui.keyguard.ScreenLifecycle +import com.android.systemui.unfold.UnfoldTransitionProgressProvider.TransitionProgressListener +import com.android.systemui.unfold.util.ScaleAwareTransitionProgressProvider.Companion.areAnimationsEnabled +import com.android.systemui.util.Compile +import java.util.Optional import java.util.concurrent.Executor import javax.inject.Inject @@ -41,17 +47,19 @@ class UnfoldLatencyTracker constructor( private val latencyTracker: LatencyTracker, private val deviceStateManager: DeviceStateManager, + private val transitionProgressProvider: Optional<UnfoldTransitionProgressProvider>, @UiBackground private val uiBgExecutor: Executor, private val context: Context, + private val contentResolver: ContentResolver, private val screenLifecycle: ScreenLifecycle -) : ScreenLifecycle.Observer { +) : ScreenLifecycle.Observer, TransitionProgressListener { private var folded: Boolean? = null + private var isTransitionEnabled: Boolean? = null private val foldStateListener = FoldStateListener(context) private val isFoldable: Boolean get() = - context - .resources + context.resources .getIntArray(com.android.internal.R.array.config_foldedDeviceStates) .isNotEmpty() @@ -62,6 +70,11 @@ constructor( } deviceStateManager.registerCallback(uiBgExecutor, foldStateListener) screenLifecycle.addObserver(this) + if (transitionProgressProvider.isPresent) { + // Might not be present if the device is not a foldable device or unfold transition + // is disabled in the device configuration + transitionProgressProvider.get().addCallback(this) + } } /** @@ -71,16 +84,72 @@ constructor( * end action event only if we previously received a fold state. */ override fun onScreenTurnedOn() { - if (folded == false) { + if (DEBUG) { + Log.d( + TAG, + "onScreenTurnedOn: folded = $folded, isTransitionEnabled = $isTransitionEnabled" + ) + } + + // We use onScreenTurnedOn event to finish tracking only if we are not playing + // the unfold animation (e.g. it could be disabled because of battery saver). + // When animation is enabled finishing of the tracking will be done in onTransitionStarted. + if (folded == false && isTransitionEnabled == false) { latencyTracker.onActionEnd(LatencyTracker.ACTION_SWITCH_DISPLAY_UNFOLD) + + if (DEBUG) { + Log.d(TAG, "onScreenTurnedOn: ending ACTION_SWITCH_DISPLAY_UNFOLD") + } + } + } + + /** + * This callback is used to end the metric when the unfold animation is enabled because it could + * add an additional delay to synchronize with launcher. + */ + override fun onTransitionStarted() { + if (DEBUG) { + Log.d( + TAG, + "onTransitionStarted: folded = $folded, isTransitionEnabled = $isTransitionEnabled" + ) + } + + if (folded == false && isTransitionEnabled == true) { + latencyTracker.onActionEnd(LatencyTracker.ACTION_SWITCH_DISPLAY_UNFOLD) + + if (DEBUG) { + Log.d(TAG, "onTransitionStarted: ending ACTION_SWITCH_DISPLAY_UNFOLD") + } } } private fun onFoldEvent(folded: Boolean) { - if (this.folded != folded) { + val oldFolded = this.folded + + if (oldFolded != folded) { this.folded = folded - if (!folded) { // unfolding started + + if (DEBUG) { + Log.d(TAG, "Received onFoldEvent = $folded") + } + + // Do not start tracking when oldFolded is null, this means that this is the first + // onFoldEvent after booting the device or starting SystemUI and not actual folding or + // unfolding the device. + if (oldFolded != null && !folded) { + // Unfolding started latencyTracker.onActionStart(LatencyTracker.ACTION_SWITCH_DISPLAY_UNFOLD) + isTransitionEnabled = + transitionProgressProvider.isPresent && contentResolver.areAnimationsEnabled() + + if (DEBUG) { + Log.d( + TAG, + "Starting ACTION_SWITCH_DISPLAY_UNFOLD, " + + "isTransitionEnabled = $isTransitionEnabled" + ) + } } } } @@ -88,3 +157,6 @@ constructor( private inner class FoldStateListener(context: Context) : DeviceStateManager.FoldStateListener(context, { onFoldEvent(it) }) } + +private const val TAG = "UnfoldLatencyTracker" +private val DEBUG = Compile.IS_DEBUG && Log.isLoggable(TAG, Log.VERBOSE) diff --git a/packages/SystemUI/tests/src/com/android/systemui/unfold/UnfoldLatencyTrackerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/unfold/UnfoldLatencyTrackerTest.kt index 4e2736c74007..c7dc0ab8f9cf 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/unfold/UnfoldLatencyTrackerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/unfold/UnfoldLatencyTrackerTest.kt @@ -18,6 +18,7 @@ package com.android.systemui.unfold import android.hardware.devicestate.DeviceStateManager import android.hardware.devicestate.DeviceStateManager.FoldStateListener +import android.provider.Settings import android.testing.AndroidTestingRunner import androidx.test.filters.SmallTest import com.android.internal.util.LatencyTracker @@ -32,9 +33,11 @@ import org.junit.runner.RunWith import org.mockito.ArgumentCaptor import org.mockito.Captor import org.mockito.Mock +import org.mockito.Mockito.never import org.mockito.Mockito.verify import org.mockito.Mockito.verifyNoMoreInteractions import org.mockito.MockitoAnnotations +import java.util.Optional @RunWith(AndroidTestingRunner::class) @SmallTest @@ -59,14 +62,18 @@ class UnfoldLatencyTrackerTest : SysuiTestCase() { private lateinit var unfoldLatencyTracker: UnfoldLatencyTracker + private val transitionProgressProvider = TestUnfoldTransitionProvider() + @Before fun setUp() { MockitoAnnotations.initMocks(this) unfoldLatencyTracker = UnfoldLatencyTracker( latencyTracker, deviceStateManager, + Optional.of(transitionProgressProvider), context.mainExecutor, context, + context.contentResolver, screenLifecycle ).apply { init() } deviceStates = FoldableTestUtils.findDeviceStates(context) @@ -76,23 +83,89 @@ class UnfoldLatencyTrackerTest : SysuiTestCase() { } @Test - fun unfold_eventPropagated() { + fun unfold_startedFolded_animationsDisabled_eventPropagatedOnScreenTurnedOnEvent() { + setAnimationsEnabled(false) + sendFoldEvent(folded = true) + sendFoldEvent(folded = false) + + sendScreenTurnedOnEvent() + + verify(latencyTracker).onActionStart(any()) + verify(latencyTracker).onActionEnd(any()) + } + + @Test + fun unfold_startedFolded_animationsEnabledOnScreenTurnedOn_eventNotFinished() { + setAnimationsEnabled(true) + sendFoldEvent(folded = true) + sendFoldEvent(folded = false) + + sendScreenTurnedOnEvent() + + verify(latencyTracker).onActionStart(any()) + verify(latencyTracker, never()).onActionEnd(any()) + } + + @Test + fun unfold_firstFoldEventAnimationsEnabledOnScreenTurnedOnAndTransitionStarted_eventNotPropagated() { + setAnimationsEnabled(true) + sendFoldEvent(folded = false) + + sendScreenTurnedOnEvent() + transitionProgressProvider.onTransitionStarted() + + verifyNoMoreInteractions(latencyTracker) + } + + @Test + fun unfold_secondFoldEventAnimationsEnabledOnScreenTurnedOnAndTransitionStarted_eventPropagated() { + setAnimationsEnabled(true) + sendFoldEvent(folded = true) + sendFoldEvent(folded = false) + + sendScreenTurnedOnEvent() + transitionProgressProvider.onTransitionStarted() + + verify(latencyTracker).onActionStart(any()) + verify(latencyTracker).onActionEnd(any()) + } + + @Test + fun unfold_unfoldFoldUnfoldAnimationsEnabledOnScreenTurnedOnAndTransitionStarted_eventPropagated() { + setAnimationsEnabled(true) + sendFoldEvent(folded = false) + sendFoldEvent(folded = true) sendFoldEvent(folded = false) + sendScreenTurnedOnEvent() + transitionProgressProvider.onTransitionStarted() verify(latencyTracker).onActionStart(any()) verify(latencyTracker).onActionEnd(any()) } @Test - fun fold_eventNotPropagated() { + fun fold_animationsDisabled_screenTurnedOn_eventNotPropagated() { + setAnimationsEnabled(false) sendFoldEvent(folded = true) + sendScreenTurnedOnEvent() // outer display on. verifyNoMoreInteractions(latencyTracker) } @Test + fun fold_animationsEnabled_screenTurnedOn_eventNotPropagated() { + setAnimationsEnabled(true) + sendFoldEvent(folded = true) + + sendScreenTurnedOnEvent() // outer display on. + transitionProgressProvider.onTransitionStarted() + + verifyNoMoreInteractions(latencyTracker) + } + + @Test fun onScreenTurnedOn_stateNeverSet_eventNotPropagated() { sendScreenTurnedOnEvent() @@ -107,4 +180,20 @@ class UnfoldLatencyTrackerTest : SysuiTestCase() { private fun sendScreenTurnedOnEvent() { screenLifecycleCaptor.value.onScreenTurnedOn() } + + private fun setAnimationsEnabled(enabled: Boolean) { + val durationScale = + if (enabled) { + 1f + } else { + 0f + } + + // It uses [TestableSettingsProvider] and it will be cleared after the test + Settings.Global.putString( + context.contentResolver, + Settings.Global.ANIMATOR_DURATION_SCALE, + durationScale.toString() + ) + } }
\ No newline at end of file diff --git a/packages/SystemUI/unfold/src/com/android/systemui/unfold/progress/PhysicsBasedUnfoldTransitionProgressProvider.kt b/packages/SystemUI/unfold/src/com/android/systemui/unfold/progress/PhysicsBasedUnfoldTransitionProgressProvider.kt index ecc029dc1a07..074b1e162fed 100644 --- a/packages/SystemUI/unfold/src/com/android/systemui/unfold/progress/PhysicsBasedUnfoldTransitionProgressProvider.kt +++ b/packages/SystemUI/unfold/src/com/android/systemui/unfold/progress/PhysicsBasedUnfoldTransitionProgressProvider.kt @@ -16,6 +16,7 @@ package com.android.systemui.unfold.progress import android.os.Trace +import android.os.Trace.TRACE_TAG_APP import android.util.Log import androidx.dynamicanimation.animation.DynamicAnimation import androidx.dynamicanimation.animation.FloatPropertyCompat @@ -157,7 +158,10 @@ class PhysicsBasedUnfoldTransitionProgressProvider( } private fun onStartTransition() { + Trace.beginSection( "$TAG#onStartTransition") listeners.forEach { it.onTransitionStarted() } + Trace.endSection() + isTransitionRunning = true if (DEBUG) { |