Merge "Long-press to configure quick affordances (1/2)." into tm-qpr-dev

This commit is contained in:
Ale Nijamkin
2023-01-13 04:20:47 +00:00
committed by Android (Google) Code Review
14 changed files with 281 additions and 190 deletions

View File

@@ -20,12 +20,15 @@ package com.android.systemui.shared.customization.data.content
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.content.ContentValues import android.content.ContentValues
import android.content.Context import android.content.Context
import android.content.Intent
import android.database.ContentObserver import android.database.ContentObserver
import android.graphics.Color import android.graphics.Color
import android.graphics.drawable.Drawable import android.graphics.drawable.Drawable
import android.net.Uri import android.net.Uri
import android.util.Log
import androidx.annotation.DrawableRes import androidx.annotation.DrawableRes
import com.android.systemui.shared.customization.data.content.CustomizationProviderContract as Contract import com.android.systemui.shared.customization.data.content.CustomizationProviderContract as Contract
import java.net.URISyntaxException
import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.channels.awaitClose import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
@@ -169,6 +172,8 @@ interface CustomizationProviderClient {
* If `null`, the button should not be shown. * If `null`, the button should not be shown.
*/ */
val enablementActionComponentName: String? = null, val enablementActionComponentName: String? = null,
/** Optional [Intent] to use to start an activity to configure this affordance. */
val configureIntent: Intent? = null,
) )
/** Models a selection of a quick affordance on a slot. */ /** Models a selection of a quick affordance on a slot. */
@@ -337,6 +342,11 @@ class CustomizationProviderClientImpl(
Contract.LockScreenQuickAffordances.AffordanceTable.Columns Contract.LockScreenQuickAffordances.AffordanceTable.Columns
.ENABLEMENT_COMPONENT_NAME .ENABLEMENT_COMPONENT_NAME
) )
val configureIntentColumnIndex =
cursor.getColumnIndex(
Contract.LockScreenQuickAffordances.AffordanceTable.Columns
.CONFIGURE_INTENT
)
if ( if (
idColumnIndex == -1 || idColumnIndex == -1 ||
nameColumnIndex == -1 || nameColumnIndex == -1 ||
@@ -344,15 +354,17 @@ class CustomizationProviderClientImpl(
isEnabledColumnIndex == -1 || isEnabledColumnIndex == -1 ||
enablementInstructionsColumnIndex == -1 || enablementInstructionsColumnIndex == -1 ||
enablementActionTextColumnIndex == -1 || enablementActionTextColumnIndex == -1 ||
enablementComponentNameColumnIndex == -1 enablementComponentNameColumnIndex == -1 ||
configureIntentColumnIndex == -1
) { ) {
return@buildList return@buildList
} }
while (cursor.moveToNext()) { while (cursor.moveToNext()) {
val affordanceId = cursor.getString(idColumnIndex)
add( add(
CustomizationProviderClient.Affordance( CustomizationProviderClient.Affordance(
id = cursor.getString(idColumnIndex), id = affordanceId,
name = cursor.getString(nameColumnIndex), name = cursor.getString(nameColumnIndex),
iconResourceId = cursor.getInt(iconColumnIndex), iconResourceId = cursor.getInt(iconColumnIndex),
isEnabled = cursor.getInt(isEnabledColumnIndex) == 1, isEnabled = cursor.getInt(isEnabledColumnIndex) == 1,
@@ -367,6 +379,10 @@ class CustomizationProviderClientImpl(
cursor.getString(enablementActionTextColumnIndex), cursor.getString(enablementActionTextColumnIndex),
enablementActionComponentName = enablementActionComponentName =
cursor.getString(enablementComponentNameColumnIndex), cursor.getString(enablementComponentNameColumnIndex),
configureIntent =
cursor
.getString(configureIntentColumnIndex)
?.toIntent(affordanceId = affordanceId),
) )
) )
} }
@@ -504,7 +520,19 @@ class CustomizationProviderClientImpl(
.onStart { emit(Unit) } .onStart { emit(Unit) }
} }
private fun String.toIntent(
affordanceId: String,
): Intent? {
return try {
Intent.parseUri(this, 0)
} catch (e: URISyntaxException) {
Log.w(TAG, "Cannot parse Uri into Intent for affordance with ID \"$affordanceId\"!")
null
}
}
companion object { companion object {
private const val TAG = "CustomizationProviderClient"
private const val SYSTEM_UI_PACKAGE_NAME = "com.android.systemui" private const val SYSTEM_UI_PACKAGE_NAME = "com.android.systemui"
} }
} }

