Loading packages/SystemUI/multivalentTests/src/com/android/systemui/topwindoweffects/data/repository/SqueezeEffectRepositoryTest.kt +101 −15 Original line number Diff line number Diff line Loading @@ -32,6 +32,9 @@ import com.android.systemui.kosmos.testScope import com.android.systemui.kosmos.useUnconfinedTestDispatcher import com.android.systemui.shared.Flags import com.android.systemui.testKosmos import com.android.systemui.topwindoweffects.data.repository.InvocationEffectPreferencesImpl.Companion.DEFAULT_INVOCATION_EFFECT_ENABLED_BY_ASSISTANT_PREFERENCE import com.android.systemui.topwindoweffects.data.repository.InvocationEffectPreferencesImpl.Companion.DEFAULT_INWARD_EFFECT_PADDING_DURATION_MS import com.android.systemui.topwindoweffects.data.repository.InvocationEffectPreferencesImpl.Companion.DEFAULT_OUTWARD_EFFECT_DURATION_MS import com.android.systemui.topwindoweffects.data.repository.InvocationEffectPreferencesImpl.Companion.INVOCATION_EFFECT_ANIMATION_IN_DURATION_PADDING_MS import com.android.systemui.topwindoweffects.data.repository.InvocationEffectPreferencesImpl.Companion.INVOCATION_EFFECT_ANIMATION_OUT_DURATION_MS import com.android.systemui.topwindoweffects.data.repository.SqueezeEffectRepositoryImpl.Companion.IS_INVOCATION_EFFECT_ENABLED_KEY Loading Loading @@ -162,7 +165,14 @@ class SqueezeEffectRepositoryTest : SysuiTestCase() { @Test fun testInvocationEffectInwardsAnimationDelay() = kosmos.runTest { fakeInvocationEffectPreferences.setInwardAnimationPaddingDurationMillis(450) fakeInvocationEffectPreferences.setInvocationEffectConfig( InvocationEffectPreferences.Config( isEnabled = true, inwardsEffectDurationPadding = 450, outwardsEffectDuration = 400, ), true, ) assertThat(underTest.getInvocationEffectInAnimationDurationMillis()).isEqualTo(800) } Loading @@ -171,44 +181,120 @@ class SqueezeEffectRepositoryTest : SysuiTestCase() { @Test fun testInvocationEffectOutwardsAnimationDelay() = kosmos.runTest { fakeInvocationEffectPreferences.setOutwardAnimationDurationMillis(400) fakeInvocationEffectPreferences.setInvocationEffectConfig( InvocationEffectPreferences.Config( isEnabled = true, inwardsEffectDurationPadding = 450, outwardsEffectDuration = 400, ), true, ) assertThat(underTest.getInvocationEffectOutAnimationDurationMillis()).isEqualTo(400) } @EnableFlags(Flags.FLAG_ENABLE_LPP_ASSIST_INVOCATION_EFFECT) @Test fun testSetUiHintsShouldUpdatePreferences() = fun testSetUiHints_whenSuppliedAllConfigs_allUpdatedInPreferences() = kosmos.runTest { fakeInvocationEffectPreferences.activeUserId = 1 fakeInvocationEffectPreferences.activeAssistant = "A" assertThat(fakeInvocationEffectPreferences.isActiveUserAndAssistantPersisted()) assertThat(fakeInvocationEffectPreferences.isCurrentUserAndAssistantPersisted()) .isFalse() val hints = createAssistantSettingBundle(false, 0, 1000) val hints = createAssistantSettingBundle( enableAssistantSetting = false, inwardsPaddingDuration = 0, outwardsAnimationDuration = 1000, ) underTest.tryHandleSetUiHints(hints) val isEffectEnabledAndPowerButtonPressed by collectLastValue(underTest.isEffectEnabledAndPowerButtonPressedAsSingleGesture) assertThat(fakeInvocationEffectPreferences.getInwardAnimationPaddingDurationMillis()) .isEqualTo(0) assertThat(fakeInvocationEffectPreferences.getOutwardAnimationDurationMillis()) .isEqualTo(1000) assertThat(fakeInvocationEffectPreferences.isInvocationEffectEnabledInPreferences()) .isFalse() assertThat(fakeInvocationEffectPreferences.isCurrentUserAndAssistantPersisted()) .isTrue() } @EnableFlags(Flags.FLAG_ENABLE_LPP_ASSIST_INVOCATION_EFFECT) @Test fun testSetUiHints_whenSuppliedPartialConfig() = kosmos.runTest { fakeInvocationEffectPreferences.activeUserId = 1 fakeInvocationEffectPreferences.activeAssistant = "A" assertThat(fakeInvocationEffectPreferences.isCurrentUserAndAssistantPersisted()) .isFalse() underTest.tryHandleSetUiHints( createAssistantSettingBundle( enableAssistantSetting = false, inwardsPaddingDuration = 0, outwardsAnimationDuration = 1000, ) ) assertThat(isEffectEnabledAndPowerButtonPressed).isFalse() assertThat(fakeInvocationEffectPreferences.getInwardAnimationPaddingDurationMillis()) .isEqualTo(0) assertThat(fakeInvocationEffectPreferences.getOutwardAnimationDurationMillis()) .isEqualTo(1000) assertThat(fakeInvocationEffectPreferences.isActiveUserAndAssistantPersisted()).isTrue() assertThat(fakeInvocationEffectPreferences.isInvocationEffectEnabledInPreferences()) .isFalse() assertThat(fakeInvocationEffectPreferences.isCurrentUserAndAssistantPersisted()) .isTrue() underTest.tryHandleSetUiHints( createAssistantSettingBundle(enableAssistantSetting = true) ) assertThat(fakeInvocationEffectPreferences.getInwardAnimationPaddingDurationMillis()) .isEqualTo(0) assertThat(fakeInvocationEffectPreferences.getOutwardAnimationDurationMillis()) .isEqualTo(1000) assertThat(fakeInvocationEffectPreferences.isInvocationEffectEnabledInPreferences()) .isTrue() } @EnableFlags(Flags.FLAG_ENABLE_LPP_ASSIST_INVOCATION_EFFECT) @Test fun testSetUiHints_whenSuppliedNoConfig_shouldSetDefaults() = kosmos.runTest { fakeInvocationEffectPreferences.activeUserId = 1 fakeInvocationEffectPreferences.activeAssistant = "A" assertThat(fakeInvocationEffectPreferences.isCurrentUserAndAssistantPersisted()) .isFalse() underTest.tryHandleSetUiHints(createAssistantSettingBundle()) assertThat(fakeInvocationEffectPreferences.getInwardAnimationPaddingDurationMillis()) .isEqualTo(DEFAULT_INWARD_EFFECT_PADDING_DURATION_MS) assertThat(fakeInvocationEffectPreferences.getOutwardAnimationDurationMillis()) .isEqualTo(DEFAULT_OUTWARD_EFFECT_DURATION_MS) assertThat(fakeInvocationEffectPreferences.isInvocationEffectEnabledInPreferences()) .isEqualTo(DEFAULT_INVOCATION_EFFECT_ENABLED_BY_ASSISTANT_PREFERENCE) assertThat(fakeInvocationEffectPreferences.isCurrentUserAndAssistantPersisted()) .isTrue() } private fun createAssistantSettingBundle( enableAssistantSetting: Boolean, inwardsPaddingDuration: Long, outwardsAnimationDuration: Long, enableAssistantSetting: Boolean? = null, inwardsPaddingDuration: Long? = null, outwardsAnimationDuration: Long? = null, ) = Bundle().apply { putString(AssistManager.ACTION_KEY, SET_INVOCATION_EFFECT_PARAMETERS_ACTION) putBoolean(IS_INVOCATION_EFFECT_ENABLED_KEY, enableAssistantSetting) putLong(INVOCATION_EFFECT_ANIMATION_IN_DURATION_PADDING_MS, inwardsPaddingDuration) putLong(INVOCATION_EFFECT_ANIMATION_OUT_DURATION_MS, outwardsAnimationDuration) enableAssistantSetting?.let { putBoolean(IS_INVOCATION_EFFECT_ENABLED_KEY, it) } inwardsPaddingDuration?.let { putLong(INVOCATION_EFFECT_ANIMATION_IN_DURATION_PADDING_MS, it) } outwardsAnimationDuration?.let { putLong(INVOCATION_EFFECT_ANIMATION_OUT_DURATION_MS, it) } } } packages/SystemUI/src/com/android/systemui/topwindoweffects/data/repository/InvocationEffectPreferences.kt +66 −60 Original line number Diff line number Diff line Loading @@ -51,25 +51,27 @@ interface InvocationEffectPreferences { val isInvocationEffectEnabledByAssistant: StateFlow<Boolean> fun saveCurrentAssistant() fun saveCurrentUserId() fun setInvocationEffectEnabledByAssistant(enabled: Boolean) fun setInwardAnimationPaddingDurationMillis(duration: Long) fun isInvocationEffectEnabledInPreferences(): Boolean fun getInwardAnimationPaddingDurationMillis(): Long fun setOutwardAnimationDurationMillis(duration: Long) fun getOutwardAnimationDurationMillis(): Long fun isCurrentUserAndAssistantPersisted(): Boolean fun setInvocationEffectConfig(config: Config, saveActiveUserAndAssistant: Boolean) fun registerOnChangeListener(listener: SharedPreferences.OnSharedPreferenceChangeListener) fun unregisterOnChangeListener(listener: SharedPreferences.OnSharedPreferenceChangeListener) fun dump(pw: PrintWriter, args: Array<out String>) data class Config( val isEnabled: Boolean, val inwardsEffectDurationPadding: Long, val outwardsEffectDuration: Long, ) } @SysUISingleton Loading @@ -81,7 +83,7 @@ constructor( private val userRepository: UserRepository, roleManager: RoleManager, @Background executor: Executor, @Background coroutineContext: CoroutineContext, @Background private val coroutineContext: CoroutineContext, ) : InvocationEffectPreferences { private val sharedPreferences by lazy { Loading Loading @@ -120,7 +122,8 @@ constructor( val changed = activeUser != userId || activeAssistant != assistant if (changed) { activeUser = userId activeAssistant = assistant activeAssistant = roleManager.getCurrentAssistantFor(userRepository.selectedUserHandle) } changed } Loading Loading @@ -152,10 +155,6 @@ constructor( initialValue = isInvocationEffectEnabledByAssistant(), ) override fun saveCurrentAssistant() { setInPreferences { putString(PERSISTED_FOR_ASSISTANT_PREFERENCE, activeAssistant) } } private fun getSavedAssistant(): String = getOrDefault<String>( key = PERSISTED_FOR_ASSISTANT_PREFERENCE, Loading @@ -163,10 +162,6 @@ constructor( checkUserAndAssistant = false, ) override fun saveCurrentUserId() { setInPreferences { putInt(PERSISTED_FOR_USER_PREFERENCE, activeUser) } } private fun getSavedUserId(): Int = getOrDefault<Int>( key = PERSISTED_FOR_USER_PREFERENCE, Loading @@ -174,31 +169,8 @@ constructor( checkUserAndAssistant = false, ) override fun setInvocationEffectEnabledByAssistant(enabled: Boolean) { setInPreferences { putBoolean(IS_INVOCATION_EFFECT_ENABLED_BY_ASSISTANT_PREFERENCE, enabled) } } private fun isInvocationEffectEnabledByAssistant(): Boolean = getOrDefault<Boolean>( key = IS_INVOCATION_EFFECT_ENABLED_BY_ASSISTANT_PREFERENCE, default = true, checkUserAndAssistant = true, ) && activeAssistant.isNotEmpty() override fun setInwardAnimationPaddingDurationMillis(duration: Long) { setInPreferences { if (duration in 0..1000) { putLong(INVOCATION_EFFECT_ANIMATION_IN_DURATION_PADDING_MS, duration) } else { putLong( INVOCATION_EFFECT_ANIMATION_IN_DURATION_PADDING_MS, DEFAULT_INWARD_EFFECT_PADDING_DURATION_MS, ) } } } isInvocationEffectEnabledInPreferences() && activeAssistant.isNotEmpty() override fun getInwardAnimationPaddingDurationMillis(): Long = getOrDefault<Long>( Loading @@ -207,20 +179,6 @@ constructor( checkUserAndAssistant = true, ) // TODO(b/418685731): Should we have a positive non-zero min value for out effect duration? override fun setOutwardAnimationDurationMillis(duration: Long) { setInPreferences { if (duration in 0..1000) { putLong(INVOCATION_EFFECT_ANIMATION_OUT_DURATION_MS, duration) } else { putLong( INVOCATION_EFFECT_ANIMATION_OUT_DURATION_MS, DEFAULT_OUTWARD_EFFECT_DURATION_MS, ) } } } override fun getOutwardAnimationDurationMillis(): Long = getOrDefault<Long>( key = INVOCATION_EFFECT_ANIMATION_OUT_DURATION_MS, Loading @@ -228,11 +186,59 @@ constructor( checkUserAndAssistant = true, ) private fun isCurrentUserAndAssistantPersisted(): Boolean = override fun isCurrentUserAndAssistantPersisted(): Boolean = activeUser == getSavedUserId() && activeAssistant == getSavedAssistant() private fun setInPreferences(block: SharedPreferences.Editor.() -> Unit) { bgScope.launch { sharedPreferences.edit { block() } } override fun isInvocationEffectEnabledInPreferences(): Boolean = getOrDefault<Boolean>( key = IS_INVOCATION_EFFECT_ENABLED_BY_ASSISTANT_PREFERENCE, default = DEFAULT_INVOCATION_EFFECT_ENABLED_BY_ASSISTANT_PREFERENCE, checkUserAndAssistant = true, ) override fun setInvocationEffectConfig( config: InvocationEffectPreferences.Config, saveActiveUserAndAssistant: Boolean, ) { bgScope.launch(context = coroutineContext) { sharedPreferences.edit { if (saveActiveUserAndAssistant) { putString(PERSISTED_FOR_ASSISTANT_PREFERENCE, activeAssistant) putInt(PERSISTED_FOR_USER_PREFERENCE, activeUser) } if (config.isEnabled != isInvocationEffectEnabledInPreferences()) { putBoolean( IS_INVOCATION_EFFECT_ENABLED_BY_ASSISTANT_PREFERENCE, config.isEnabled, ) } if ( config.inwardsEffectDurationPadding != getInwardAnimationPaddingDurationMillis() ) { putLong( INVOCATION_EFFECT_ANIMATION_IN_DURATION_PADDING_MS, if (config.inwardsEffectDurationPadding in 0..1000) { config.inwardsEffectDurationPadding } else { DEFAULT_INWARD_EFFECT_PADDING_DURATION_MS }, ) } if (config.outwardsEffectDuration != getOutwardAnimationDurationMillis()) { putLong( INVOCATION_EFFECT_ANIMATION_OUT_DURATION_MS, if (config.outwardsEffectDuration in 100..1000) { config.outwardsEffectDuration } else { DEFAULT_OUTWARD_EFFECT_DURATION_MS }, ) } } } } private inline fun <reified T> getOrDefault( Loading packages/SystemUI/src/com/android/systemui/topwindoweffects/data/repository/SqueezeEffectRepositoryImpl.kt +43 −32 Original line number Diff line number Diff line Loading @@ -29,9 +29,6 @@ import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Application import com.android.systemui.dagger.qualifiers.Background import com.android.systemui.shared.Flags import com.android.systemui.topwindoweffects.data.repository.InvocationEffectPreferencesImpl.Companion.DEFAULT_INVOCATION_EFFECT_ENABLED_BY_ASSISTANT_PREFERENCE import com.android.systemui.topwindoweffects.data.repository.InvocationEffectPreferencesImpl.Companion.DEFAULT_INWARD_EFFECT_PADDING_DURATION_MS import com.android.systemui.topwindoweffects.data.repository.InvocationEffectPreferencesImpl.Companion.DEFAULT_OUTWARD_EFFECT_DURATION_MS import com.android.systemui.topwindoweffects.data.repository.InvocationEffectPreferencesImpl.Companion.INVOCATION_EFFECT_ANIMATION_IN_DURATION_PADDING_MS import com.android.systemui.topwindoweffects.data.repository.InvocationEffectPreferencesImpl.Companion.INVOCATION_EFFECT_ANIMATION_OUT_DURATION_MS import com.android.systemui.topwindoweffects.data.repository.InvocationEffectPreferencesImpl.Companion.IS_INVOCATION_EFFECT_ENABLED_BY_ASSISTANT_PREFERENCE Loading Loading @@ -91,43 +88,57 @@ constructor( return preferences.getOutwardAnimationDurationMillis() } private fun setInvocationEffectPreferences( isEnabled: Boolean? = null, inwardsEffectDurationPadding: Long? = null, outwardsEffectDuration: Long? = null, ) { preferences.setInvocationEffectConfig( config = InvocationEffectPreferences.Config( isEnabled = isEnabled ?: preferences.isInvocationEffectEnabledInPreferences(), inwardsEffectDurationPadding = inwardsEffectDurationPadding ?: preferences.getInwardAnimationPaddingDurationMillis(), outwardsEffectDuration = outwardsEffectDuration ?: preferences.getOutwardAnimationDurationMillis(), ), saveActiveUserAndAssistant = !preferences.isCurrentUserAndAssistantPersisted(), ) } override fun tryHandleSetUiHints(hints: Bundle): Boolean { return when (hints.getString(AssistManager.ACTION_KEY)) { SET_INVOCATION_EFFECT_PARAMETERS_ACTION -> { preferences.saveCurrentUserId() preferences.saveCurrentAssistant() val isEnabled: Boolean? = if (hints.containsKey(IS_INVOCATION_EFFECT_ENABLED_BY_ASSISTANT_PREFERENCE)) { preferences.setInvocationEffectEnabledByAssistant( hints.getBoolean(IS_INVOCATION_EFFECT_ENABLED_BY_ASSISTANT_PREFERENCE) ) } else { preferences.setInvocationEffectEnabledByAssistant( DEFAULT_INVOCATION_EFFECT_ENABLED_BY_ASSISTANT_PREFERENCE ) null } val inwardsEffectDurationPadding: Long? = if (hints.containsKey(INVOCATION_EFFECT_ANIMATION_IN_DURATION_PADDING_MS)) { preferences.setInwardAnimationPaddingDurationMillis( hints.getLong(INVOCATION_EFFECT_ANIMATION_IN_DURATION_PADDING_MS) ) } else { preferences.setInwardAnimationPaddingDurationMillis( DEFAULT_INWARD_EFFECT_PADDING_DURATION_MS ) null } val outwardsEffectDuration: Long? = if (hints.containsKey(INVOCATION_EFFECT_ANIMATION_OUT_DURATION_MS)) { preferences.setOutwardAnimationDurationMillis( hints.getLong(INVOCATION_EFFECT_ANIMATION_OUT_DURATION_MS) ) } else { preferences.setOutwardAnimationDurationMillis( DEFAULT_OUTWARD_EFFECT_DURATION_MS ) null } setInvocationEffectPreferences( isEnabled = isEnabled, inwardsEffectDurationPadding = inwardsEffectDurationPadding, outwardsEffectDuration = outwardsEffectDuration, ) true } else -> false Loading packages/SystemUI/tests/utils/src/com/android/systemui/topwindoweffects/data/repository/FakeInvocationEffectPreferences.kt +38 −24 Original line number Diff line number Diff line Loading @@ -19,10 +19,12 @@ package com.android.systemui.topwindoweffects.data.repository import android.content.SharedPreferences import androidx.core.content.edit import com.android.systemui.kosmos.Kosmos import com.android.systemui.topwindoweffects.data.repository.InvocationEffectPreferencesImpl.Companion.DEFAULT_INVOCATION_EFFECT_ENABLED_BY_ASSISTANT_PREFERENCE import com.android.systemui.topwindoweffects.data.repository.InvocationEffectPreferencesImpl.Companion.DEFAULT_INWARD_EFFECT_PADDING_DURATION_MS import com.android.systemui.topwindoweffects.data.repository.InvocationEffectPreferencesImpl.Companion.DEFAULT_OUTWARD_EFFECT_DURATION_MS import com.android.systemui.topwindoweffects.data.repository.InvocationEffectPreferencesImpl.Companion.INVOCATION_EFFECT_ANIMATION_IN_DURATION_PADDING_MS import com.android.systemui.topwindoweffects.data.repository.InvocationEffectPreferencesImpl.Companion.INVOCATION_EFFECT_ANIMATION_OUT_DURATION_MS import com.android.systemui.topwindoweffects.data.repository.InvocationEffectPreferencesImpl.Companion.IS_INVOCATION_EFFECT_ENABLED_BY_ASSISTANT_PREFERENCE import com.android.systemui.topwindoweffects.data.repository.InvocationEffectPreferencesImpl.Companion.PERSISTED_FOR_ASSISTANT_PREFERENCE import com.android.systemui.topwindoweffects.data.repository.InvocationEffectPreferencesImpl.Companion.PERSISTED_FOR_USER_PREFERENCE import java.io.PrintWriter Loading @@ -42,35 +44,23 @@ class FakeInvocationEffectPreferences : InvocationEffectPreferences { fakeSharedPreferences.edit { f() } } fun clear() { fakeSharedPreferences = FakeSharedPreferences() override fun isInvocationEffectEnabledInPreferences(): Boolean { return fakeSharedPreferences.getBoolean( IS_INVOCATION_EFFECT_ENABLED_BY_ASSISTANT_PREFERENCE, DEFAULT_INVOCATION_EFFECT_ENABLED_BY_ASSISTANT_PREFERENCE, ) } override fun saveCurrentAssistant() { addToPref { putString(PERSISTED_FOR_ASSISTANT_PREFERENCE, activeAssistant) } fun clear() { fakeSharedPreferences = FakeSharedPreferences() } fun getSavedAssistant(): String { return fakeSharedPreferences.getString(PERSISTED_FOR_ASSISTANT_PREFERENCE, "") ?: "" } override fun saveCurrentUserId() { addToPref { putInt(PERSISTED_FOR_USER_PREFERENCE, activeUserId) } } fun getSavedUserId(): Int { return fakeSharedPreferences.getInt(PERSISTED_FOR_USER_PREFERENCE, -1) } fun isActiveUserAndAssistantPersisted() = activeUserId == getSavedUserId() && activeAssistant == getSavedAssistant() override fun setInvocationEffectEnabledByAssistant(enabled: Boolean) { isInvocationEffectEnabledByAssistant.value = enabled } override fun setInwardAnimationPaddingDurationMillis(duration: Long) { addToPref { putLong(INVOCATION_EFFECT_ANIMATION_IN_DURATION_PADDING_MS, duration) } return fakeSharedPreferences.getInt(PERSISTED_FOR_USER_PREFERENCE, Int.MIN_VALUE) } override fun getInwardAnimationPaddingDurationMillis(): Long { Loading @@ -80,10 +70,6 @@ class FakeInvocationEffectPreferences : InvocationEffectPreferences { ) } override fun setOutwardAnimationDurationMillis(duration: Long) { addToPref { putLong(INVOCATION_EFFECT_ANIMATION_OUT_DURATION_MS, duration) } } override fun getOutwardAnimationDurationMillis(): Long { return fakeSharedPreferences.getLong( INVOCATION_EFFECT_ANIMATION_OUT_DURATION_MS, Loading @@ -91,6 +77,30 @@ class FakeInvocationEffectPreferences : InvocationEffectPreferences { ) } override fun isCurrentUserAndAssistantPersisted(): Boolean { return activeUserId == getSavedUserId() && activeAssistant == getSavedAssistant() } override fun setInvocationEffectConfig( config: InvocationEffectPreferences.Config, saveActiveUserAndAssistant: Boolean, ) { if (saveActiveUserAndAssistant) { addToPref { putString(PERSISTED_FOR_ASSISTANT_PREFERENCE, activeAssistant) putInt(PERSISTED_FOR_USER_PREFERENCE, activeUserId) } } addToPref { putLong(INVOCATION_EFFECT_ANIMATION_OUT_DURATION_MS, config.outwardsEffectDuration) putLong( INVOCATION_EFFECT_ANIMATION_IN_DURATION_PADDING_MS, config.inwardsEffectDurationPadding, ) putBoolean(IS_INVOCATION_EFFECT_ENABLED_BY_ASSISTANT_PREFERENCE, config.isEnabled) } } override fun registerOnChangeListener( listener: SharedPreferences.OnSharedPreferenceChangeListener ) { Loading @@ -106,6 +116,10 @@ class FakeInvocationEffectPreferences : InvocationEffectPreferences { override fun dump(pw: PrintWriter, args: Array<out String>) { // empty } fun setInvocationEffectEnabledByAssistant(enabled: Boolean) { isInvocationEffectEnabledByAssistant.value = enabled } } private class FakeSharedPreferences : SharedPreferences { Loading Loading
packages/SystemUI/multivalentTests/src/com/android/systemui/topwindoweffects/data/repository/SqueezeEffectRepositoryTest.kt +101 −15 Original line number Diff line number Diff line Loading @@ -32,6 +32,9 @@ import com.android.systemui.kosmos.testScope import com.android.systemui.kosmos.useUnconfinedTestDispatcher import com.android.systemui.shared.Flags import com.android.systemui.testKosmos import com.android.systemui.topwindoweffects.data.repository.InvocationEffectPreferencesImpl.Companion.DEFAULT_INVOCATION_EFFECT_ENABLED_BY_ASSISTANT_PREFERENCE import com.android.systemui.topwindoweffects.data.repository.InvocationEffectPreferencesImpl.Companion.DEFAULT_INWARD_EFFECT_PADDING_DURATION_MS import com.android.systemui.topwindoweffects.data.repository.InvocationEffectPreferencesImpl.Companion.DEFAULT_OUTWARD_EFFECT_DURATION_MS import com.android.systemui.topwindoweffects.data.repository.InvocationEffectPreferencesImpl.Companion.INVOCATION_EFFECT_ANIMATION_IN_DURATION_PADDING_MS import com.android.systemui.topwindoweffects.data.repository.InvocationEffectPreferencesImpl.Companion.INVOCATION_EFFECT_ANIMATION_OUT_DURATION_MS import com.android.systemui.topwindoweffects.data.repository.SqueezeEffectRepositoryImpl.Companion.IS_INVOCATION_EFFECT_ENABLED_KEY Loading Loading @@ -162,7 +165,14 @@ class SqueezeEffectRepositoryTest : SysuiTestCase() { @Test fun testInvocationEffectInwardsAnimationDelay() = kosmos.runTest { fakeInvocationEffectPreferences.setInwardAnimationPaddingDurationMillis(450) fakeInvocationEffectPreferences.setInvocationEffectConfig( InvocationEffectPreferences.Config( isEnabled = true, inwardsEffectDurationPadding = 450, outwardsEffectDuration = 400, ), true, ) assertThat(underTest.getInvocationEffectInAnimationDurationMillis()).isEqualTo(800) } Loading @@ -171,44 +181,120 @@ class SqueezeEffectRepositoryTest : SysuiTestCase() { @Test fun testInvocationEffectOutwardsAnimationDelay() = kosmos.runTest { fakeInvocationEffectPreferences.setOutwardAnimationDurationMillis(400) fakeInvocationEffectPreferences.setInvocationEffectConfig( InvocationEffectPreferences.Config( isEnabled = true, inwardsEffectDurationPadding = 450, outwardsEffectDuration = 400, ), true, ) assertThat(underTest.getInvocationEffectOutAnimationDurationMillis()).isEqualTo(400) } @EnableFlags(Flags.FLAG_ENABLE_LPP_ASSIST_INVOCATION_EFFECT) @Test fun testSetUiHintsShouldUpdatePreferences() = fun testSetUiHints_whenSuppliedAllConfigs_allUpdatedInPreferences() = kosmos.runTest { fakeInvocationEffectPreferences.activeUserId = 1 fakeInvocationEffectPreferences.activeAssistant = "A" assertThat(fakeInvocationEffectPreferences.isActiveUserAndAssistantPersisted()) assertThat(fakeInvocationEffectPreferences.isCurrentUserAndAssistantPersisted()) .isFalse() val hints = createAssistantSettingBundle(false, 0, 1000) val hints = createAssistantSettingBundle( enableAssistantSetting = false, inwardsPaddingDuration = 0, outwardsAnimationDuration = 1000, ) underTest.tryHandleSetUiHints(hints) val isEffectEnabledAndPowerButtonPressed by collectLastValue(underTest.isEffectEnabledAndPowerButtonPressedAsSingleGesture) assertThat(fakeInvocationEffectPreferences.getInwardAnimationPaddingDurationMillis()) .isEqualTo(0) assertThat(fakeInvocationEffectPreferences.getOutwardAnimationDurationMillis()) .isEqualTo(1000) assertThat(fakeInvocationEffectPreferences.isInvocationEffectEnabledInPreferences()) .isFalse() assertThat(fakeInvocationEffectPreferences.isCurrentUserAndAssistantPersisted()) .isTrue() } @EnableFlags(Flags.FLAG_ENABLE_LPP_ASSIST_INVOCATION_EFFECT) @Test fun testSetUiHints_whenSuppliedPartialConfig() = kosmos.runTest { fakeInvocationEffectPreferences.activeUserId = 1 fakeInvocationEffectPreferences.activeAssistant = "A" assertThat(fakeInvocationEffectPreferences.isCurrentUserAndAssistantPersisted()) .isFalse() underTest.tryHandleSetUiHints( createAssistantSettingBundle( enableAssistantSetting = false, inwardsPaddingDuration = 0, outwardsAnimationDuration = 1000, ) ) assertThat(isEffectEnabledAndPowerButtonPressed).isFalse() assertThat(fakeInvocationEffectPreferences.getInwardAnimationPaddingDurationMillis()) .isEqualTo(0) assertThat(fakeInvocationEffectPreferences.getOutwardAnimationDurationMillis()) .isEqualTo(1000) assertThat(fakeInvocationEffectPreferences.isActiveUserAndAssistantPersisted()).isTrue() assertThat(fakeInvocationEffectPreferences.isInvocationEffectEnabledInPreferences()) .isFalse() assertThat(fakeInvocationEffectPreferences.isCurrentUserAndAssistantPersisted()) .isTrue() underTest.tryHandleSetUiHints( createAssistantSettingBundle(enableAssistantSetting = true) ) assertThat(fakeInvocationEffectPreferences.getInwardAnimationPaddingDurationMillis()) .isEqualTo(0) assertThat(fakeInvocationEffectPreferences.getOutwardAnimationDurationMillis()) .isEqualTo(1000) assertThat(fakeInvocationEffectPreferences.isInvocationEffectEnabledInPreferences()) .isTrue() } @EnableFlags(Flags.FLAG_ENABLE_LPP_ASSIST_INVOCATION_EFFECT) @Test fun testSetUiHints_whenSuppliedNoConfig_shouldSetDefaults() = kosmos.runTest { fakeInvocationEffectPreferences.activeUserId = 1 fakeInvocationEffectPreferences.activeAssistant = "A" assertThat(fakeInvocationEffectPreferences.isCurrentUserAndAssistantPersisted()) .isFalse() underTest.tryHandleSetUiHints(createAssistantSettingBundle()) assertThat(fakeInvocationEffectPreferences.getInwardAnimationPaddingDurationMillis()) .isEqualTo(DEFAULT_INWARD_EFFECT_PADDING_DURATION_MS) assertThat(fakeInvocationEffectPreferences.getOutwardAnimationDurationMillis()) .isEqualTo(DEFAULT_OUTWARD_EFFECT_DURATION_MS) assertThat(fakeInvocationEffectPreferences.isInvocationEffectEnabledInPreferences()) .isEqualTo(DEFAULT_INVOCATION_EFFECT_ENABLED_BY_ASSISTANT_PREFERENCE) assertThat(fakeInvocationEffectPreferences.isCurrentUserAndAssistantPersisted()) .isTrue() } private fun createAssistantSettingBundle( enableAssistantSetting: Boolean, inwardsPaddingDuration: Long, outwardsAnimationDuration: Long, enableAssistantSetting: Boolean? = null, inwardsPaddingDuration: Long? = null, outwardsAnimationDuration: Long? = null, ) = Bundle().apply { putString(AssistManager.ACTION_KEY, SET_INVOCATION_EFFECT_PARAMETERS_ACTION) putBoolean(IS_INVOCATION_EFFECT_ENABLED_KEY, enableAssistantSetting) putLong(INVOCATION_EFFECT_ANIMATION_IN_DURATION_PADDING_MS, inwardsPaddingDuration) putLong(INVOCATION_EFFECT_ANIMATION_OUT_DURATION_MS, outwardsAnimationDuration) enableAssistantSetting?.let { putBoolean(IS_INVOCATION_EFFECT_ENABLED_KEY, it) } inwardsPaddingDuration?.let { putLong(INVOCATION_EFFECT_ANIMATION_IN_DURATION_PADDING_MS, it) } outwardsAnimationDuration?.let { putLong(INVOCATION_EFFECT_ANIMATION_OUT_DURATION_MS, it) } } }
packages/SystemUI/src/com/android/systemui/topwindoweffects/data/repository/InvocationEffectPreferences.kt +66 −60 Original line number Diff line number Diff line Loading @@ -51,25 +51,27 @@ interface InvocationEffectPreferences { val isInvocationEffectEnabledByAssistant: StateFlow<Boolean> fun saveCurrentAssistant() fun saveCurrentUserId() fun setInvocationEffectEnabledByAssistant(enabled: Boolean) fun setInwardAnimationPaddingDurationMillis(duration: Long) fun isInvocationEffectEnabledInPreferences(): Boolean fun getInwardAnimationPaddingDurationMillis(): Long fun setOutwardAnimationDurationMillis(duration: Long) fun getOutwardAnimationDurationMillis(): Long fun isCurrentUserAndAssistantPersisted(): Boolean fun setInvocationEffectConfig(config: Config, saveActiveUserAndAssistant: Boolean) fun registerOnChangeListener(listener: SharedPreferences.OnSharedPreferenceChangeListener) fun unregisterOnChangeListener(listener: SharedPreferences.OnSharedPreferenceChangeListener) fun dump(pw: PrintWriter, args: Array<out String>) data class Config( val isEnabled: Boolean, val inwardsEffectDurationPadding: Long, val outwardsEffectDuration: Long, ) } @SysUISingleton Loading @@ -81,7 +83,7 @@ constructor( private val userRepository: UserRepository, roleManager: RoleManager, @Background executor: Executor, @Background coroutineContext: CoroutineContext, @Background private val coroutineContext: CoroutineContext, ) : InvocationEffectPreferences { private val sharedPreferences by lazy { Loading Loading @@ -120,7 +122,8 @@ constructor( val changed = activeUser != userId || activeAssistant != assistant if (changed) { activeUser = userId activeAssistant = assistant activeAssistant = roleManager.getCurrentAssistantFor(userRepository.selectedUserHandle) } changed } Loading Loading @@ -152,10 +155,6 @@ constructor( initialValue = isInvocationEffectEnabledByAssistant(), ) override fun saveCurrentAssistant() { setInPreferences { putString(PERSISTED_FOR_ASSISTANT_PREFERENCE, activeAssistant) } } private fun getSavedAssistant(): String = getOrDefault<String>( key = PERSISTED_FOR_ASSISTANT_PREFERENCE, Loading @@ -163,10 +162,6 @@ constructor( checkUserAndAssistant = false, ) override fun saveCurrentUserId() { setInPreferences { putInt(PERSISTED_FOR_USER_PREFERENCE, activeUser) } } private fun getSavedUserId(): Int = getOrDefault<Int>( key = PERSISTED_FOR_USER_PREFERENCE, Loading @@ -174,31 +169,8 @@ constructor( checkUserAndAssistant = false, ) override fun setInvocationEffectEnabledByAssistant(enabled: Boolean) { setInPreferences { putBoolean(IS_INVOCATION_EFFECT_ENABLED_BY_ASSISTANT_PREFERENCE, enabled) } } private fun isInvocationEffectEnabledByAssistant(): Boolean = getOrDefault<Boolean>( key = IS_INVOCATION_EFFECT_ENABLED_BY_ASSISTANT_PREFERENCE, default = true, checkUserAndAssistant = true, ) && activeAssistant.isNotEmpty() override fun setInwardAnimationPaddingDurationMillis(duration: Long) { setInPreferences { if (duration in 0..1000) { putLong(INVOCATION_EFFECT_ANIMATION_IN_DURATION_PADDING_MS, duration) } else { putLong( INVOCATION_EFFECT_ANIMATION_IN_DURATION_PADDING_MS, DEFAULT_INWARD_EFFECT_PADDING_DURATION_MS, ) } } } isInvocationEffectEnabledInPreferences() && activeAssistant.isNotEmpty() override fun getInwardAnimationPaddingDurationMillis(): Long = getOrDefault<Long>( Loading @@ -207,20 +179,6 @@ constructor( checkUserAndAssistant = true, ) // TODO(b/418685731): Should we have a positive non-zero min value for out effect duration? override fun setOutwardAnimationDurationMillis(duration: Long) { setInPreferences { if (duration in 0..1000) { putLong(INVOCATION_EFFECT_ANIMATION_OUT_DURATION_MS, duration) } else { putLong( INVOCATION_EFFECT_ANIMATION_OUT_DURATION_MS, DEFAULT_OUTWARD_EFFECT_DURATION_MS, ) } } } override fun getOutwardAnimationDurationMillis(): Long = getOrDefault<Long>( key = INVOCATION_EFFECT_ANIMATION_OUT_DURATION_MS, Loading @@ -228,11 +186,59 @@ constructor( checkUserAndAssistant = true, ) private fun isCurrentUserAndAssistantPersisted(): Boolean = override fun isCurrentUserAndAssistantPersisted(): Boolean = activeUser == getSavedUserId() && activeAssistant == getSavedAssistant() private fun setInPreferences(block: SharedPreferences.Editor.() -> Unit) { bgScope.launch { sharedPreferences.edit { block() } } override fun isInvocationEffectEnabledInPreferences(): Boolean = getOrDefault<Boolean>( key = IS_INVOCATION_EFFECT_ENABLED_BY_ASSISTANT_PREFERENCE, default = DEFAULT_INVOCATION_EFFECT_ENABLED_BY_ASSISTANT_PREFERENCE, checkUserAndAssistant = true, ) override fun setInvocationEffectConfig( config: InvocationEffectPreferences.Config, saveActiveUserAndAssistant: Boolean, ) { bgScope.launch(context = coroutineContext) { sharedPreferences.edit { if (saveActiveUserAndAssistant) { putString(PERSISTED_FOR_ASSISTANT_PREFERENCE, activeAssistant) putInt(PERSISTED_FOR_USER_PREFERENCE, activeUser) } if (config.isEnabled != isInvocationEffectEnabledInPreferences()) { putBoolean( IS_INVOCATION_EFFECT_ENABLED_BY_ASSISTANT_PREFERENCE, config.isEnabled, ) } if ( config.inwardsEffectDurationPadding != getInwardAnimationPaddingDurationMillis() ) { putLong( INVOCATION_EFFECT_ANIMATION_IN_DURATION_PADDING_MS, if (config.inwardsEffectDurationPadding in 0..1000) { config.inwardsEffectDurationPadding } else { DEFAULT_INWARD_EFFECT_PADDING_DURATION_MS }, ) } if (config.outwardsEffectDuration != getOutwardAnimationDurationMillis()) { putLong( INVOCATION_EFFECT_ANIMATION_OUT_DURATION_MS, if (config.outwardsEffectDuration in 100..1000) { config.outwardsEffectDuration } else { DEFAULT_OUTWARD_EFFECT_DURATION_MS }, ) } } } } private inline fun <reified T> getOrDefault( Loading
packages/SystemUI/src/com/android/systemui/topwindoweffects/data/repository/SqueezeEffectRepositoryImpl.kt +43 −32 Original line number Diff line number Diff line Loading @@ -29,9 +29,6 @@ import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Application import com.android.systemui.dagger.qualifiers.Background import com.android.systemui.shared.Flags import com.android.systemui.topwindoweffects.data.repository.InvocationEffectPreferencesImpl.Companion.DEFAULT_INVOCATION_EFFECT_ENABLED_BY_ASSISTANT_PREFERENCE import com.android.systemui.topwindoweffects.data.repository.InvocationEffectPreferencesImpl.Companion.DEFAULT_INWARD_EFFECT_PADDING_DURATION_MS import com.android.systemui.topwindoweffects.data.repository.InvocationEffectPreferencesImpl.Companion.DEFAULT_OUTWARD_EFFECT_DURATION_MS import com.android.systemui.topwindoweffects.data.repository.InvocationEffectPreferencesImpl.Companion.INVOCATION_EFFECT_ANIMATION_IN_DURATION_PADDING_MS import com.android.systemui.topwindoweffects.data.repository.InvocationEffectPreferencesImpl.Companion.INVOCATION_EFFECT_ANIMATION_OUT_DURATION_MS import com.android.systemui.topwindoweffects.data.repository.InvocationEffectPreferencesImpl.Companion.IS_INVOCATION_EFFECT_ENABLED_BY_ASSISTANT_PREFERENCE Loading Loading @@ -91,43 +88,57 @@ constructor( return preferences.getOutwardAnimationDurationMillis() } private fun setInvocationEffectPreferences( isEnabled: Boolean? = null, inwardsEffectDurationPadding: Long? = null, outwardsEffectDuration: Long? = null, ) { preferences.setInvocationEffectConfig( config = InvocationEffectPreferences.Config( isEnabled = isEnabled ?: preferences.isInvocationEffectEnabledInPreferences(), inwardsEffectDurationPadding = inwardsEffectDurationPadding ?: preferences.getInwardAnimationPaddingDurationMillis(), outwardsEffectDuration = outwardsEffectDuration ?: preferences.getOutwardAnimationDurationMillis(), ), saveActiveUserAndAssistant = !preferences.isCurrentUserAndAssistantPersisted(), ) } override fun tryHandleSetUiHints(hints: Bundle): Boolean { return when (hints.getString(AssistManager.ACTION_KEY)) { SET_INVOCATION_EFFECT_PARAMETERS_ACTION -> { preferences.saveCurrentUserId() preferences.saveCurrentAssistant() val isEnabled: Boolean? = if (hints.containsKey(IS_INVOCATION_EFFECT_ENABLED_BY_ASSISTANT_PREFERENCE)) { preferences.setInvocationEffectEnabledByAssistant( hints.getBoolean(IS_INVOCATION_EFFECT_ENABLED_BY_ASSISTANT_PREFERENCE) ) } else { preferences.setInvocationEffectEnabledByAssistant( DEFAULT_INVOCATION_EFFECT_ENABLED_BY_ASSISTANT_PREFERENCE ) null } val inwardsEffectDurationPadding: Long? = if (hints.containsKey(INVOCATION_EFFECT_ANIMATION_IN_DURATION_PADDING_MS)) { preferences.setInwardAnimationPaddingDurationMillis( hints.getLong(INVOCATION_EFFECT_ANIMATION_IN_DURATION_PADDING_MS) ) } else { preferences.setInwardAnimationPaddingDurationMillis( DEFAULT_INWARD_EFFECT_PADDING_DURATION_MS ) null } val outwardsEffectDuration: Long? = if (hints.containsKey(INVOCATION_EFFECT_ANIMATION_OUT_DURATION_MS)) { preferences.setOutwardAnimationDurationMillis( hints.getLong(INVOCATION_EFFECT_ANIMATION_OUT_DURATION_MS) ) } else { preferences.setOutwardAnimationDurationMillis( DEFAULT_OUTWARD_EFFECT_DURATION_MS ) null } setInvocationEffectPreferences( isEnabled = isEnabled, inwardsEffectDurationPadding = inwardsEffectDurationPadding, outwardsEffectDuration = outwardsEffectDuration, ) true } else -> false Loading
packages/SystemUI/tests/utils/src/com/android/systemui/topwindoweffects/data/repository/FakeInvocationEffectPreferences.kt +38 −24 Original line number Diff line number Diff line Loading @@ -19,10 +19,12 @@ package com.android.systemui.topwindoweffects.data.repository import android.content.SharedPreferences import androidx.core.content.edit import com.android.systemui.kosmos.Kosmos import com.android.systemui.topwindoweffects.data.repository.InvocationEffectPreferencesImpl.Companion.DEFAULT_INVOCATION_EFFECT_ENABLED_BY_ASSISTANT_PREFERENCE import com.android.systemui.topwindoweffects.data.repository.InvocationEffectPreferencesImpl.Companion.DEFAULT_INWARD_EFFECT_PADDING_DURATION_MS import com.android.systemui.topwindoweffects.data.repository.InvocationEffectPreferencesImpl.Companion.DEFAULT_OUTWARD_EFFECT_DURATION_MS import com.android.systemui.topwindoweffects.data.repository.InvocationEffectPreferencesImpl.Companion.INVOCATION_EFFECT_ANIMATION_IN_DURATION_PADDING_MS import com.android.systemui.topwindoweffects.data.repository.InvocationEffectPreferencesImpl.Companion.INVOCATION_EFFECT_ANIMATION_OUT_DURATION_MS import com.android.systemui.topwindoweffects.data.repository.InvocationEffectPreferencesImpl.Companion.IS_INVOCATION_EFFECT_ENABLED_BY_ASSISTANT_PREFERENCE import com.android.systemui.topwindoweffects.data.repository.InvocationEffectPreferencesImpl.Companion.PERSISTED_FOR_ASSISTANT_PREFERENCE import com.android.systemui.topwindoweffects.data.repository.InvocationEffectPreferencesImpl.Companion.PERSISTED_FOR_USER_PREFERENCE import java.io.PrintWriter Loading @@ -42,35 +44,23 @@ class FakeInvocationEffectPreferences : InvocationEffectPreferences { fakeSharedPreferences.edit { f() } } fun clear() { fakeSharedPreferences = FakeSharedPreferences() override fun isInvocationEffectEnabledInPreferences(): Boolean { return fakeSharedPreferences.getBoolean( IS_INVOCATION_EFFECT_ENABLED_BY_ASSISTANT_PREFERENCE, DEFAULT_INVOCATION_EFFECT_ENABLED_BY_ASSISTANT_PREFERENCE, ) } override fun saveCurrentAssistant() { addToPref { putString(PERSISTED_FOR_ASSISTANT_PREFERENCE, activeAssistant) } fun clear() { fakeSharedPreferences = FakeSharedPreferences() } fun getSavedAssistant(): String { return fakeSharedPreferences.getString(PERSISTED_FOR_ASSISTANT_PREFERENCE, "") ?: "" } override fun saveCurrentUserId() { addToPref { putInt(PERSISTED_FOR_USER_PREFERENCE, activeUserId) } } fun getSavedUserId(): Int { return fakeSharedPreferences.getInt(PERSISTED_FOR_USER_PREFERENCE, -1) } fun isActiveUserAndAssistantPersisted() = activeUserId == getSavedUserId() && activeAssistant == getSavedAssistant() override fun setInvocationEffectEnabledByAssistant(enabled: Boolean) { isInvocationEffectEnabledByAssistant.value = enabled } override fun setInwardAnimationPaddingDurationMillis(duration: Long) { addToPref { putLong(INVOCATION_EFFECT_ANIMATION_IN_DURATION_PADDING_MS, duration) } return fakeSharedPreferences.getInt(PERSISTED_FOR_USER_PREFERENCE, Int.MIN_VALUE) } override fun getInwardAnimationPaddingDurationMillis(): Long { Loading @@ -80,10 +70,6 @@ class FakeInvocationEffectPreferences : InvocationEffectPreferences { ) } override fun setOutwardAnimationDurationMillis(duration: Long) { addToPref { putLong(INVOCATION_EFFECT_ANIMATION_OUT_DURATION_MS, duration) } } override fun getOutwardAnimationDurationMillis(): Long { return fakeSharedPreferences.getLong( INVOCATION_EFFECT_ANIMATION_OUT_DURATION_MS, Loading @@ -91,6 +77,30 @@ class FakeInvocationEffectPreferences : InvocationEffectPreferences { ) } override fun isCurrentUserAndAssistantPersisted(): Boolean { return activeUserId == getSavedUserId() && activeAssistant == getSavedAssistant() } override fun setInvocationEffectConfig( config: InvocationEffectPreferences.Config, saveActiveUserAndAssistant: Boolean, ) { if (saveActiveUserAndAssistant) { addToPref { putString(PERSISTED_FOR_ASSISTANT_PREFERENCE, activeAssistant) putInt(PERSISTED_FOR_USER_PREFERENCE, activeUserId) } } addToPref { putLong(INVOCATION_EFFECT_ANIMATION_OUT_DURATION_MS, config.outwardsEffectDuration) putLong( INVOCATION_EFFECT_ANIMATION_IN_DURATION_PADDING_MS, config.inwardsEffectDurationPadding, ) putBoolean(IS_INVOCATION_EFFECT_ENABLED_BY_ASSISTANT_PREFERENCE, config.isEnabled) } } override fun registerOnChangeListener( listener: SharedPreferences.OnSharedPreferenceChangeListener ) { Loading @@ -106,6 +116,10 @@ class FakeInvocationEffectPreferences : InvocationEffectPreferences { override fun dump(pw: PrintWriter, args: Array<out String>) { // empty } fun setInvocationEffectEnabledByAssistant(enabled: Boolean) { isInvocationEffectEnabledByAssistant.value = enabled } } private class FakeSharedPreferences : SharedPreferences { Loading