summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--packages/SystemUI/src/com/android/systemui/dagger/SystemUICoreStartableModule.kt7
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepository.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/power/shared/model/WakeSleepReason.kt6
-rw-r--r--packages/SystemUI/src/com/android/systemui/unfold/DisplaySwitchLatencyLogger.kt55
-rw-r--r--packages/SystemUI/src/com/android/systemui/unfold/DisplaySwitchLatencyTracker.kt248
-rw-r--r--packages/SystemUI/src/com/android/systemui/unfold/UnfoldTraceLogger.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/unfold/UnfoldTransitionModule.kt9
-rw-r--r--packages/SystemUI/src/com/android/systemui/unfold/data/repository/FoldStateRepository.kt (renamed from packages/SystemUI/unfold/src/com/android/systemui/unfold/updates/FoldStateRepository.kt)12
-rw-r--r--packages/SystemUI/src/com/android/systemui/unfold/domain/interactor/UnfoldTransitionInteractor.kt16
-rw-r--r--packages/SystemUI/src/com/android/systemui/util/Utils.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/util/time/MeasureTimeUtil.kt32
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/unfold/DisplaySwitchLatencyTrackerTest.kt324
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/unfold/FoldStateRepositoryTest.kt (renamed from packages/SystemUI/tests/src/com/android/systemui/unfold/updates/FoldStateRepositoryTest.kt)11
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardRepository.kt2
-rw-r--r--packages/SystemUI/unfold/src/com/android/systemui/unfold/UnfoldSharedModule.kt6
16 files changed, 726 insertions, 18 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUICoreStartableModule.kt b/packages/SystemUI/src/com/android/systemui/dagger/SystemUICoreStartableModule.kt
index ac71664e5590..87a736d926b5 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/SystemUICoreStartableModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUICoreStartableModule.kt
@@ -54,6 +54,7 @@ import com.android.systemui.statusbar.phone.StatusBarHeadsUpChangeListener
import com.android.systemui.stylus.StylusUsiPowerStartable
import com.android.systemui.temporarydisplay.chipbar.ChipbarCoordinator
import com.android.systemui.theme.ThemeOverlayController
+import com.android.systemui.unfold.DisplaySwitchLatencyTracker
import com.android.systemui.usb.StorageNotification
import com.android.systemui.util.NotificationChannels
import com.android.systemui.util.StartBinderLoggerModule
@@ -141,6 +142,12 @@ abstract class SystemUICoreStartableModule {
@ClassKey(LatencyTester::class)
abstract fun bindLatencyTester(sysui: LatencyTester): CoreStartable
+ /** Inject into DisplaySwitchLatencyTracker. */
+ @Binds
+ @IntoMap
+ @ClassKey(DisplaySwitchLatencyTracker::class)
+ abstract fun bindDisplaySwitchLatencyTracker(sysui: DisplaySwitchLatencyTracker): CoreStartable
+
/** Inject into NotificationChannels. */
@Binds
@IntoMap
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepository.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepository.kt
index 31ef100abbcb..2f937bcd3414 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepository.kt
@@ -110,7 +110,7 @@ interface KeyguardRepository {
val isKeyguardGoingAway: Flow<Boolean>
/** Is the always-on display available to be used? */
- val isAodAvailable: Flow<Boolean>
+ val isAodAvailable: StateFlow<Boolean>
fun setAodAvailable(value: Boolean)
@@ -338,7 +338,7 @@ constructor(
.distinctUntilChanged()
private val _isAodAvailable = MutableStateFlow(false)
- override val isAodAvailable: Flow<Boolean> = _isAodAvailable.asStateFlow()
+ override val isAodAvailable: StateFlow<Boolean> = _isAodAvailable.asStateFlow()
override fun setAodAvailable(value: Boolean) {
_isAodAvailable.value = value
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt
index 21651ba2cc2b..6eb3b64d4c09 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt
@@ -104,7 +104,7 @@ constructor(
val dozeTimeTick: Flow<Long> = repository.dozeTimeTick
/** Whether Always-on Display mode is available. */
- val isAodAvailable: Flow<Boolean> = repository.isAodAvailable
+ val isAodAvailable: StateFlow<Boolean> = repository.isAodAvailable
/** Doze transition information. */
val dozeTransitionModel: Flow<DozeTransitionModel> = repository.dozeTransitionModel
diff --git a/packages/SystemUI/src/com/android/systemui/power/shared/model/WakeSleepReason.kt b/packages/SystemUI/src/com/android/systemui/power/shared/model/WakeSleepReason.kt
index faf9fbe3239d..7505566898c0 100644
--- a/packages/SystemUI/src/com/android/systemui/power/shared/model/WakeSleepReason.kt
+++ b/packages/SystemUI/src/com/android/systemui/power/shared/model/WakeSleepReason.kt
@@ -51,7 +51,10 @@ enum class WakeSleepReason(
BIOMETRIC(isTouch = false, PowerManager.WAKE_REASON_BIOMETRIC),
/** Something else happened to wake up or sleep the device. */
- OTHER(isTouch = false, PowerManager.WAKE_REASON_UNKNOWN);
+ OTHER(isTouch = false, PowerManager.WAKE_REASON_UNKNOWN),
+
+ /** Device goes to sleep due to folding of a foldable device. */
+ FOLD(isTouch = false, PowerManager.GO_TO_SLEEP_REASON_DEVICE_FOLD);
companion object {
fun fromPowerManagerWakeReason(reason: Int): WakeSleepReason {
@@ -72,6 +75,7 @@ enum class WakeSleepReason(
fun fromPowerManagerSleepReason(reason: Int): WakeSleepReason {
return when (reason) {
PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON -> POWER_BUTTON
+ PowerManager.GO_TO_SLEEP_REASON_DEVICE_FOLD -> FOLD
else -> OTHER
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/unfold/DisplaySwitchLatencyLogger.kt b/packages/SystemUI/src/com/android/systemui/unfold/DisplaySwitchLatencyLogger.kt
new file mode 100644
index 000000000000..76f7609f81c7
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/unfold/DisplaySwitchLatencyLogger.kt
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.unfold
+
+import com.android.systemui.shared.system.SysUiStatsLog
+
+class DisplaySwitchLatencyLogger {
+
+ /**
+ * Based on data present in [displaySwitchLatencyEvent], logs metrics for atom
+ * [DisplaySwitchLatencyTracked]
+ */
+ fun log(displaySwitchLatencyEvent: DisplaySwitchLatencyTracker.DisplaySwitchLatencyEvent) {
+ with(displaySwitchLatencyEvent) {
+ SysUiStatsLog.write(
+ SysUiStatsLog.DISPLAY_SWITCH_LATENCY_TRACKED,
+ latencyMs,
+ fromFoldableDeviceState,
+ fromState,
+ fromFocusedAppUid,
+ fromPipAppUid,
+ fromVisibleAppsUid.toIntArray(),
+ fromDensityDpi,
+ toState,
+ toFoldableDeviceState,
+ toFocusedAppUid,
+ toPipAppUid,
+ toVisibleAppsUid.toIntArray(),
+ toDensityDpi,
+ notificationCount,
+ externalDisplayCount,
+ throttlingLevel,
+ vskinTemperatureC,
+ hallSensorToFirstHingeAngleChangeMs,
+ hallSensorToDeviceStateChangeMs,
+ onScreenTurningOnToOnDrawnMs,
+ onDrawnToOnScreenTurnedOnMs,
+ )
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/unfold/DisplaySwitchLatencyTracker.kt b/packages/SystemUI/src/com/android/systemui/unfold/DisplaySwitchLatencyTracker.kt
new file mode 100644
index 000000000000..92a64a618ba9
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/unfold/DisplaySwitchLatencyTracker.kt
@@ -0,0 +1,248 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.unfold
+
+import android.content.Context
+import android.util.Log
+import com.android.app.tracing.TraceUtils.instantForTrack
+import com.android.app.tracing.TraceUtils.traceAsync
+import com.android.systemui.CoreStartable
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.display.data.repository.DeviceStateRepository
+import com.android.systemui.display.data.repository.DeviceStateRepository.DeviceState
+import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
+import com.android.systemui.power.domain.interactor.PowerInteractor
+import com.android.systemui.power.shared.model.ScreenPowerState
+import com.android.systemui.power.shared.model.WakeSleepReason
+import com.android.systemui.shared.system.SysUiStatsLog
+import com.android.systemui.unfold.dagger.UnfoldSingleThreadBg
+import com.android.systemui.unfold.domain.interactor.UnfoldTransitionInteractor
+import com.android.systemui.util.Compile
+import com.android.systemui.util.Utils.isDeviceFoldable
+import com.android.systemui.util.animation.data.repository.AnimationStatusRepository
+import com.android.systemui.util.kotlin.pairwise
+import com.android.systemui.util.time.SystemClock
+import com.android.systemui.util.time.measureTimeMillis
+import java.util.concurrent.Executor
+import javax.inject.Inject
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.asCoroutineDispatcher
+import kotlinx.coroutines.flow.filter
+import kotlinx.coroutines.flow.first
+import kotlinx.coroutines.flow.flatMapLatest
+import kotlinx.coroutines.flow.flow
+import kotlinx.coroutines.launch
+
+/**
+ * [DisplaySwitchLatencyTracker] tracks latency and related fields for display switch of a foldable
+ * device. This class populates [DisplaySwitchLatencyEvent] while an ongoing display switch event
+ */
+@SysUISingleton
+class DisplaySwitchLatencyTracker
+@Inject
+constructor(
+ private val context: Context,
+ private val deviceStateRepository: DeviceStateRepository,
+ private val powerInteractor: PowerInteractor,
+ private val unfoldTransitionInteractor: UnfoldTransitionInteractor,
+ private val animationStatusRepository: AnimationStatusRepository,
+ private val keyguardInteractor: KeyguardInteractor,
+ @UnfoldSingleThreadBg private val singleThreadBgExecutor: Executor,
+ @Application private val applicationScope: CoroutineScope,
+ private val displaySwitchLatencyLogger: DisplaySwitchLatencyLogger,
+ private val systemClock: SystemClock
+) : CoreStartable {
+
+ private val backgroundDispatcher = singleThreadBgExecutor.asCoroutineDispatcher()
+
+ @OptIn(ExperimentalCoroutinesApi::class)
+ override fun start() {
+ if (!isDeviceFoldable(context)) {
+ return
+ }
+ applicationScope.launch(backgroundDispatcher) {
+ deviceStateRepository.state
+ .pairwise()
+ .filter {
+ // Start tracking only when the foldable device is
+ //folding(UNFOLDED/HALF_FOLDED -> FOLDED) or
+ //unfolding(FOLDED -> HALF_FOLD/UNFOLDED)
+ foldableDeviceState ->
+ foldableDeviceState.previousValue == DeviceState.FOLDED ||
+ foldableDeviceState.newValue == DeviceState.FOLDED
+ }
+ .flatMapLatest { foldableDeviceState ->
+ flow {
+ var displaySwitchLatencyEvent = DisplaySwitchLatencyEvent()
+ val toFoldableDeviceState = foldableDeviceState.newValue.toStatsInt()
+ displaySwitchLatencyEvent =
+ displaySwitchLatencyEvent.withBeforeFields(
+ foldableDeviceState.previousValue.toStatsInt()
+ )
+
+ val displaySwitchTimeMs =
+ measureTimeMillis(systemClock) {
+ traceAsync(TAG, "displaySwitch") {
+ waitForDisplaySwitch(toFoldableDeviceState)
+ }
+ }
+
+ displaySwitchLatencyEvent =
+ displaySwitchLatencyEvent.withAfterFields(
+ toFoldableDeviceState,
+ displaySwitchTimeMs.toInt(),
+ getCurrentState()
+ )
+ emit(displaySwitchLatencyEvent)
+ }
+ }
+ .collect { displaySwitchLatencyLogger.log(it) }
+ }
+ }
+
+ private fun DeviceState.toStatsInt(): Int =
+ when (this) {
+ DeviceState.FOLDED -> FOLDABLE_DEVICE_STATE_CLOSED
+ DeviceState.HALF_FOLDED -> FOLDABLE_DEVICE_STATE_HALF_OPEN
+ DeviceState.UNFOLDED -> FOLDABLE_DEVICE_STATE_OPEN
+ DeviceState.CONCURRENT_DISPLAY -> FOLDABLE_DEVICE_STATE_FLIPPED
+ else -> FOLDABLE_DEVICE_STATE_UNKNOWN
+ }
+
+ private suspend fun waitForDisplaySwitch(toFoldableDeviceState: Int) {
+ val isTransitionEnabled =
+ unfoldTransitionInteractor.isAvailable &&
+ animationStatusRepository.areAnimationsEnabled().first()
+ if (shouldWaitForScreenOn(toFoldableDeviceState, isTransitionEnabled)) {
+ waitForScreenTurnedOn()
+ } else {
+ traceAsync(TAG, "waitForTransitionStart()") {
+ unfoldTransitionInteractor.waitForTransitionStart()
+ }
+ }
+ }
+
+ private fun shouldWaitForScreenOn(
+ toFoldableDeviceState: Int,
+ isTransitionEnabled: Boolean
+ ): Boolean = (toFoldableDeviceState == FOLDABLE_DEVICE_STATE_CLOSED || !isTransitionEnabled)
+
+ private suspend fun waitForScreenTurnedOn() {
+ traceAsync(TAG, "waitForScreenTurnedOn()") {
+ powerInteractor.screenPowerState.filter { it == ScreenPowerState.SCREEN_ON }.first()
+ }
+ }
+
+ private fun getCurrentState(): Int =
+ when {
+ isStateAod() -> SysUiStatsLog.DISPLAY_SWITCH_LATENCY_TRACKED__TO_STATE__AOD
+ else -> SysUiStatsLog.DISPLAY_SWITCH_LATENCY_TRACKED__TO_STATE__UNKNOWN
+ }
+
+ private fun isStateAod(): Boolean {
+ val lastWakefulnessEvent = powerInteractor.detailedWakefulness.value
+ val isAodEnabled = keyguardInteractor.isAodAvailable.value
+
+ return (lastWakefulnessEvent.isAsleep() &&
+ (lastWakefulnessEvent.lastSleepReason == WakeSleepReason.FOLD) &&
+ isAodEnabled)
+ }
+
+ private inline fun log(msg: () -> String) {
+ if (DEBUG) Log.d(TAG, msg())
+ }
+
+ private fun DisplaySwitchLatencyEvent.withBeforeFields(
+ fromFoldableDeviceState: Int
+ ): DisplaySwitchLatencyEvent {
+ log { "fromFoldableDeviceState=$fromFoldableDeviceState" }
+ instantForTrack(TAG, "fromFoldableDeviceState=$fromFoldableDeviceState")
+
+ return copy(fromFoldableDeviceState = fromFoldableDeviceState)
+ }
+
+ private fun DisplaySwitchLatencyEvent.withAfterFields(
+ toFoldableDeviceState: Int,
+ displaySwitchTimeMs: Int,
+ toState: Int
+ ): DisplaySwitchLatencyEvent {
+ log {
+ "toFoldableDeviceState=$toFoldableDeviceState, " +
+ "toState=$toState, " +
+ "latencyMs=$displaySwitchTimeMs"
+ }
+ instantForTrack(TAG, "toFoldableDeviceState=$toFoldableDeviceState, toState=$toState")
+
+ return copy(
+ toFoldableDeviceState = toFoldableDeviceState,
+ latencyMs = displaySwitchTimeMs,
+ toState = toState
+ )
+ }
+
+ /**
+ * Stores values corresponding to all respective [DisplaySwitchLatencyTrackedField] in a single
+ * event of display switch for foldable devices.
+ *
+ * Once the data is captured in this data class and appropriate to log, it is logged through
+ * [DisplaySwitchLatencyLogger]
+ */
+ data class DisplaySwitchLatencyEvent(
+ val latencyMs: Int = VALUE_UNKNOWN,
+ val fromFoldableDeviceState: Int = FOLDABLE_DEVICE_STATE_UNKNOWN,
+ val fromState: Int = SysUiStatsLog.DISPLAY_SWITCH_LATENCY_TRACKED__FROM_STATE__UNKNOWN,
+ val fromFocusedAppUid: Int = VALUE_UNKNOWN,
+ val fromPipAppUid: Int = VALUE_UNKNOWN,
+ val fromVisibleAppsUid: Set<Int> = setOf(),
+ val fromDensityDpi: Int = VALUE_UNKNOWN,
+ val toFoldableDeviceState: Int = FOLDABLE_DEVICE_STATE_UNKNOWN,
+ val toState: Int = SysUiStatsLog.DISPLAY_SWITCH_LATENCY_TRACKED__FROM_STATE__UNKNOWN,
+ val toFocusedAppUid: Int = VALUE_UNKNOWN,
+ val toPipAppUid: Int = VALUE_UNKNOWN,
+ val toVisibleAppsUid: Set<Int> = setOf(),
+ val toDensityDpi: Int = VALUE_UNKNOWN,
+ val notificationCount: Int = VALUE_UNKNOWN,
+ val externalDisplayCount: Int = VALUE_UNKNOWN,
+ val throttlingLevel: Int =
+ SysUiStatsLog.DISPLAY_SWITCH_LATENCY_TRACKED__THROTTLING_LEVEL__NONE,
+ val vskinTemperatureC: Int = VALUE_UNKNOWN,
+ val hallSensorToFirstHingeAngleChangeMs: Int = VALUE_UNKNOWN,
+ val hallSensorToDeviceStateChangeMs: Int = VALUE_UNKNOWN,
+ val onScreenTurningOnToOnDrawnMs: Int = VALUE_UNKNOWN,
+ val onDrawnToOnScreenTurnedOnMs: Int = VALUE_UNKNOWN
+ )
+
+ companion object {
+ private const val VALUE_UNKNOWN = -1
+ private const val TAG = "DisplaySwitchLatency"
+ private val DEBUG = Compile.IS_DEBUG && Log.isLoggable(TAG, Log.VERBOSE)
+
+ private const val FOLDABLE_DEVICE_STATE_UNKNOWN =
+ SysUiStatsLog.DISPLAY_SWITCH_LATENCY_TRACKED__FROM_FOLDABLE_DEVICE_STATE__STATE_UNKNOWN
+ const val FOLDABLE_DEVICE_STATE_CLOSED =
+ SysUiStatsLog.DISPLAY_SWITCH_LATENCY_TRACKED__FROM_FOLDABLE_DEVICE_STATE__STATE_CLOSED
+ const val FOLDABLE_DEVICE_STATE_HALF_OPEN =
+ SysUiStatsLog
+ .DISPLAY_SWITCH_LATENCY_TRACKED__FROM_FOLDABLE_DEVICE_STATE__STATE_HALF_OPENED
+ private const val FOLDABLE_DEVICE_STATE_OPEN =
+ SysUiStatsLog.DISPLAY_SWITCH_LATENCY_TRACKED__FROM_FOLDABLE_DEVICE_STATE__STATE_OPENED
+ private const val FOLDABLE_DEVICE_STATE_FLIPPED =
+ SysUiStatsLog.DISPLAY_SWITCH_LATENCY_TRACKED__FROM_FOLDABLE_DEVICE_STATE__STATE_FLIPPED
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/unfold/UnfoldTraceLogger.kt b/packages/SystemUI/src/com/android/systemui/unfold/UnfoldTraceLogger.kt
index 94912bf82377..adf50a1e661b 100644
--- a/packages/SystemUI/src/com/android/systemui/unfold/UnfoldTraceLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/unfold/UnfoldTraceLogger.kt
@@ -22,8 +22,8 @@ import com.android.systemui.CoreStartable
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.dagger.qualifiers.Background
+import com.android.systemui.unfold.data.repository.FoldStateRepository
import com.android.systemui.unfold.system.DeviceStateRepository
-import com.android.systemui.unfold.updates.FoldStateRepository
import javax.inject.Inject
import kotlin.coroutines.CoroutineContext
import kotlinx.coroutines.CoroutineScope
diff --git a/packages/SystemUI/src/com/android/systemui/unfold/UnfoldTransitionModule.kt b/packages/SystemUI/src/com/android/systemui/unfold/UnfoldTransitionModule.kt
index 50515daedc51..8bef53c8c4fb 100644
--- a/packages/SystemUI/src/com/android/systemui/unfold/UnfoldTransitionModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/unfold/UnfoldTransitionModule.kt
@@ -27,6 +27,8 @@ import com.android.systemui.keyguard.LifecycleScreenStatusProvider
import com.android.systemui.unfold.config.UnfoldTransitionConfig
import com.android.systemui.unfold.dagger.UnfoldBgProgressFlag
import com.android.systemui.unfold.dagger.UnfoldMain
+import com.android.systemui.unfold.data.repository.FoldStateRepository
+import com.android.systemui.unfold.data.repository.FoldStateRepositoryImpl
import com.android.systemui.unfold.data.repository.UnfoldTransitionRepository
import com.android.systemui.unfold.data.repository.UnfoldTransitionRepositoryImpl
import com.android.systemui.unfold.domain.interactor.UnfoldTransitionInteractor
@@ -168,6 +170,11 @@ class UnfoldTransitionModule {
@Provides
fun screenStatusProvider(impl: LifecycleScreenStatusProvider): ScreenStatusProvider = impl
+ @Provides
+ @Singleton
+ fun provideDisplaySwitchLatencyLogger(): DisplaySwitchLatencyLogger =
+ DisplaySwitchLatencyLogger()
+
@Module
interface Bindings {
@Binds
@@ -178,6 +185,8 @@ class UnfoldTransitionModule {
@Binds fun bindRepository(impl: UnfoldTransitionRepositoryImpl): UnfoldTransitionRepository
@Binds fun bindInteractor(impl: UnfoldTransitionInteractorImpl): UnfoldTransitionInteractor
+
+ @Binds fun bindFoldStateRepository(impl: FoldStateRepositoryImpl): FoldStateRepository
}
}
diff --git a/packages/SystemUI/unfold/src/com/android/systemui/unfold/updates/FoldStateRepository.kt b/packages/SystemUI/src/com/android/systemui/unfold/data/repository/FoldStateRepository.kt
index 61b0b40a55bf..04b00ca58c47 100644
--- a/packages/SystemUI/unfold/src/com/android/systemui/unfold/updates/FoldStateRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/unfold/data/repository/FoldStateRepository.kt
@@ -13,9 +13,15 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package com.android.systemui.unfold.updates
+package com.android.systemui.unfold.data.repository
-import com.android.systemui.unfold.updates.FoldStateRepository.FoldUpdate
+import com.android.systemui.unfold.data.repository.FoldStateRepository.FoldUpdate
+import com.android.systemui.unfold.updates.FOLD_UPDATE_FINISH_CLOSED
+import com.android.systemui.unfold.updates.FOLD_UPDATE_FINISH_FULL_OPEN
+import com.android.systemui.unfold.updates.FOLD_UPDATE_FINISH_HALF_OPEN
+import com.android.systemui.unfold.updates.FOLD_UPDATE_START_CLOSING
+import com.android.systemui.unfold.updates.FOLD_UPDATE_START_OPENING
+import com.android.systemui.unfold.updates.FoldStateProvider
import javax.inject.Inject
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.channels.awaitClose
@@ -50,7 +56,7 @@ interface FoldStateRepository {
FOLD_UPDATE_FINISH_HALF_OPEN -> FINISH_HALF_OPEN
FOLD_UPDATE_FINISH_FULL_OPEN -> FINISH_FULL_OPEN
FOLD_UPDATE_FINISH_CLOSED -> FINISH_CLOSED
- else -> error("FoldUpdateNotFound")
+ else -> error("Fold update with id $oldId is not supported")
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/unfold/domain/interactor/UnfoldTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/unfold/domain/interactor/UnfoldTransitionInteractor.kt
index a2e77afedea6..3e2e564c307c 100644
--- a/packages/SystemUI/src/com/android/systemui/unfold/domain/interactor/UnfoldTransitionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/unfold/domain/interactor/UnfoldTransitionInteractor.kt
@@ -15,16 +15,26 @@
*/
package com.android.systemui.unfold.domain.interactor
-import com.android.systemui.unfold.data.repository.UnfoldTransitionStatus.TransitionFinished
import com.android.systemui.unfold.data.repository.UnfoldTransitionRepository
+import com.android.systemui.unfold.data.repository.UnfoldTransitionStatus.TransitionFinished
+import com.android.systemui.unfold.data.repository.UnfoldTransitionStatus.TransitionStarted
import javax.inject.Inject
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.first
+/**
+ * Contains business-logic related to fold-unfold transitions while interacting with
+ * [UnfoldTransitionRepository]
+ */
interface UnfoldTransitionInteractor {
+ /** Returns availability of fold/unfold transitions on the device */
val isAvailable: Boolean
+ /** Suspends and waits for a fold/unfold transition to finish */
suspend fun waitForTransitionFinish()
+
+ /** Suspends and waits for a fold/unfold transition to start */
+ suspend fun waitForTransitionStart()
}
class UnfoldTransitionInteractorImpl
@@ -37,4 +47,8 @@ constructor(private val repository: UnfoldTransitionRepository) : UnfoldTransiti
override suspend fun waitForTransitionFinish() {
repository.transitionStatus.filter { it is TransitionFinished }.first()
}
+
+ override suspend fun waitForTransitionStart() {
+ repository.transitionStatus.filter { it is TransitionStarted }.first()
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/util/Utils.java b/packages/SystemUI/src/com/android/systemui/util/Utils.java
index fa6d0552c9e9..7861ded6cd24 100644
--- a/packages/SystemUI/src/com/android/systemui/util/Utils.java
+++ b/packages/SystemUI/src/com/android/systemui/util/Utils.java
@@ -82,6 +82,14 @@ public class Utils {
}
/**
+ * Returns {@code true} if the device is a foldable device
+ */
+ public static boolean isDeviceFoldable(Context context) {
+ return context.getResources()
+ .getIntArray(com.android.internal.R.array.config_foldedDeviceStates).length != 0;
+ }
+
+ /**
* Allow the media player to be shown in the QS area, controlled by 2 flags.
* On by default, but can be disabled by setting either flag to 0/false.
*/
diff --git a/packages/SystemUI/src/com/android/systemui/util/time/MeasureTimeUtil.kt b/packages/SystemUI/src/com/android/systemui/util/time/MeasureTimeUtil.kt
new file mode 100644
index 000000000000..f13196857167
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/util/time/MeasureTimeUtil.kt
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.util.time
+
+import kotlin.contracts.ExperimentalContracts
+import kotlin.contracts.InvocationKind
+import kotlin.contracts.contract
+
+/**
+ * Executes the given [block] and returns elapsed time using provided [systemClock] in milliseconds.
+ */
+@OptIn(ExperimentalContracts::class)
+inline fun measureTimeMillis(systemClock: SystemClock, block: () -> Unit): Long {
+ contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }
+ val start = systemClock.currentTimeMillis()
+ block()
+ return systemClock.currentTimeMillis() - start
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/unfold/DisplaySwitchLatencyTrackerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/unfold/DisplaySwitchLatencyTrackerTest.kt
new file mode 100644
index 000000000000..ee2e5addd0e6
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/unfold/DisplaySwitchLatencyTrackerTest.kt
@@ -0,0 +1,324 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.unfold
+
+import android.content.Context
+import android.content.res.Resources
+import android.testing.AndroidTestingRunner
+import androidx.test.filters.SmallTest
+import com.android.internal.R
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.display.data.repository.DeviceStateRepository
+import com.android.systemui.display.data.repository.DeviceStateRepository.DeviceState
+import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
+import com.android.systemui.power.domain.interactor.PowerInteractor
+import com.android.systemui.power.shared.model.ScreenPowerState
+import com.android.systemui.power.shared.model.WakeSleepReason
+import com.android.systemui.power.shared.model.WakefulnessModel
+import com.android.systemui.power.shared.model.WakefulnessState
+import com.android.systemui.shared.system.SysUiStatsLog
+import com.android.systemui.unfold.DisplaySwitchLatencyTracker.Companion.FOLDABLE_DEVICE_STATE_CLOSED
+import com.android.systemui.unfold.DisplaySwitchLatencyTracker.Companion.FOLDABLE_DEVICE_STATE_HALF_OPEN
+import com.android.systemui.unfold.DisplaySwitchLatencyTracker.DisplaySwitchLatencyEvent
+import com.android.systemui.unfold.data.repository.UnfoldTransitionRepositoryImpl
+import com.android.systemui.unfold.domain.interactor.UnfoldTransitionInteractorImpl
+import com.android.systemui.util.animation.data.repository.AnimationStatusRepository
+import com.android.systemui.util.mockito.any
+import com.android.systemui.util.mockito.capture
+import com.android.systemui.util.mockito.mock
+import com.android.systemui.util.time.FakeSystemClock
+import com.google.common.truth.Truth.assertThat
+import java.util.Optional
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.asExecutor
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.test.StandardTestDispatcher
+import kotlinx.coroutines.test.TestDispatcher
+import kotlinx.coroutines.test.TestScope
+import kotlinx.coroutines.test.runCurrent
+import kotlinx.coroutines.test.runTest
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.ArgumentCaptor
+import org.mockito.Captor
+import org.mockito.Mockito.never
+import org.mockito.Mockito.verify
+import org.mockito.Mockito.`when` as whenever
+import org.mockito.MockitoAnnotations
+
+@OptIn(ExperimentalCoroutinesApi::class)
+@RunWith(AndroidTestingRunner::class)
+@SmallTest
+class DisplaySwitchLatencyTrackerTest : SysuiTestCase() {
+ private lateinit var displaySwitchLatencyTracker: DisplaySwitchLatencyTracker
+ @Captor private lateinit var loggerArgumentCaptor: ArgumentCaptor<DisplaySwitchLatencyEvent>
+
+ private val mockContext = mock<Context>()
+ private val resources = mock<Resources>()
+ private val foldStateRepository = mock<DeviceStateRepository>()
+ private val powerInteractor = mock<PowerInteractor>()
+ private val animationStatusRepository = mock<AnimationStatusRepository>()
+ private val keyguardInteractor = mock<KeyguardInteractor>()
+ private val displaySwitchLatencyLogger = mock<DisplaySwitchLatencyLogger>()
+
+ private val nonEmptyClosedDeviceStatesArray: IntArray = IntArray(2) { 0 }
+ private val testDispatcher: TestDispatcher = StandardTestDispatcher()
+ private val testScope: TestScope = TestScope(testDispatcher)
+ private val isAsleep = MutableStateFlow(false)
+ private val isAodAvailable = MutableStateFlow(false)
+ private val deviceState = MutableStateFlow(DeviceState.UNFOLDED)
+ private val screenPowerState = MutableStateFlow(ScreenPowerState.SCREEN_ON)
+ private val areAnimationEnabled = MutableStateFlow(true)
+ private val lastWakefulnessEvent = MutableStateFlow(WakefulnessModel())
+ private val systemClock = FakeSystemClock()
+ private val unfoldTransitionProgressProvider = TestUnfoldTransitionProvider()
+ private val unfoldTransitionRepository =
+ UnfoldTransitionRepositoryImpl(Optional.of(unfoldTransitionProgressProvider))
+ private val unfoldTransitionInteractor =
+ UnfoldTransitionInteractorImpl(unfoldTransitionRepository)
+
+ @Before
+ fun setup() {
+ MockitoAnnotations.initMocks(this)
+ whenever(mockContext.resources).thenReturn(resources)
+ whenever(resources.getIntArray(R.array.config_foldedDeviceStates))
+ .thenReturn(nonEmptyClosedDeviceStatesArray)
+ whenever(foldStateRepository.state).thenReturn(deviceState)
+ whenever(powerInteractor.isAsleep).thenReturn(isAsleep)
+ whenever(animationStatusRepository.areAnimationsEnabled()).thenReturn(areAnimationEnabled)
+ whenever(powerInteractor.screenPowerState).thenReturn(screenPowerState)
+ whenever(keyguardInteractor.isAodAvailable).thenReturn(isAodAvailable)
+ whenever(powerInteractor.detailedWakefulness).thenReturn(lastWakefulnessEvent)
+
+ displaySwitchLatencyTracker =
+ DisplaySwitchLatencyTracker(
+ mockContext,
+ foldStateRepository,
+ powerInteractor,
+ unfoldTransitionInteractor,
+ animationStatusRepository,
+ keyguardInteractor,
+ testDispatcher.asExecutor(),
+ testScope.backgroundScope,
+ displaySwitchLatencyLogger,
+ systemClock
+ )
+ }
+
+ @Test
+ fun unfold_logsLatencyTillTransitionStarted() {
+ testScope.runTest {
+ areAnimationEnabled.emit(true)
+
+ displaySwitchLatencyTracker.start()
+ deviceState.emit(DeviceState.FOLDED)
+ screenPowerState.emit(ScreenPowerState.SCREEN_OFF)
+ systemClock.advanceTime(50)
+ runCurrent()
+ deviceState.emit(DeviceState.HALF_FOLDED)
+ runCurrent()
+ systemClock.advanceTime(50)
+ screenPowerState.emit(ScreenPowerState.SCREEN_ON)
+ systemClock.advanceTime(200)
+ unfoldTransitionProgressProvider.onTransitionStarted()
+ runCurrent()
+ deviceState.emit(DeviceState.UNFOLDED)
+
+ verify(displaySwitchLatencyLogger).log(capture(loggerArgumentCaptor))
+ val loggedEvent = loggerArgumentCaptor.value
+ val expectedLoggedEvent =
+ DisplaySwitchLatencyEvent(
+ latencyMs = 250,
+ fromFoldableDeviceState = FOLDABLE_DEVICE_STATE_CLOSED,
+ toFoldableDeviceState = FOLDABLE_DEVICE_STATE_HALF_OPEN
+ )
+ assertThat(loggedEvent).isEqualTo(expectedLoggedEvent)
+ }
+ }
+
+ @Test
+ fun unfold_progressUnavailable_logsLatencyTillScreenTurnedOn() {
+ testScope.runTest {
+ val unfoldTransitionInteractorWithEmptyProgressProvider =
+ UnfoldTransitionInteractorImpl(UnfoldTransitionRepositoryImpl(Optional.empty()))
+ displaySwitchLatencyTracker =
+ DisplaySwitchLatencyTracker(
+ mockContext,
+ foldStateRepository,
+ powerInteractor,
+ unfoldTransitionInteractorWithEmptyProgressProvider,
+ animationStatusRepository,
+ keyguardInteractor,
+ testDispatcher.asExecutor(),
+ testScope.backgroundScope,
+ displaySwitchLatencyLogger,
+ systemClock
+ )
+ areAnimationEnabled.emit(true)
+
+ displaySwitchLatencyTracker.start()
+ deviceState.emit(DeviceState.FOLDED)
+ screenPowerState.emit(ScreenPowerState.SCREEN_OFF)
+ systemClock.advanceTime(50)
+ runCurrent()
+ deviceState.emit(DeviceState.HALF_FOLDED)
+ systemClock.advanceTime(50)
+ runCurrent()
+ screenPowerState.emit(ScreenPowerState.SCREEN_ON)
+ systemClock.advanceTime(50)
+ runCurrent()
+ systemClock.advanceTime(200)
+ unfoldTransitionProgressProvider.onTransitionStarted()
+ runCurrent()
+ deviceState.emit(DeviceState.UNFOLDED)
+
+ verify(displaySwitchLatencyLogger).log(capture(loggerArgumentCaptor))
+ val loggedEvent = loggerArgumentCaptor.value
+ val expectedLoggedEvent =
+ DisplaySwitchLatencyEvent(
+ latencyMs = 50,
+ fromFoldableDeviceState = FOLDABLE_DEVICE_STATE_CLOSED,
+ toFoldableDeviceState = FOLDABLE_DEVICE_STATE_HALF_OPEN
+ )
+ assertThat(loggedEvent).isEqualTo(expectedLoggedEvent)
+ }
+ }
+
+ @Test
+ fun unfold_animationDisabled_logsLatencyTillScreenTurnedOn() {
+ testScope.runTest {
+ areAnimationEnabled.emit(false)
+
+ displaySwitchLatencyTracker.start()
+ deviceState.emit(DeviceState.FOLDED)
+ screenPowerState.emit(ScreenPowerState.SCREEN_OFF)
+ systemClock.advanceTime(50)
+ runCurrent()
+ deviceState.emit(DeviceState.HALF_FOLDED)
+ systemClock.advanceTime(50)
+ runCurrent()
+ screenPowerState.emit(ScreenPowerState.SCREEN_ON)
+ systemClock.advanceTime(50)
+ runCurrent()
+ unfoldTransitionProgressProvider.onTransitionStarted()
+ systemClock.advanceTime(200)
+ runCurrent()
+ deviceState.emit(DeviceState.UNFOLDED)
+
+ verify(displaySwitchLatencyLogger).log(capture(loggerArgumentCaptor))
+ val loggedEvent = loggerArgumentCaptor.value
+ val expectedLoggedEvent =
+ DisplaySwitchLatencyEvent(
+ latencyMs = 50,
+ fromFoldableDeviceState = FOLDABLE_DEVICE_STATE_CLOSED,
+ toFoldableDeviceState = FOLDABLE_DEVICE_STATE_HALF_OPEN
+ )
+ assertThat(loggedEvent).isEqualTo(expectedLoggedEvent)
+ }
+ }
+
+ @Test
+ fun foldWhileStayingAwake_logsLatency() {
+ testScope.runTest {
+ areAnimationEnabled.emit(true)
+ deviceState.emit(DeviceState.UNFOLDED)
+ screenPowerState.emit(ScreenPowerState.SCREEN_ON)
+
+ displaySwitchLatencyTracker.start()
+ deviceState.emit(DeviceState.HALF_FOLDED)
+ systemClock.advanceTime(50)
+ runCurrent()
+ deviceState.emit(DeviceState.FOLDED)
+ screenPowerState.emit(ScreenPowerState.SCREEN_OFF)
+ runCurrent()
+ systemClock.advanceTime(200)
+ screenPowerState.emit(ScreenPowerState.SCREEN_ON)
+ runCurrent()
+
+ verify(displaySwitchLatencyLogger).log(capture(loggerArgumentCaptor))
+ val loggedEvent = loggerArgumentCaptor.value
+ val expectedLoggedEvent =
+ DisplaySwitchLatencyEvent(
+ latencyMs = 200,
+ fromFoldableDeviceState = FOLDABLE_DEVICE_STATE_HALF_OPEN,
+ toFoldableDeviceState = FOLDABLE_DEVICE_STATE_CLOSED
+ )
+ assertThat(loggedEvent).isEqualTo(expectedLoggedEvent)
+ }
+ }
+
+ @Test
+ fun foldToAod_capturesToStateAsAod() {
+ testScope.runTest {
+ areAnimationEnabled.emit(true)
+ deviceState.emit(DeviceState.UNFOLDED)
+ isAodAvailable.emit(true)
+
+ displaySwitchLatencyTracker.start()
+ deviceState.emit(DeviceState.HALF_FOLDED)
+ systemClock.advanceTime(50)
+ runCurrent()
+ deviceState.emit(DeviceState.FOLDED)
+ lastWakefulnessEvent.emit(
+ WakefulnessModel(
+ internalWakefulnessState = WakefulnessState.ASLEEP,
+ lastSleepReason = WakeSleepReason.FOLD
+ )
+ )
+ screenPowerState.emit(ScreenPowerState.SCREEN_OFF)
+ runCurrent()
+ systemClock.advanceTime(200)
+ screenPowerState.emit(ScreenPowerState.SCREEN_ON)
+ runCurrent()
+
+ verify(displaySwitchLatencyLogger).log(capture(loggerArgumentCaptor))
+ val loggedEvent = loggerArgumentCaptor.value
+ val expectedLoggedEvent =
+ DisplaySwitchLatencyEvent(
+ latencyMs = 200,
+ fromFoldableDeviceState = FOLDABLE_DEVICE_STATE_HALF_OPEN,
+ toFoldableDeviceState = FOLDABLE_DEVICE_STATE_CLOSED,
+ toState = SysUiStatsLog.DISPLAY_SWITCH_LATENCY_TRACKED__TO_STATE__AOD
+ )
+ assertThat(loggedEvent).isEqualTo(expectedLoggedEvent)
+ }
+ }
+
+ @Test
+ fun fold_notAFoldable_shouldNotLogLatency() {
+ testScope.runTest {
+ areAnimationEnabled.emit(true)
+ deviceState.emit(DeviceState.UNFOLDED)
+ whenever(resources.getIntArray(R.array.config_foldedDeviceStates))
+ .thenReturn(IntArray(0))
+
+ displaySwitchLatencyTracker.start()
+ deviceState.emit(DeviceState.HALF_FOLDED)
+ systemClock.advanceTime(50)
+ runCurrent()
+ deviceState.emit(DeviceState.FOLDED)
+ screenPowerState.emit(ScreenPowerState.SCREEN_OFF)
+ runCurrent()
+ systemClock.advanceTime(200)
+ screenPowerState.emit(ScreenPowerState.SCREEN_ON)
+ runCurrent()
+
+ verify(displaySwitchLatencyLogger, never()).log(any())
+ }
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/unfold/updates/FoldStateRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/unfold/FoldStateRepositoryTest.kt
index 065132300564..ab779a75518e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/unfold/updates/FoldStateRepositoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/unfold/FoldStateRepositoryTest.kt
@@ -13,13 +13,20 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package com.android.systemui.unfold.updates
+package com.android.systemui.unfold
import android.testing.AndroidTestingRunner
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.coroutines.collectLastValue
-import com.android.systemui.unfold.updates.FoldStateRepository.FoldUpdate
+import com.android.systemui.unfold.data.repository.FoldStateRepository.FoldUpdate
+import com.android.systemui.unfold.data.repository.FoldStateRepositoryImpl
+import com.android.systemui.unfold.updates.FOLD_UPDATE_FINISH_CLOSED
+import com.android.systemui.unfold.updates.FOLD_UPDATE_FINISH_FULL_OPEN
+import com.android.systemui.unfold.updates.FOLD_UPDATE_FINISH_HALF_OPEN
+import com.android.systemui.unfold.updates.FOLD_UPDATE_START_CLOSING
+import com.android.systemui.unfold.updates.FOLD_UPDATE_START_OPENING
+import com.android.systemui.unfold.updates.FoldStateProvider
import com.android.systemui.util.mockito.argumentCaptor
import com.android.systemui.util.mockito.capture
import com.android.systemui.util.mockito.mock
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardRepository.kt
index 4200f05ad64b..975db3b179ac 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardRepository.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardRepository.kt
@@ -80,7 +80,7 @@ class FakeKeyguardRepository @Inject constructor() : KeyguardRepository {
override val lastDozeTapToWakePosition = _lastDozeTapToWakePosition.asStateFlow()
private val _isAodAvailable = MutableStateFlow(false)
- override val isAodAvailable: Flow<Boolean> = _isAodAvailable
+ override val isAodAvailable: StateFlow<Boolean> = _isAodAvailable
private val _isDreaming = MutableStateFlow(false)
override val isDreaming: Flow<Boolean> = _isDreaming
diff --git a/packages/SystemUI/unfold/src/com/android/systemui/unfold/UnfoldSharedModule.kt b/packages/SystemUI/unfold/src/com/android/systemui/unfold/UnfoldSharedModule.kt
index f7fb01465a40..1b7e71a42c22 100644
--- a/packages/SystemUI/unfold/src/com/android/systemui/unfold/UnfoldSharedModule.kt
+++ b/packages/SystemUI/unfold/src/com/android/systemui/unfold/UnfoldSharedModule.kt
@@ -27,8 +27,6 @@ import com.android.systemui.unfold.progress.PhysicsBasedUnfoldTransitionProgress
import com.android.systemui.unfold.progress.UnfoldTransitionProgressForwarder
import com.android.systemui.unfold.updates.DeviceFoldStateProvider
import com.android.systemui.unfold.updates.FoldStateProvider
-import com.android.systemui.unfold.updates.FoldStateRepository
-import com.android.systemui.unfold.updates.FoldStateRepositoryImpl
import com.android.systemui.unfold.updates.RotationChangeProvider
import com.android.systemui.unfold.updates.hinge.EmptyHingeAngleProvider
import com.android.systemui.unfold.updates.hinge.HingeAngleProvider
@@ -68,10 +66,6 @@ class UnfoldSharedModule {
fun unfoldKeyguardVisibilityManager(
impl: UnfoldKeyguardVisibilityManagerImpl
): UnfoldKeyguardVisibilityManager = impl
-
- @Provides
- @Singleton
- fun foldStateRepository(impl: FoldStateRepositoryImpl): FoldStateRepository = impl
}
@Module