View File

@@ -113,6 +113,11 @@ object CustomizationProviderContract {
* opens a destination where the user can re-enable the disabled affordance. * opens a destination where the user can re-enable the disabled affordance.
*/ */
const val ENABLEMENT_COMPONENT_NAME = "enablement_action_intent" const val ENABLEMENT_COMPONENT_NAME = "enablement_action_intent"
/**
* Byte array. Optional parcelled `Intent` to use to start an activity that can be
* used to configure the affordance.
*/
const val CONFIGURE_INTENT = "configure_intent"
} }
} }

View File

@@ -282,6 +282,7 @@ class CustomizationProvider :
.ENABLEMENT_ACTION_TEXT, .ENABLEMENT_ACTION_TEXT,
Contract.LockScreenQuickAffordances.AffordanceTable.Columns Contract.LockScreenQuickAffordances.AffordanceTable.Columns
.ENABLEMENT_COMPONENT_NAME, .ENABLEMENT_COMPONENT_NAME,
Contract.LockScreenQuickAffordances.AffordanceTable.Columns.CONFIGURE_INTENT,
) )
) )
.apply { .apply {
@@ -298,6 +299,7 @@ class CustomizationProvider :
), ),
representation.actionText, representation.actionText,
representation.actionComponentName, representation.actionComponentName,
representation.configureIntent?.toUri(0),
) )
) )
} }

View File

