diff options
| author | 2024-09-11 08:23:10 +0000 | |
|---|---|---|
| committer | 2024-09-11 08:23:10 +0000 | |
| commit | 6501ca315efe4bddaac97ed2bfa0334b7858875a (patch) | |
| tree | ebb9eb242c034a2b9352a5e73e57af0c20957400 | |
| parent | f8481647d19d25043cb1fc3a60265243ef85e170 (diff) | |
| parent | 931f02d95d53fa18bcf1f602a6e53aa2cc3c7c31 (diff) | |
Merge "[Contextual Edu] Check if initial delay is elapsed before updating signal count" into main
4 files changed, 117 insertions, 7 deletions
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/education/domain/interactor/KeyboardTouchpadStatsInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/education/domain/interactor/KeyboardTouchpadStatsInteractorTest.kt index c4fc13227eef..98e09474d5f2 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/education/domain/interactor/KeyboardTouchpadStatsInteractorTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/education/domain/interactor/KeyboardTouchpadStatsInteractorTest.kt @@ -24,12 +24,17 @@ import com.android.systemui.contextualeducation.GestureType.BACK import com.android.systemui.coroutines.collectLastValue import com.android.systemui.education.data.repository.contextualEducationRepository import com.android.systemui.education.data.repository.fakeEduClock +import com.android.systemui.inputdevice.tutorial.data.repository.DeviceType +import com.android.systemui.inputdevice.tutorial.tutorialSchedulerRepository import com.android.systemui.keyboard.data.repository.keyboardRepository import com.android.systemui.kosmos.testScope import com.android.systemui.testKosmos import com.android.systemui.touchpad.data.repository.touchpadRepository import com.google.common.truth.Truth.assertThat +import kotlin.time.Duration.Companion.seconds +import kotlinx.coroutines.launch import kotlinx.coroutines.test.runTest +import org.junit.After import org.junit.Test import org.junit.runner.RunWith @@ -42,10 +47,15 @@ class KeyboardTouchpadStatsInteractorTest : SysuiTestCase() { private val keyboardRepository = kosmos.keyboardRepository private val touchpadRepository = kosmos.touchpadRepository private val repository = kosmos.contextualEducationRepository + private val fakeClock = kosmos.fakeEduClock + private val tutorialSchedulerRepository = kosmos.tutorialSchedulerRepository + private val initialDelayElapsedDuration = + KeyboardTouchpadEduStatsInteractorImpl.initialDelayDuration + 1.seconds @Test fun dataUpdatedOnIncrementSignalCountWhenTouchpadConnected() = testScope.runTest { + setUpForInitialDelayElapse() touchpadRepository.setIsAnyTouchpadConnected(true) val model by collectLastValue(repository.readGestureEduModelFlow(BACK)) @@ -58,6 +68,7 @@ class KeyboardTouchpadStatsInteractorTest : SysuiTestCase() { @Test fun dataUnchangedOnIncrementSignalCountWhenTouchpadDisconnected() = testScope.runTest { + setUpForInitialDelayElapse() touchpadRepository.setIsAnyTouchpadConnected(false) val model by collectLastValue(repository.readGestureEduModelFlow(BACK)) @@ -70,6 +81,7 @@ class KeyboardTouchpadStatsInteractorTest : SysuiTestCase() { @Test fun dataUpdatedOnIncrementSignalCountWhenKeyboardConnected() = testScope.runTest { + setUpForInitialDelayElapse() keyboardRepository.setIsAnyKeyboardConnected(true) val model by collectLastValue(repository.readGestureEduModelFlow(ALL_APPS)) @@ -82,6 +94,7 @@ class KeyboardTouchpadStatsInteractorTest : SysuiTestCase() { @Test fun dataUnchangedOnIncrementSignalCountWhenKeyboardDisconnected() = testScope.runTest { + setUpForInitialDelayElapse() keyboardRepository.setIsAnyKeyboardConnected(false) val model by collectLastValue(repository.readGestureEduModelFlow(ALL_APPS)) @@ -99,4 +112,61 @@ class KeyboardTouchpadStatsInteractorTest : SysuiTestCase() { underTest.updateShortcutTriggerTime(BACK) assertThat(model?.lastShortcutTriggeredTime).isEqualTo(kosmos.fakeEduClock.instant()) } + + @Test + fun dataUpdatedOnIncrementSignalCountAfterInitialDelay() = + testScope.runTest { + setUpForDeviceConnection() + tutorialSchedulerRepository.updateLaunchTime(DeviceType.TOUCHPAD, fakeClock.instant()) + + fakeClock.offset(initialDelayElapsedDuration) + val model by collectLastValue(repository.readGestureEduModelFlow(BACK)) + val originalValue = model!!.signalCount + underTest.incrementSignalCount(BACK) + + assertThat(model?.signalCount).isEqualTo(originalValue + 1) + } + + @Test + fun dataUnchangedOnIncrementSignalCountBeforeInitialDelay() = + testScope.runTest { + setUpForDeviceConnection() + tutorialSchedulerRepository.updateLaunchTime(DeviceType.TOUCHPAD, fakeClock.instant()) + + // No offset to the clock to simulate update before initial delay + val model by collectLastValue(repository.readGestureEduModelFlow(BACK)) + val originalValue = model!!.signalCount + underTest.incrementSignalCount(BACK) + + assertThat(model?.signalCount).isEqualTo(originalValue) + } + + @Test + fun dataUnchangedOnIncrementSignalCountWithoutOobeLaunchTime() = + testScope.runTest { + // No update to OOBE launch time to simulate no OOBE is launched yet + setUpForDeviceConnection() + + val model by collectLastValue(repository.readGestureEduModelFlow(BACK)) + val originalValue = model!!.signalCount + underTest.incrementSignalCount(BACK) + + assertThat(model?.signalCount).isEqualTo(originalValue) + } + + private suspend fun setUpForInitialDelayElapse() { + tutorialSchedulerRepository.updateLaunchTime(DeviceType.TOUCHPAD, fakeClock.instant()) + tutorialSchedulerRepository.updateLaunchTime(DeviceType.KEYBOARD, fakeClock.instant()) + fakeClock.offset(initialDelayElapsedDuration) + } + + private fun setUpForDeviceConnection() { + touchpadRepository.setIsAnyTouchpadConnected(true) + keyboardRepository.setIsAnyKeyboardConnected(true) + } + + @After + fun clear() { + testScope.launch { tutorialSchedulerRepository.clearDataStore() } + } } diff --git a/packages/SystemUI/src/com/android/systemui/education/domain/interactor/KeyboardTouchpadEduStatsInteractor.kt b/packages/SystemUI/src/com/android/systemui/education/domain/interactor/KeyboardTouchpadEduStatsInteractor.kt index eb4eee204834..0e2d9b6a3ae0 100644 --- a/packages/SystemUI/src/com/android/systemui/education/domain/interactor/KeyboardTouchpadEduStatsInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/education/domain/interactor/KeyboardTouchpadEduStatsInteractor.kt @@ -16,15 +16,23 @@ package com.android.systemui.education.domain.interactor +import android.os.SystemProperties import com.android.systemui.contextualeducation.GestureType import com.android.systemui.contextualeducation.GestureType.ALL_APPS import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Background +import com.android.systemui.education.dagger.ContextualEducationModule.EduClock import com.android.systemui.inputdevice.data.repository.UserInputDeviceRepository import com.android.systemui.inputdevice.tutorial.data.repository.DeviceType import com.android.systemui.inputdevice.tutorial.data.repository.DeviceType.KEYBOARD import com.android.systemui.inputdevice.tutorial.data.repository.DeviceType.TOUCHPAD +import com.android.systemui.inputdevice.tutorial.data.repository.TutorialSchedulerRepository +import java.time.Clock import javax.inject.Inject +import kotlin.time.Duration +import kotlin.time.Duration.Companion.hours +import kotlin.time.DurationUnit +import kotlin.time.toDuration import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.first import kotlinx.coroutines.launch @@ -47,12 +55,24 @@ constructor( @Background private val backgroundScope: CoroutineScope, private val contextualEducationInteractor: ContextualEducationInteractor, private val inputDeviceRepository: UserInputDeviceRepository, + private val tutorialRepository: TutorialSchedulerRepository, + @EduClock private val clock: Clock, ) : KeyboardTouchpadEduStatsInteractor { + companion object { + val initialDelayDuration: Duration + get() = + SystemProperties.getLong( + "persist.contextual_edu.initial_delay_sec", + /* defaultValue= */ 72.hours.inWholeSeconds + ) + .toDuration(DurationUnit.SECONDS) + } + override fun incrementSignalCount(gestureType: GestureType) { backgroundScope.launch { val targetDevice = getTargetDevice(gestureType) - if (isTargetDeviceConnected(targetDevice)) { + if (isTargetDeviceConnected(targetDevice) && hasInitialDelayElapsed(targetDevice)) { contextualEducationInteractor.incrementSignalCount(gestureType) } } @@ -65,12 +85,10 @@ constructor( } private suspend fun isTargetDeviceConnected(deviceType: DeviceType): Boolean { - if (deviceType == KEYBOARD) { - return inputDeviceRepository.isAnyKeyboardConnectedForUser.first().isConnected - } else if (deviceType == TOUCHPAD) { - return inputDeviceRepository.isAnyTouchpadConnectedForUser.first().isConnected + return when (deviceType) { + KEYBOARD -> inputDeviceRepository.isAnyKeyboardConnectedForUser.first().isConnected + TOUCHPAD -> inputDeviceRepository.isAnyTouchpadConnectedForUser.first().isConnected } - return false } /** @@ -83,4 +101,11 @@ constructor( ALL_APPS -> KEYBOARD else -> TOUCHPAD } + + private suspend fun hasInitialDelayElapsed(deviceType: DeviceType): Boolean { + val oobeLaunchTime = tutorialRepository.launchTime(deviceType) ?: return false + return clock + .instant() + .isAfter(oobeLaunchTime.plusSeconds(initialDelayDuration.inWholeSeconds)) + } } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/education/domain/interactor/KeyboardTouchpadEduInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/education/domain/interactor/KeyboardTouchpadEduInteractorKosmos.kt index 251a6b10a0da..80f6fc24ef2c 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/education/domain/interactor/KeyboardTouchpadEduInteractorKosmos.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/education/domain/interactor/KeyboardTouchpadEduInteractorKosmos.kt @@ -19,6 +19,7 @@ package com.android.systemui.education.domain.interactor import android.hardware.input.InputManager import com.android.systemui.education.data.repository.fakeEduClock import com.android.systemui.inputdevice.data.repository.UserInputDeviceRepository +import com.android.systemui.inputdevice.tutorial.tutorialSchedulerRepository import com.android.systemui.keyboard.data.repository.keyboardRepository import com.android.systemui.kosmos.Kosmos import com.android.systemui.kosmos.testDispatcher @@ -57,6 +58,8 @@ var Kosmos.keyboardTouchpadEduStatsInteractor by keyboardRepository, touchpadRepository, userRepository - ) + ), + tutorialSchedulerRepository, + fakeEduClock ) } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/inputdevice/tutorial/InputDeviceTutorialKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/inputdevice/tutorial/InputDeviceTutorialKosmos.kt index 827f0d277d11..a83baffd78b2 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/inputdevice/tutorial/InputDeviceTutorialKosmos.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/inputdevice/tutorial/InputDeviceTutorialKosmos.kt @@ -16,8 +16,20 @@ package com.android.systemui.inputdevice.tutorial +import android.content.applicationContext +import com.android.systemui.inputdevice.tutorial.data.repository.TutorialSchedulerRepository import com.android.systemui.kosmos.Kosmos +import com.android.systemui.kosmos.testScope import org.mockito.kotlin.mock var Kosmos.inputDeviceTutorialLogger: InputDeviceTutorialLogger by Kosmos.Fixture { mock<InputDeviceTutorialLogger>() } + +var Kosmos.tutorialSchedulerRepository by + Kosmos.Fixture { + TutorialSchedulerRepository( + applicationContext = applicationContext, + testScope.backgroundScope, + "KosmosTutorialSchedulerRepository" + ) + } |