summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Nick Chameyev <nickchameyev@google.com> 2022-12-06 17:47:27 +0000
committer Nick Chameyev <nickchameyev@google.com> 2022-12-16 15:31:29 +0000
commit8874ab952f8fc29b18bd202064413a977d080172 (patch)
treeb26ecf7e6254681fb3a026351a5758e88347e326
parentc514109b3bc4794ea12a94bedf08edf3d5b27a48 (diff)
[Unfold transition] Update latency tracker to listen for animation start
We are going to introduce potential delay before starting the animation, so updating the latency tracker to track the end of the unfold display switch only when the animation is started. Bug: 258214245 Test: atest com.android.systemui.unfold.UnfoldLatencyTrackerTest Test: manual unfold with/without animations => check that metric is reported Change-Id: If3017719631f115579f16493136cce0d0e5e2f80
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/LifecycleScreenStatusProvider.kt15
-rw-r--r--packages/SystemUI/src/com/android/systemui/unfold/UnfoldLatencyTracker.kt84
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/unfold/UnfoldLatencyTrackerTest.kt93
-rw-r--r--packages/SystemUI/unfold/src/com/android/systemui/unfold/progress/PhysicsBasedUnfoldTransitionProgressProvider.kt4
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) {