@@ -17,6 +17,7 @@
package com.android.systemui.keyguard.data.quickaffordance package com.android.systemui.keyguard.data.quickaffordance
import android.content.Context import android.content.Context
import android.content.Intent
import android.net.Uri import android.net.Uri
import android.provider.Settings import android.provider.Settings
import android.provider.Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS import android.provider.Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS
@@ -39,6 +40,7 @@ import com.android.systemui.settings.UserTracker
import com.android.systemui.statusbar.policy.ZenModeController import com.android.systemui.statusbar.policy.ZenModeController
import com.android.systemui.util.settings.SecureSettings import com.android.systemui.util.settings.SecureSettings
import com.android.systemui.util.settings.SettingsProxyExt.observerFlow import com.android.systemui.util.settings.SettingsProxyExt.observerFlow
import javax.inject.Inject
import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.channels.awaitClose import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
@@ -48,10 +50,10 @@ import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.onStart import kotlinx.coroutines.flow.onStart
import javax.inject.Inject
@SysUISingleton @SysUISingleton
class DoNotDisturbQuickAffordanceConfig constructor( class DoNotDisturbQuickAffordanceConfig
constructor(
private val context: Context, private val context: Context,
private val controller: ZenModeController, private val controller: ZenModeController,
private val secureSettings: SecureSettings, private val secureSettings: SecureSettings,
@@ -59,7 +61,7 @@ class DoNotDisturbQuickAffordanceConfig constructor(
@Background private val backgroundDispatcher: CoroutineDispatcher, @Background private val backgroundDispatcher: CoroutineDispatcher,
private val testConditionId: Uri?, private val testConditionId: Uri?,
testDialog: EnableZenModeDialog?, testDialog: EnableZenModeDialog?,
): KeyguardQuickAffordanceConfig { ) : KeyguardQuickAffordanceConfig {
@Inject @Inject
constructor( constructor(
@@ -76,20 +78,23 @@ class DoNotDisturbQuickAffordanceConfig constructor(
private val conditionUri: Uri private val conditionUri: Uri
get() = get() =
testConditionId ?: ZenModeConfig.toTimeCondition( testConditionId
context, ?: ZenModeConfig.toTimeCondition(
settingsValue, context,
userTracker.userId, settingsValue,
true, /* shortVersion */ userTracker.userId,
).id true, /* shortVersion */
)
.id
private val dialog: EnableZenModeDialog by lazy { private val dialog: EnableZenModeDialog by lazy {
testDialog ?: EnableZenModeDialog( testDialog
context, ?: EnableZenModeDialog(
R.style.Theme_SystemUI_Dialog, context,
true, /* cancelIsNeutral */ R.style.Theme_SystemUI_Dialog,
ZenModeDialogMetricsLogger(context), true, /* cancelIsNeutral */
) ZenModeDialogMetricsLogger(context),
)
} }
override val key: String = BuiltInKeyguardQuickAffordanceKeys.DO_NOT_DISTURB override val key: String = BuiltInKeyguardQuickAffordanceKeys.DO_NOT_DISTURB
@@ -98,58 +103,62 @@ class DoNotDisturbQuickAffordanceConfig constructor(
override val pickerIconResourceId: Int = R.drawable.ic_do_not_disturb override val pickerIconResourceId: Int = R.drawable.ic_do_not_disturb
override val lockScreenState: Flow<KeyguardQuickAffordanceConfig.LockScreenState> = combine( override val lockScreenState: Flow<KeyguardQuickAffordanceConfig.LockScreenState> =
conflatedCallbackFlow { combine(
val callback = object: ZenModeController.Callback { conflatedCallbackFlow {
override fun onZenChanged(zen: Int) { val callback =
dndMode = zen object : ZenModeController.Callback {
trySendWithFailureLogging(updateState(), TAG) override fun onZenChanged(zen: Int) {
} dndMode = zen
trySendWithFailureLogging(updateState(), TAG)
}
override fun onZenAvailableChanged(available: Boolean) { override fun onZenAvailableChanged(available: Boolean) {
isAvailable = available isAvailable = available
trySendWithFailureLogging(updateState(), TAG) trySendWithFailureLogging(updateState(), TAG)
} }
} }
dndMode = controller.zen dndMode = controller.zen
isAvailable = controller.isZenAvailable isAvailable = controller.isZenAvailable
trySendWithFailureLogging(updateState(), TAG) trySendWithFailureLogging(updateState(), TAG)
controller.addCallback(callback) controller.addCallback(callback)
awaitClose { controller.removeCallback(callback) } awaitClose { controller.removeCallback(callback) }
}, },
secureSettings secureSettings
.observerFlow(Settings.Secure.ZEN_DURATION) .observerFlow(Settings.Secure.ZEN_DURATION)
.onStart { emit(Unit) } .onStart { emit(Unit) }
.map { secureSettings.getInt(Settings.Secure.ZEN_DURATION, ZEN_MODE_OFF) } .map { secureSettings.getInt(Settings.Secure.ZEN_DURATION, ZEN_MODE_OFF) }
.flowOn(backgroundDispatcher) .flowOn(backgroundDispatcher)
.distinctUntilChanged() .distinctUntilChanged()
.onEach { settingsValue = it } .onEach { settingsValue = it }
) { callbackFlowValue, _ -> callbackFlowValue } ) { callbackFlowValue, _ -> callbackFlowValue }
override suspend fun getPickerScreenState(): KeyguardQuickAffordanceConfig.PickerScreenState { override suspend fun getPickerScreenState(): KeyguardQuickAffordanceConfig.PickerScreenState {
return if (controller.isZenAvailable) { return if (controller.isZenAvailable) {
KeyguardQuickAffordanceConfig.PickerScreenState.Default KeyguardQuickAffordanceConfig.PickerScreenState.Default(
configureIntent = Intent(Settings.ACTION_ZEN_MODE_SETTINGS)
)
} else { } else {
KeyguardQuickAffordanceConfig.PickerScreenState.UnavailableOnDevice KeyguardQuickAffordanceConfig.PickerScreenState.UnavailableOnDevice
} }
} }
override fun onTriggered(expandable: Expandable?): override fun onTriggered(
KeyguardQuickAffordanceConfig.OnTriggeredResult { expandable: Expandable?
): KeyguardQuickAffordanceConfig.OnTriggeredResult {
return when { return when {
!isAvailable -> !isAvailable -> KeyguardQuickAffordanceConfig.OnTriggeredResult.Handled
KeyguardQuickAffordanceConfig.OnTriggeredResult.Handled
dndMode != ZEN_MODE_OFF -> { dndMode != ZEN_MODE_OFF -> {
controller.setZen(ZEN_MODE_OFF, null, TAG) controller.setZen(ZEN_MODE_OFF, null, TAG)
KeyguardQuickAffordanceConfig.OnTriggeredResult.Handled KeyguardQuickAffordanceConfig.OnTriggeredResult.Handled
} }
settingsValue == ZEN_DURATION_PROMPT -> settingsValue == ZEN_DURATION_PROMPT ->
KeyguardQuickAffordanceConfig.OnTriggeredResult.ShowDialog( KeyguardQuickAffordanceConfig.OnTriggeredResult.ShowDialog(
dialog.createDialog(), dialog.createDialog(),
expandable expandable
) )
settingsValue == ZEN_DURATION_FOREVER -> { settingsValue == ZEN_DURATION_FOREVER -> {
controller.setZen(ZEN_MODE_IMPORTANT_INTERRUPTIONS, null, TAG) controller.setZen(ZEN_MODE_IMPORTANT_INTERRUPTIONS, null, TAG)
@@ -187,4 +196,4 @@ class DoNotDisturbQuickAffordanceConfig constructor(
companion object { companion object {
const val TAG = "DoNotDisturbQuickAffordanceConfig" const val TAG = "DoNotDisturbQuickAffordanceConfig"
} }
} }

View File

@@ -135,7 +135,7 @@ constructor(
override suspend fun getPickerScreenState(): KeyguardQuickAffordanceConfig.PickerScreenState = override suspend fun getPickerScreenState(): KeyguardQuickAffordanceConfig.PickerScreenState =
if (flashlightController.isAvailable) { if (flashlightController.isAvailable) {
KeyguardQuickAffordanceConfig.PickerScreenState.Default KeyguardQuickAffordanceConfig.PickerScreenState.Default()
} else { } else {
KeyguardQuickAffordanceConfig.PickerScreenState.UnavailableOnDevice KeyguardQuickAffordanceConfig.PickerScreenState.UnavailableOnDevice
} }

View File

@@ -90,7 +90,7 @@ constructor(
) )
} }
return KeyguardQuickAffordanceConfig.PickerScreenState.Default return KeyguardQuickAffordanceConfig.PickerScreenState.Default()
} }
override fun onTriggered( override fun onTriggered(

View File

@@ -46,7 +46,7 @@ interface KeyguardQuickAffordanceConfig {
* Returns the [PickerScreenState] representing the affordance in the settings or selector * Returns the [PickerScreenState] representing the affordance in the settings or selector
* experience. * experience.
*/ */
suspend fun getPickerScreenState(): PickerScreenState = PickerScreenState.Default suspend fun getPickerScreenState(): PickerScreenState = PickerScreenState.Default()
/** /**
* Notifies that the affordance was clicked by the user. * Notifies that the affordance was clicked by the user.
@@ -63,7 +63,10 @@ interface KeyguardQuickAffordanceConfig {
sealed class PickerScreenState { sealed class PickerScreenState {
/** The picker shows the item for selecting this affordance as it normally would. */ /** The picker shows the item for selecting this affordance as it normally would. */
object Default : PickerScreenState() data class Default(
/** Optional [Intent] to use to start an activity to configure this affordance. */
val configureIntent: Intent? = null,
) : PickerScreenState()
/** /**
* The picker does not show an item for selecting this affordance as it is not supported on * The picker does not show an item for selecting this affordance as it is not supported on

View File

@@ -89,7 +89,7 @@ constructor(
), ),
), ),
) )
else -> KeyguardQuickAffordanceConfig.PickerScreenState.Default else -> KeyguardQuickAffordanceConfig.PickerScreenState.Default()
} }
} }

View File

@@ -128,7 +128,7 @@ constructor(
actionComponentName = componentName, actionComponentName = componentName,
) )
} }
else -> KeyguardQuickAffordanceConfig.PickerScreenState.Default else -> KeyguardQuickAffordanceConfig.PickerScreenState.Default()
} }
} }

View File

@@ -187,6 +187,8 @@ constructor(
pickerState is KeyguardQuickAffordanceConfig.PickerScreenState.UnavailableOnDevice pickerState is KeyguardQuickAffordanceConfig.PickerScreenState.UnavailableOnDevice
} }
.map { (config, pickerState) -> .map { (config, pickerState) ->
val defaultPickerState =
pickerState as? KeyguardQuickAffordanceConfig.PickerScreenState.Default
val disabledPickerState = val disabledPickerState =
pickerState as? KeyguardQuickAffordanceConfig.PickerScreenState.Disabled pickerState as? KeyguardQuickAffordanceConfig.PickerScreenState.Disabled
KeyguardQuickAffordancePickerRepresentation( KeyguardQuickAffordancePickerRepresentation(
@@ -198,6 +200,7 @@ constructor(
instructions = disabledPickerState?.instructions, instructions = disabledPickerState?.instructions,
actionText = disabledPickerState?.actionText, actionText = disabledPickerState?.actionText,
actionComponentName = disabledPickerState?.actionComponentName, actionComponentName = disabledPickerState?.actionComponentName,
configureIntent = defaultPickerState?.configureIntent,
) )
} }
} }

View File

@@ -17,6 +17,7 @@
package com.android.systemui.keyguard.shared.model package com.android.systemui.keyguard.shared.model
import android.content.Intent
import androidx.annotation.DrawableRes import androidx.annotation.DrawableRes
/** /**
@@ -45,4 +46,7 @@ data class KeyguardQuickAffordancePickerRepresentation(
* user to a destination where they can re-enable it. * user to a destination where they can re-enable it.
*/ */
val actionComponentName: String? = null, val actionComponentName: String? = null,
/** Optional [Intent] to use to start an activity to configure this affordance. */
val configureIntent: Intent? = null,
) )

View File

@@ -38,6 +38,7 @@ import com.android.systemui.util.mockito.eq
import com.android.systemui.util.mockito.mock import com.android.systemui.util.mockito.mock
import com.android.systemui.util.mockito.whenever import com.android.systemui.util.mockito.whenever
import com.android.systemui.util.settings.FakeSettings import com.android.systemui.util.settings.FakeSettings
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.StandardTestDispatcher import kotlinx.coroutines.test.StandardTestDispatcher
import kotlinx.coroutines.test.TestDispatcher import kotlinx.coroutines.test.TestDispatcher
@@ -83,169 +84,205 @@ class DoNotDisturbQuickAffordanceConfigTest : SysuiTestCase() {
settings = FakeSettings() settings = FakeSettings()
underTest = DoNotDisturbQuickAffordanceConfig( underTest =
context, DoNotDisturbQuickAffordanceConfig(
zenModeController, context,
settings, zenModeController,
userTracker, settings,
testDispatcher, userTracker,
conditionUri, testDispatcher,
enableZenModeDialog, conditionUri,
) enableZenModeDialog,
)
} }
@Test @Test
fun `dnd not available - picker state hidden`() = testScope.runTest { fun `dnd not available - picker state hidden`() =
//given testScope.runTest {
whenever(zenModeController.isZenAvailable).thenReturn(false) // given
whenever(zenModeController.isZenAvailable).thenReturn(false)
//when // when
val result = underTest.getPickerScreenState() val result = underTest.getPickerScreenState()
//then // then
assertEquals(KeyguardQuickAffordanceConfig.PickerScreenState.UnavailableOnDevice, result) assertEquals(
} KeyguardQuickAffordanceConfig.PickerScreenState.UnavailableOnDevice,
result
)
}
@Test @Test
fun `dnd available - picker state visible`() = testScope.runTest { fun `dnd available - picker state visible`() =
//given testScope.runTest {
whenever(zenModeController.isZenAvailable).thenReturn(true) // given
whenever(zenModeController.isZenAvailable).thenReturn(true)
//when // when
val result = underTest.getPickerScreenState() val result = underTest.getPickerScreenState()
//then // then
assertEquals(KeyguardQuickAffordanceConfig.PickerScreenState.Default, result) assertThat(result)
} .isInstanceOf(KeyguardQuickAffordanceConfig.PickerScreenState.Default::class.java)
val defaultPickerState =
result as KeyguardQuickAffordanceConfig.PickerScreenState.Default
assertThat(defaultPickerState.configureIntent).isNotNull()
assertThat(defaultPickerState.configureIntent?.action)
.isEqualTo(Settings.ACTION_ZEN_MODE_SETTINGS)
}
@Test @Test
fun `onTriggered - dnd mode is not ZEN_MODE_OFF - set to ZEN_MODE_OFF`() = testScope.runTest { fun `onTriggered - dnd mode is not ZEN_MODE_OFF - set to ZEN_MODE_OFF`() =
//given testScope.runTest {
whenever(zenModeController.isZenAvailable).thenReturn(true) // given
whenever(zenModeController.zen).thenReturn(-1) whenever(zenModeController.isZenAvailable).thenReturn(true)
settings.putInt(Settings.Secure.ZEN_DURATION, -2) whenever(zenModeController.zen).thenReturn(-1)
collectLastValue(underTest.lockScreenState) settings.putInt(Settings.Secure.ZEN_DURATION, -2)
runCurrent() collectLastValue(underTest.lockScreenState)
runCurrent()
//when // when
val result = underTest.onTriggered(null) val result = underTest.onTriggered(null)
verify(zenModeController).setZen(spyZenMode.capture(), spyConditionId.capture(), eq(DoNotDisturbQuickAffordanceConfig.TAG)) verify(zenModeController)
.setZen(
spyZenMode.capture(),
spyConditionId.capture(),
eq(DoNotDisturbQuickAffordanceConfig.TAG)
)
//then // then
assertEquals(KeyguardQuickAffordanceConfig.OnTriggeredResult.Handled, result) assertEquals(KeyguardQuickAffordanceConfig.OnTriggeredResult.Handled, result)
assertEquals(ZEN_MODE_OFF, spyZenMode.value) assertEquals(ZEN_MODE_OFF, spyZenMode.value)
assertNull(spyConditionId.value) assertNull(spyConditionId.value)
} }
@Test @Test
fun `onTriggered - dnd mode is ZEN_MODE_OFF - setting is FOREVER - set zen with no condition`() = testScope.runTest { fun `onTriggered - dnd mode is ZEN_MODE_OFF - setting FOREVER - set zen without condition`() =
//given testScope.runTest {
whenever(zenModeController.isZenAvailable).thenReturn(true) // given
whenever(zenModeController.zen).thenReturn(ZEN_MODE_OFF) whenever(zenModeController.isZenAvailable).thenReturn(true)
settings.putInt(Settings.Secure.ZEN_DURATION, ZEN_DURATION_FOREVER) whenever(zenModeController.zen).thenReturn(ZEN_MODE_OFF)
collectLastValue(underTest.lockScreenState) settings.putInt(Settings.Secure.ZEN_DURATION, ZEN_DURATION_FOREVER)
runCurrent() collectLastValue(underTest.lockScreenState)
runCurrent()
//when // when
val result = underTest.onTriggered(null) val result = underTest.onTriggered(null)
verify(zenModeController).setZen(spyZenMode.capture(), spyConditionId.capture(), eq(DoNotDisturbQuickAffordanceConfig.TAG)) verify(zenModeController)
.setZen(
spyZenMode.capture(),
spyConditionId.capture(),
eq(DoNotDisturbQuickAffordanceConfig.TAG)
)
//then // then
assertEquals(KeyguardQuickAffordanceConfig.OnTriggeredResult.Handled, result) assertEquals(KeyguardQuickAffordanceConfig.OnTriggeredResult.Handled, result)
assertEquals(ZEN_MODE_IMPORTANT_INTERRUPTIONS, spyZenMode.value) assertEquals(ZEN_MODE_IMPORTANT_INTERRUPTIONS, spyZenMode.value)
assertNull(spyConditionId.value) assertNull(spyConditionId.value)
} }
@Test @Test
fun `onTriggered - dnd mode is ZEN_MODE_OFF - setting is not FOREVER or PROMPT - set zen with condition`() = testScope.runTest { fun `onTriggered - dnd ZEN_MODE_OFF - setting not FOREVER or PROMPT - zen with condition`() =
//given testScope.runTest {
whenever(zenModeController.isZenAvailable).thenReturn(true) // given
whenever(zenModeController.zen).thenReturn(ZEN_MODE_OFF) whenever(zenModeController.isZenAvailable).thenReturn(true)
settings.putInt(Settings.Secure.ZEN_DURATION, -900) whenever(zenModeController.zen).thenReturn(ZEN_MODE_OFF)
collectLastValue(underTest.lockScreenState) settings.putInt(Settings.Secure.ZEN_DURATION, -900)
runCurrent() collectLastValue(underTest.lockScreenState)
runCurrent()
//when // when
val result = underTest.onTriggered(null) val result = underTest.onTriggered(null)
verify(zenModeController).setZen(spyZenMode.capture(), spyConditionId.capture(), eq(DoNotDisturbQuickAffordanceConfig.TAG)) verify(zenModeController)
.setZen(
spyZenMode.capture(),
spyConditionId.capture(),
eq(DoNotDisturbQuickAffordanceConfig.TAG)
)
//then // then
assertEquals(KeyguardQuickAffordanceConfig.OnTriggeredResult.Handled, result) assertEquals(KeyguardQuickAffordanceConfig.OnTriggeredResult.Handled, result)
assertEquals(ZEN_MODE_IMPORTANT_INTERRUPTIONS, spyZenMode.value) assertEquals(ZEN_MODE_IMPORTANT_INTERRUPTIONS, spyZenMode.value)
assertEquals(conditionUri, spyConditionId.value) assertEquals(conditionUri, spyConditionId.value)
} }
@Test @Test
fun `onTriggered - dnd mode is ZEN_MODE_OFF - setting is PROMPT - show dialog`() = testScope.runTest { fun `onTriggered - dnd mode is ZEN_MODE_OFF - setting is PROMPT - show dialog`() =
//given testScope.runTest {
val expandable: Expandable = mock() // given
whenever(zenModeController.isZenAvailable).thenReturn(true) val expandable: Expandable = mock()
whenever(zenModeController.zen).thenReturn(ZEN_MODE_OFF) whenever(zenModeController.isZenAvailable).thenReturn(true)
settings.putInt(Settings.Secure.ZEN_DURATION, ZEN_DURATION_PROMPT) whenever(zenModeController.zen).thenReturn(ZEN_MODE_OFF)
whenever(enableZenModeDialog.createDialog()).thenReturn(mock()) settings.putInt(Settings.Secure.ZEN_DURATION, ZEN_DURATION_PROMPT)
collectLastValue(underTest.lockScreenState) whenever(enableZenModeDialog.createDialog()).thenReturn(mock())
runCurrent() collectLastValue(underTest.lockScreenState)
runCurrent()
//when // when
val result = underTest.onTriggered(expandable) val result = underTest.onTriggered(expandable)
//then // then
assertTrue(result is KeyguardQuickAffordanceConfig.OnTriggeredResult.ShowDialog) assertTrue(result is KeyguardQuickAffordanceConfig.OnTriggeredResult.ShowDialog)
assertEquals(expandable, (result as KeyguardQuickAffordanceConfig.OnTriggeredResult.ShowDialog).expandable) assertEquals(
} expandable,
(result as KeyguardQuickAffordanceConfig.OnTriggeredResult.ShowDialog).expandable
)
}
@Test @Test
fun `lockScreenState - dndAvailable starts as true - changes to false - State moves to Hidden`() = testScope.runTest { fun `lockScreenState - dndAvailable starts as true - change to false - State is Hidden`() =
//given testScope.runTest {
whenever(zenModeController.isZenAvailable).thenReturn(true) // given
val callbackCaptor: ArgumentCaptor<ZenModeController.Callback> = argumentCaptor() whenever(zenModeController.isZenAvailable).thenReturn(true)
val valueSnapshot = collectLastValue(underTest.lockScreenState) val callbackCaptor: ArgumentCaptor<ZenModeController.Callback> = argumentCaptor()
val secondLastValue = valueSnapshot() val valueSnapshot = collectLastValue(underTest.lockScreenState)
verify(zenModeController).addCallback(callbackCaptor.capture()) val secondLastValue = valueSnapshot()
verify(zenModeController).addCallback(callbackCaptor.capture())
//when // when
callbackCaptor.value.onZenAvailableChanged(false) callbackCaptor.value.onZenAvailableChanged(false)
val lastValue = valueSnapshot() val lastValue = valueSnapshot()
//then // then
assertTrue(secondLastValue is KeyguardQuickAffordanceConfig.LockScreenState.Visible) assertTrue(secondLastValue is KeyguardQuickAffordanceConfig.LockScreenState.Visible)
assertTrue(lastValue is KeyguardQuickAffordanceConfig.LockScreenState.Hidden) assertTrue(lastValue is KeyguardQuickAffordanceConfig.LockScreenState.Hidden)
} }
@Test @Test
fun `lockScreenState - dndMode starts as ZEN_MODE_OFF - changes to not OFF - State moves to Visible`() = testScope.runTest { fun `lockScreenState - dndMode starts as ZEN_MODE_OFF - change to not OFF - State Visible`() =
//given testScope.runTest {
whenever(zenModeController.isZenAvailable).thenReturn(true) // given
whenever(zenModeController.zen).thenReturn(ZEN_MODE_OFF) whenever(zenModeController.isZenAvailable).thenReturn(true)
val valueSnapshot = collectLastValue(underTest.lockScreenState) whenever(zenModeController.zen).thenReturn(ZEN_MODE_OFF)
val secondLastValue = valueSnapshot() val valueSnapshot = collectLastValue(underTest.lockScreenState)
val callbackCaptor: ArgumentCaptor<ZenModeController.Callback> = argumentCaptor() val secondLastValue = valueSnapshot()
verify(zenModeController).addCallback(callbackCaptor.capture()) val callbackCaptor: ArgumentCaptor<ZenModeController.Callback> = argumentCaptor()
verify(zenModeController).addCallback(callbackCaptor.capture())
//when // when
callbackCaptor.value.onZenChanged(ZEN_MODE_IMPORTANT_INTERRUPTIONS) callbackCaptor.value.onZenChanged(ZEN_MODE_IMPORTANT_INTERRUPTIONS)
val lastValue = valueSnapshot() val lastValue = valueSnapshot()
//then // then
assertEquals( assertEquals(
KeyguardQuickAffordanceConfig.LockScreenState.Visible( KeyguardQuickAffordanceConfig.LockScreenState.Visible(
Icon.Resource( Icon.Resource(
R.drawable.qs_dnd_icon_off, R.drawable.qs_dnd_icon_off,
ContentDescription.Resource(R.string.dnd_is_off) ContentDescription.Resource(R.string.dnd_is_off)
),
ActivationState.Inactive
), ),
ActivationState.Inactive secondLastValue,
), )
secondLastValue, assertEquals(
) KeyguardQuickAffordanceConfig.LockScreenState.Visible(
assertEquals( Icon.Resource(
KeyguardQuickAffordanceConfig.LockScreenState.Visible( R.drawable.qs_dnd_icon_on,
Icon.Resource( ContentDescription.Resource(R.string.dnd_is_on)
R.drawable.qs_dnd_icon_on, ),
ContentDescription.Resource(R.string.dnd_is_on) ActivationState.Active
), ),
ActivationState.Active lastValue,
), )
lastValue, }
) }
}
}

View File

@@ -141,7 +141,7 @@ class QrCodeScannerKeyguardQuickAffordanceConfigTest : SysuiTestCase() {
whenever(controller.isAbleToOpenCameraApp).thenReturn(true) whenever(controller.isAbleToOpenCameraApp).thenReturn(true)
assertThat(underTest.getPickerScreenState()) assertThat(underTest.getPickerScreenState())
.isEqualTo(KeyguardQuickAffordanceConfig.PickerScreenState.Default) .isEqualTo(KeyguardQuickAffordanceConfig.PickerScreenState.Default())
} }
@Test @Test

View File

@@ -159,7 +159,7 @@ class QuickAccessWalletKeyguardQuickAffordanceConfigTest : SysuiTestCase() {
setUpState() setUpState()
assertThat(underTest.getPickerScreenState()) assertThat(underTest.getPickerScreenState())
.isEqualTo(KeyguardQuickAffordanceConfig.PickerScreenState.Default) .isEqualTo(KeyguardQuickAffordanceConfig.PickerScreenState.Default())
} }
@Test @Test