Merge "Add Do Not disturb custom quick affordance" into tm-qpr-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
591c007930
25
packages/SystemUI/res/drawable/ic_do_not_disturb.xml
Normal file
25
packages/SystemUI/res/drawable/ic_do_not_disturb.xml
Normal file
@@ -0,0 +1,25 @@
|
||||
<!--
|
||||
~ Copyright (C) 2022 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.
|
||||
-->
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:height="24dp"
|
||||
android:width="24dp"
|
||||
android:viewportHeight="24.0"
|
||||
android:viewportWidth="24.0">
|
||||
|
||||
<path
|
||||
android:fillColor="#ffffff"
|
||||
android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM12,20c-4.41,0 -8,-3.59 -8,-8s3.59,-8 8,-8 8,3.59 8,8 -3.59,8 -8,8zM7,11h10v2L7,13z"/>
|
||||
</vector>
|
||||
@@ -2035,6 +2035,9 @@
|
||||
<!-- Label for when Do not disturb is off in QS detail panel [CHAR LIMIT=NONE] -->
|
||||
<string name="dnd_is_off">Do Not Disturb is off</string>
|
||||
|
||||
<!-- Label for when Do not disturb is on in lockscreen quick affordance [CHAR LIMIT=NONE] -->
|
||||
<string name="dnd_is_on">Do Not Disturb is on</string>
|
||||
|
||||
<!-- Prompt for when Do not disturb is on from automatic rule in QS [CHAR LIMIT=NONE] -->
|
||||
<string name="qs_dnd_prompt_auto_rule">Do Not Disturb was turned on by an automatic rule (<xliff:g name="rule">%s</xliff:g>).</string>
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@ package com.android.systemui.keyguard.data.quickaffordance
|
||||
object BuiltInKeyguardQuickAffordanceKeys {
|
||||
// Please keep alphabetical order of const names to simplify future maintenance.
|
||||
const val CAMERA = "camera"
|
||||
const val DO_NOT_DISTURB = "do_not_disturb"
|
||||
const val FLASHLIGHT = "flashlight"
|
||||
const val HOME_CONTROLS = "home"
|
||||
const val QR_CODE_SCANNER = "qr_code_scanner"
|
||||
|
||||
@@ -0,0 +1,190 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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.keyguard.data.quickaffordance
|
||||
|
||||
import android.content.Context
|
||||
import android.net.Uri
|
||||
import android.provider.Settings
|
||||
import android.provider.Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS
|
||||
import android.provider.Settings.Global.ZEN_MODE_OFF
|
||||
import android.provider.Settings.Secure.ZEN_DURATION_FOREVER
|
||||
import android.provider.Settings.Secure.ZEN_DURATION_PROMPT
|
||||
import android.service.notification.ZenModeConfig
|
||||
import com.android.settingslib.notification.EnableZenModeDialog
|
||||
import com.android.settingslib.notification.ZenModeDialogMetricsLogger
|
||||
import com.android.systemui.R
|
||||
import com.android.systemui.animation.Expandable
|
||||
import com.android.systemui.common.coroutine.ChannelExt.trySendWithFailureLogging
|
||||
import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow
|
||||
import com.android.systemui.common.shared.model.ContentDescription
|
||||
import com.android.systemui.common.shared.model.Icon
|
||||
import com.android.systemui.dagger.SysUISingleton
|
||||
import com.android.systemui.dagger.qualifiers.Background
|
||||
import com.android.systemui.keyguard.shared.quickaffordance.ActivationState
|
||||
import com.android.systemui.settings.UserTracker
|
||||
import com.android.systemui.statusbar.policy.ZenModeController
|
||||
import com.android.systemui.util.settings.SecureSettings
|
||||
import com.android.systemui.util.settings.SettingsProxyExt.observerFlow
|
||||
import kotlinx.coroutines.CoroutineDispatcher
|
||||
import kotlinx.coroutines.channels.awaitClose
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.combine
|
||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||
import kotlinx.coroutines.flow.flowOn
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import kotlinx.coroutines.flow.onStart
|
||||
import javax.inject.Inject
|
||||
|
||||
@SysUISingleton
|
||||
class DoNotDisturbQuickAffordanceConfig constructor(
|
||||
private val context: Context,
|
||||
private val controller: ZenModeController,
|
||||
private val secureSettings: SecureSettings,
|
||||
private val userTracker: UserTracker,
|
||||
@Background private val backgroundDispatcher: CoroutineDispatcher,
|
||||
private val testConditionId: Uri?,
|
||||
testDialog: EnableZenModeDialog?,
|
||||
): KeyguardQuickAffordanceConfig {
|
||||
|
||||
@Inject
|
||||
constructor(
|
||||
context: Context,
|
||||
controller: ZenModeController,
|
||||
secureSettings: SecureSettings,
|
||||
userTracker: UserTracker,
|
||||
@Background backgroundDispatcher: CoroutineDispatcher,
|
||||
) : this(context, controller, secureSettings, userTracker, backgroundDispatcher, null, null)
|
||||
|
||||
private var dndMode: Int = 0
|
||||
private var isAvailable = false
|
||||
private var settingsValue: Int = 0
|
||||
|
||||
private val conditionUri: Uri
|
||||
get() =
|
||||
testConditionId ?: ZenModeConfig.toTimeCondition(
|
||||
context,
|
||||
settingsValue,
|
||||
userTracker.userId,
|
||||
true, /* shortVersion */
|
||||
).id
|
||||
|
||||
private val dialog: EnableZenModeDialog by lazy {
|
||||
testDialog ?: EnableZenModeDialog(
|
||||
context,
|
||||
R.style.Theme_SystemUI_Dialog,
|
||||
true, /* cancelIsNeutral */
|
||||
ZenModeDialogMetricsLogger(context),
|
||||
)
|
||||
}
|
||||
|
||||
override val key: String = BuiltInKeyguardQuickAffordanceKeys.DO_NOT_DISTURB
|
||||
|
||||
override val pickerName: String = context.getString(R.string.quick_settings_dnd_label)
|
||||
|
||||
override val pickerIconResourceId: Int = R.drawable.ic_do_not_disturb
|
||||
|
||||
override val lockScreenState: Flow<KeyguardQuickAffordanceConfig.LockScreenState> = combine(
|
||||
conflatedCallbackFlow {
|
||||
val callback = object: ZenModeController.Callback {
|
||||
override fun onZenChanged(zen: Int) {
|
||||
dndMode = zen
|
||||
trySendWithFailureLogging(updateState(), TAG)
|
||||
}
|
||||
|
||||
override fun onZenAvailableChanged(available: Boolean) {
|
||||
isAvailable = available
|
||||
trySendWithFailureLogging(updateState(), TAG)
|
||||
}
|
||||
}
|
||||
|
||||
dndMode = controller.zen
|
||||
isAvailable = controller.isZenAvailable
|
||||
trySendWithFailureLogging(updateState(), TAG)
|
||||
|
||||
controller.addCallback(callback)
|
||||
|
||||
awaitClose { controller.removeCallback(callback) }
|
||||
},
|
||||
secureSettings
|
||||
.observerFlow(Settings.Secure.ZEN_DURATION)
|
||||
.onStart { emit(Unit) }
|
||||
.map { secureSettings.getInt(Settings.Secure.ZEN_DURATION, ZEN_MODE_OFF) }
|
||||
.flowOn(backgroundDispatcher)
|
||||
.distinctUntilChanged()
|
||||
.onEach { settingsValue = it }
|
||||
) { callbackFlowValue, _ -> callbackFlowValue }
|
||||
|
||||
override suspend fun getPickerScreenState(): KeyguardQuickAffordanceConfig.PickerScreenState {
|
||||
return if (controller.isZenAvailable) {
|
||||
KeyguardQuickAffordanceConfig.PickerScreenState.Default
|
||||
} else {
|
||||
KeyguardQuickAffordanceConfig.PickerScreenState.UnavailableOnDevice
|
||||
}
|
||||
}
|
||||
|
||||
override fun onTriggered(expandable: Expandable?):
|
||||
KeyguardQuickAffordanceConfig.OnTriggeredResult {
|
||||
return when {
|
||||
!isAvailable ->
|
||||
KeyguardQuickAffordanceConfig.OnTriggeredResult.Handled
|
||||
dndMode != ZEN_MODE_OFF -> {
|
||||
controller.setZen(ZEN_MODE_OFF, null, TAG)
|
||||
KeyguardQuickAffordanceConfig.OnTriggeredResult.Handled
|
||||
}
|
||||
settingsValue == ZEN_DURATION_PROMPT ->
|
||||
KeyguardQuickAffordanceConfig.OnTriggeredResult.ShowDialog(
|
||||
dialog.createDialog(),
|
||||
expandable
|
||||
)
|
||||
settingsValue == ZEN_DURATION_FOREVER -> {
|
||||
controller.setZen(ZEN_MODE_IMPORTANT_INTERRUPTIONS, null, TAG)
|
||||
KeyguardQuickAffordanceConfig.OnTriggeredResult.Handled
|
||||
}
|
||||
else -> {
|
||||
controller.setZen(ZEN_MODE_IMPORTANT_INTERRUPTIONS, conditionUri, TAG)
|
||||
KeyguardQuickAffordanceConfig.OnTriggeredResult.Handled
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateState(): KeyguardQuickAffordanceConfig.LockScreenState {
|
||||
return if (!isAvailable) {
|
||||
KeyguardQuickAffordanceConfig.LockScreenState.Hidden
|
||||
} else if (dndMode == ZEN_MODE_OFF) {
|
||||
KeyguardQuickAffordanceConfig.LockScreenState.Visible(
|
||||
Icon.Resource(
|
||||
R.drawable.qs_dnd_icon_off,
|
||||
ContentDescription.Resource(R.string.dnd_is_off),
|
||||
),
|
||||
ActivationState.Inactive,
|
||||
)
|
||||
} else {
|
||||
KeyguardQuickAffordanceConfig.LockScreenState.Visible(
|
||||
Icon.Resource(
|
||||
R.drawable.qs_dnd_icon_on,
|
||||
ContentDescription.Resource(R.string.dnd_is_on),
|
||||
),
|
||||
ActivationState.Active,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val TAG = "DoNotDisturbQuickAffordanceConfig"
|
||||
}
|
||||
}
|
||||
@@ -33,6 +33,7 @@ interface KeyguardDataQuickAffordanceModule {
|
||||
@Provides
|
||||
@ElementsIntoSet
|
||||
fun quickAffordanceConfigs(
|
||||
doNotDisturb: DoNotDisturbQuickAffordanceConfig,
|
||||
flashlight: FlashlightQuickAffordanceConfig,
|
||||
home: HomeControlsKeyguardQuickAffordanceConfig,
|
||||
quickAccessWallet: QuickAccessWalletKeyguardQuickAffordanceConfig,
|
||||
@@ -41,6 +42,7 @@ interface KeyguardDataQuickAffordanceModule {
|
||||
): Set<KeyguardQuickAffordanceConfig> {
|
||||
return setOf(
|
||||
camera,
|
||||
doNotDisturb,
|
||||
flashlight,
|
||||
home,
|
||||
quickAccessWallet,
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
|
||||
package com.android.systemui.keyguard.data.quickaffordance
|
||||
|
||||
import android.app.AlertDialog
|
||||
import android.content.Intent
|
||||
import com.android.systemui.animation.Expandable
|
||||
import com.android.systemui.common.shared.model.Icon
|
||||
@@ -141,6 +142,16 @@ interface KeyguardQuickAffordanceConfig {
|
||||
val intent: Intent,
|
||||
val canShowWhileLocked: Boolean,
|
||||
) : OnTriggeredResult()
|
||||
|
||||
/**
|
||||
* Returning this as a result from the [onTriggered] method means that the implementation
|
||||
* has _not_ taken care of the action and the system should show a Dialog using the
|
||||
* given [AlertDialog] and [Expandable].
|
||||
*/
|
||||
data class ShowDialog(
|
||||
val dialog: AlertDialog,
|
||||
val expandable: Expandable?,
|
||||
) : OnTriggeredResult()
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
@@ -17,9 +17,11 @@
|
||||
|
||||
package com.android.systemui.keyguard.domain.interactor
|
||||
|
||||
import android.app.AlertDialog
|
||||
import android.content.Intent
|
||||
import android.util.Log
|
||||
import com.android.internal.widget.LockPatternUtils
|
||||
import com.android.systemui.animation.DialogLaunchAnimator
|
||||
import com.android.systemui.animation.Expandable
|
||||
import com.android.systemui.dagger.SysUISingleton
|
||||
import com.android.systemui.flags.FeatureFlags
|
||||
@@ -35,15 +37,16 @@ import com.android.systemui.keyguard.shared.quickaffordance.KeyguardQuickAfforda
|
||||
import com.android.systemui.plugins.ActivityStarter
|
||||
import com.android.systemui.settings.UserTracker
|
||||
import com.android.systemui.shared.quickaffordance.data.content.KeyguardQuickAffordanceProviderContract as Contract
|
||||
import com.android.systemui.statusbar.phone.SystemUIDialog
|
||||
import com.android.systemui.statusbar.policy.KeyguardStateController
|
||||
import dagger.Lazy
|
||||
import javax.inject.Inject
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.combine
|
||||
import kotlinx.coroutines.flow.flatMapLatest
|
||||
import kotlinx.coroutines.flow.flowOf
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.onStart
|
||||
import javax.inject.Inject
|
||||
|
||||
@SysUISingleton
|
||||
class KeyguardQuickAffordanceInteractor
|
||||
@@ -57,6 +60,7 @@ constructor(
|
||||
private val activityStarter: ActivityStarter,
|
||||
private val featureFlags: FeatureFlags,
|
||||
private val repository: Lazy<KeyguardQuickAffordanceRepository>,
|
||||
private val launchAnimator: DialogLaunchAnimator,
|
||||
) {
|
||||
private val isUsingRepository: Boolean
|
||||
get() = featureFlags.isEnabled(Flags.CUSTOMIZABLE_LOCK_SCREEN_QUICK_AFFORDANCES)
|
||||
@@ -131,6 +135,11 @@ constructor(
|
||||
expandable = expandable,
|
||||
)
|
||||
is KeyguardQuickAffordanceConfig.OnTriggeredResult.Handled -> Unit
|
||||
is KeyguardQuickAffordanceConfig.OnTriggeredResult.ShowDialog ->
|
||||
showDialog(
|
||||
result.dialog,
|
||||
result.expandable,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -279,6 +288,19 @@ constructor(
|
||||
}
|
||||
}
|
||||
|
||||
private fun showDialog(dialog: AlertDialog, expandable: Expandable?) {
|
||||
expandable?.dialogLaunchController()?.let { controller ->
|
||||
SystemUIDialog.applyFlags(dialog)
|
||||
SystemUIDialog.setShowForAllUsers(dialog, true)
|
||||
SystemUIDialog.registerDismissListener(dialog)
|
||||
SystemUIDialog.setDialogSize(dialog)
|
||||
launchAnimator.show(
|
||||
dialog,
|
||||
controller
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun launchQuickAffordance(
|
||||
intent: Intent,
|
||||
canShowWhileLocked: Boolean,
|
||||
|
||||
@@ -31,6 +31,7 @@ import androidx.test.filters.SmallTest
|
||||
import com.android.internal.widget.LockPatternUtils
|
||||
import com.android.systemui.SystemUIAppComponentFactoryBase
|
||||
import com.android.systemui.SysuiTestCase
|
||||
import com.android.systemui.animation.DialogLaunchAnimator
|
||||
import com.android.systemui.flags.FakeFeatureFlags
|
||||
import com.android.systemui.flags.Flags
|
||||
import com.android.systemui.keyguard.data.quickaffordance.FakeKeyguardQuickAffordanceConfig
|
||||
@@ -84,6 +85,7 @@ class KeyguardQuickAffordanceProviderTest : SysuiTestCase() {
|
||||
@Mock private lateinit var previewRenderer: KeyguardPreviewRenderer
|
||||
@Mock private lateinit var backgroundHandler: Handler
|
||||
@Mock private lateinit var previewSurfacePackage: SurfaceControlViewHost.SurfacePackage
|
||||
@Mock private lateinit var launchAnimator: DialogLaunchAnimator
|
||||
|
||||
private lateinit var underTest: KeyguardQuickAffordanceProvider
|
||||
|
||||
@@ -170,6 +172,7 @@ class KeyguardQuickAffordanceProviderTest : SysuiTestCase() {
|
||||
set(Flags.LOCKSCREEN_CUSTOM_CLOCKS, true)
|
||||
},
|
||||
repository = { quickAffordanceRepository },
|
||||
launchAnimator = launchAnimator,
|
||||
)
|
||||
underTest.previewManager =
|
||||
KeyguardRemotePreviewManager(
|
||||
|
||||
@@ -0,0 +1,251 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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.keyguard.data.quickaffordance
|
||||
|
||||
import android.net.Uri
|
||||
import android.provider.Settings
|
||||
import android.provider.Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS
|
||||
import android.provider.Settings.Global.ZEN_MODE_OFF
|
||||
import android.provider.Settings.Secure.ZEN_DURATION_FOREVER
|
||||
import android.provider.Settings.Secure.ZEN_DURATION_PROMPT
|
||||
import androidx.test.filters.SmallTest
|
||||
import com.android.settingslib.notification.EnableZenModeDialog
|
||||
import com.android.systemui.R
|
||||
import com.android.systemui.SysuiTestCase
|
||||
import com.android.systemui.animation.Expandable
|
||||
import com.android.systemui.common.shared.model.ContentDescription
|
||||
import com.android.systemui.common.shared.model.Icon
|
||||
import com.android.systemui.coroutines.collectLastValue
|
||||
import com.android.systemui.keyguard.shared.quickaffordance.ActivationState
|
||||
import com.android.systemui.settings.UserTracker
|
||||
import com.android.systemui.statusbar.policy.ZenModeController
|
||||
import com.android.systemui.util.mockito.argumentCaptor
|
||||
import com.android.systemui.util.mockito.eq
|
||||
import com.android.systemui.util.mockito.mock
|
||||
import com.android.systemui.util.mockito.whenever
|
||||
import com.android.systemui.util.settings.FakeSettings
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
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.Assert.assertEquals
|
||||
import org.junit.Assert.assertNull
|
||||
import org.junit.Assert.assertTrue
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.junit.runners.JUnit4
|
||||
import org.mockito.ArgumentCaptor
|
||||
import org.mockito.Captor
|
||||
import org.mockito.Mock
|
||||
import org.mockito.Mockito.verify
|
||||
import org.mockito.MockitoAnnotations
|
||||
|
||||
@OptIn(ExperimentalCoroutinesApi::class)
|
||||
@SmallTest
|
||||
@RunWith(JUnit4::class)
|
||||
class DoNotDisturbQuickAffordanceConfigTest : SysuiTestCase() {
|
||||
|
||||
@Mock private lateinit var zenModeController: ZenModeController
|
||||
@Mock private lateinit var userTracker: UserTracker
|
||||
@Mock private lateinit var conditionUri: Uri
|
||||
@Mock private lateinit var enableZenModeDialog: EnableZenModeDialog
|
||||
@Captor private lateinit var spyZenMode: ArgumentCaptor<Int>
|
||||
@Captor private lateinit var spyConditionId: ArgumentCaptor<Uri?>
|
||||
private lateinit var settings: FakeSettings
|
||||
|
||||
private lateinit var underTest: DoNotDisturbQuickAffordanceConfig
|
||||
private lateinit var testDispatcher: TestDispatcher
|
||||
private lateinit var testScope: TestScope
|
||||
|
||||
@Before
|
||||
fun setUp() {
|
||||
MockitoAnnotations.initMocks(this)
|
||||
|
||||
testDispatcher = StandardTestDispatcher()
|
||||
testScope = TestScope(testDispatcher)
|
||||
|
||||
settings = FakeSettings()
|
||||
|
||||
underTest = DoNotDisturbQuickAffordanceConfig(
|
||||
context,
|
||||
zenModeController,
|
||||
settings,
|
||||
userTracker,
|
||||
testDispatcher,
|
||||
conditionUri,
|
||||
enableZenModeDialog,
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `dnd not available - picker state hidden`() = testScope.runTest {
|
||||
//given
|
||||
whenever(zenModeController.isZenAvailable).thenReturn(false)
|
||||
|
||||
//when
|
||||
val result = underTest.getPickerScreenState()
|
||||
|
||||
//then
|
||||
assertEquals(KeyguardQuickAffordanceConfig.PickerScreenState.UnavailableOnDevice, result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `dnd available - picker state visible`() = testScope.runTest {
|
||||
//given
|
||||
whenever(zenModeController.isZenAvailable).thenReturn(true)
|
||||
|
||||
//when
|
||||
val result = underTest.getPickerScreenState()
|
||||
|
||||
//then
|
||||
assertEquals(KeyguardQuickAffordanceConfig.PickerScreenState.Default, result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `onTriggered - dnd mode is not ZEN_MODE_OFF - set to ZEN_MODE_OFF`() = testScope.runTest {
|
||||
//given
|
||||
whenever(zenModeController.isZenAvailable).thenReturn(true)
|
||||
whenever(zenModeController.zen).thenReturn(-1)
|
||||
settings.putInt(Settings.Secure.ZEN_DURATION, -2)
|
||||
collectLastValue(underTest.lockScreenState)
|
||||
runCurrent()
|
||||
|
||||
//when
|
||||
val result = underTest.onTriggered(null)
|
||||
verify(zenModeController).setZen(spyZenMode.capture(), spyConditionId.capture(), eq(DoNotDisturbQuickAffordanceConfig.TAG))
|
||||
|
||||
//then
|
||||
assertEquals(KeyguardQuickAffordanceConfig.OnTriggeredResult.Handled, result)
|
||||
assertEquals(ZEN_MODE_OFF, spyZenMode.value)
|
||||
assertNull(spyConditionId.value)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `onTriggered - dnd mode is ZEN_MODE_OFF - setting is FOREVER - set zen with no condition`() = testScope.runTest {
|
||||
//given
|
||||
whenever(zenModeController.isZenAvailable).thenReturn(true)
|
||||
whenever(zenModeController.zen).thenReturn(ZEN_MODE_OFF)
|
||||
settings.putInt(Settings.Secure.ZEN_DURATION, ZEN_DURATION_FOREVER)
|
||||
collectLastValue(underTest.lockScreenState)
|
||||
runCurrent()
|
||||
|
||||
//when
|
||||
val result = underTest.onTriggered(null)
|
||||
verify(zenModeController).setZen(spyZenMode.capture(), spyConditionId.capture(), eq(DoNotDisturbQuickAffordanceConfig.TAG))
|
||||
|
||||
//then
|
||||
assertEquals(KeyguardQuickAffordanceConfig.OnTriggeredResult.Handled, result)
|
||||
assertEquals(ZEN_MODE_IMPORTANT_INTERRUPTIONS, spyZenMode.value)
|
||||
assertNull(spyConditionId.value)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `onTriggered - dnd mode is ZEN_MODE_OFF - setting is not FOREVER or PROMPT - set zen with condition`() = testScope.runTest {
|
||||
//given
|
||||
whenever(zenModeController.isZenAvailable).thenReturn(true)
|
||||
whenever(zenModeController.zen).thenReturn(ZEN_MODE_OFF)
|
||||
settings.putInt(Settings.Secure.ZEN_DURATION, -900)
|
||||
collectLastValue(underTest.lockScreenState)
|
||||
runCurrent()
|
||||
|
||||
//when
|
||||
val result = underTest.onTriggered(null)
|
||||
verify(zenModeController).setZen(spyZenMode.capture(), spyConditionId.capture(), eq(DoNotDisturbQuickAffordanceConfig.TAG))
|
||||
|
||||
//then
|
||||
assertEquals(KeyguardQuickAffordanceConfig.OnTriggeredResult.Handled, result)
|
||||
assertEquals(ZEN_MODE_IMPORTANT_INTERRUPTIONS, spyZenMode.value)
|
||||
assertEquals(conditionUri, spyConditionId.value)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `onTriggered - dnd mode is ZEN_MODE_OFF - setting is PROMPT - show dialog`() = testScope.runTest {
|
||||
//given
|
||||
val expandable: Expandable = mock()
|
||||
whenever(zenModeController.isZenAvailable).thenReturn(true)
|
||||
whenever(zenModeController.zen).thenReturn(ZEN_MODE_OFF)
|
||||
settings.putInt(Settings.Secure.ZEN_DURATION, ZEN_DURATION_PROMPT)
|
||||
whenever(enableZenModeDialog.createDialog()).thenReturn(mock())
|
||||
collectLastValue(underTest.lockScreenState)
|
||||
runCurrent()
|
||||
|
||||
//when
|
||||
val result = underTest.onTriggered(expandable)
|
||||
|
||||
//then
|
||||
assertTrue(result is KeyguardQuickAffordanceConfig.OnTriggeredResult.ShowDialog)
|
||||
assertEquals(expandable, (result as KeyguardQuickAffordanceConfig.OnTriggeredResult.ShowDialog).expandable)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `lockScreenState - dndAvailable starts as true - changes to false - State moves to Hidden`() = testScope.runTest {
|
||||
//given
|
||||
whenever(zenModeController.isZenAvailable).thenReturn(true)
|
||||
val callbackCaptor: ArgumentCaptor<ZenModeController.Callback> = argumentCaptor()
|
||||
val valueSnapshot = collectLastValue(underTest.lockScreenState)
|
||||
val secondLastValue = valueSnapshot()
|
||||
verify(zenModeController).addCallback(callbackCaptor.capture())
|
||||
|
||||
//when
|
||||
callbackCaptor.value.onZenAvailableChanged(false)
|
||||
val lastValue = valueSnapshot()
|
||||
|
||||
//then
|
||||
assertTrue(secondLastValue is KeyguardQuickAffordanceConfig.LockScreenState.Visible)
|
||||
assertTrue(lastValue is KeyguardQuickAffordanceConfig.LockScreenState.Hidden)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `lockScreenState - dndMode starts as ZEN_MODE_OFF - changes to not OFF - State moves to Visible`() = testScope.runTest {
|
||||
//given
|
||||
whenever(zenModeController.isZenAvailable).thenReturn(true)
|
||||
whenever(zenModeController.zen).thenReturn(ZEN_MODE_OFF)
|
||||
val valueSnapshot = collectLastValue(underTest.lockScreenState)
|
||||
val secondLastValue = valueSnapshot()
|
||||
val callbackCaptor: ArgumentCaptor<ZenModeController.Callback> = argumentCaptor()
|
||||
verify(zenModeController).addCallback(callbackCaptor.capture())
|
||||
|
||||
//when
|
||||
callbackCaptor.value.onZenChanged(ZEN_MODE_IMPORTANT_INTERRUPTIONS)
|
||||
val lastValue = valueSnapshot()
|
||||
|
||||
//then
|
||||
assertEquals(
|
||||
KeyguardQuickAffordanceConfig.LockScreenState.Visible(
|
||||
Icon.Resource(
|
||||
R.drawable.qs_dnd_icon_off,
|
||||
ContentDescription.Resource(R.string.dnd_is_off)
|
||||
),
|
||||
ActivationState.Inactive
|
||||
),
|
||||
secondLastValue,
|
||||
)
|
||||
assertEquals(
|
||||
KeyguardQuickAffordanceConfig.LockScreenState.Visible(
|
||||
Icon.Resource(
|
||||
R.drawable.qs_dnd_icon_on,
|
||||
ContentDescription.Resource(R.string.dnd_is_on)
|
||||
),
|
||||
ActivationState.Active
|
||||
),
|
||||
lastValue,
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -23,6 +23,7 @@ import androidx.test.filters.SmallTest
|
||||
import com.android.internal.widget.LockPatternUtils
|
||||
import com.android.systemui.SysuiTestCase
|
||||
import com.android.systemui.animation.ActivityLaunchAnimator
|
||||
import com.android.systemui.animation.DialogLaunchAnimator
|
||||
import com.android.systemui.animation.Expandable
|
||||
import com.android.systemui.common.shared.model.ContentDescription
|
||||
import com.android.systemui.common.shared.model.Icon
|
||||
@@ -214,6 +215,7 @@ class KeyguardQuickAffordanceInteractorParameterizedTest : SysuiTestCase() {
|
||||
@Mock private lateinit var activityStarter: ActivityStarter
|
||||
@Mock private lateinit var animationController: ActivityLaunchAnimator.Controller
|
||||
@Mock private lateinit var expandable: Expandable
|
||||
@Mock private lateinit var launchAnimator: DialogLaunchAnimator
|
||||
|
||||
private lateinit var underTest: KeyguardQuickAffordanceInteractor
|
||||
|
||||
@@ -308,6 +310,7 @@ class KeyguardQuickAffordanceInteractorParameterizedTest : SysuiTestCase() {
|
||||
set(Flags.CUSTOMIZABLE_LOCK_SCREEN_QUICK_AFFORDANCES, false)
|
||||
},
|
||||
repository = { quickAffordanceRepository },
|
||||
launchAnimator = launchAnimator,
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@ import androidx.test.filters.SmallTest
|
||||
import com.android.internal.widget.LockPatternUtils
|
||||
import com.android.systemui.R
|
||||
import com.android.systemui.SysuiTestCase
|
||||
import com.android.systemui.animation.DialogLaunchAnimator
|
||||
import com.android.systemui.common.shared.model.ContentDescription
|
||||
import com.android.systemui.common.shared.model.Icon
|
||||
import com.android.systemui.coroutines.collectLastValue
|
||||
@@ -73,6 +74,7 @@ class KeyguardQuickAffordanceInteractorTest : SysuiTestCase() {
|
||||
@Mock private lateinit var keyguardStateController: KeyguardStateController
|
||||
@Mock private lateinit var userTracker: UserTracker
|
||||
@Mock private lateinit var activityStarter: ActivityStarter
|
||||
@Mock private lateinit var launchAnimator: DialogLaunchAnimator
|
||||
|
||||
private lateinit var underTest: KeyguardQuickAffordanceInteractor
|
||||
|
||||
@@ -171,6 +173,7 @@ class KeyguardQuickAffordanceInteractorTest : SysuiTestCase() {
|
||||
activityStarter = activityStarter,
|
||||
featureFlags = featureFlags,
|
||||
repository = { quickAffordanceRepository },
|
||||
launchAnimator = launchAnimator,
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@ import android.os.UserHandle
|
||||
import androidx.test.filters.SmallTest
|
||||
import com.android.internal.widget.LockPatternUtils
|
||||
import com.android.systemui.SysuiTestCase
|
||||
import com.android.systemui.animation.DialogLaunchAnimator
|
||||
import com.android.systemui.animation.Expandable
|
||||
import com.android.systemui.common.shared.model.Icon
|
||||
import com.android.systemui.coroutines.collectLastValue
|
||||
@@ -82,6 +83,7 @@ class KeyguardBottomAreaViewModelTest : SysuiTestCase() {
|
||||
@Mock private lateinit var keyguardStateController: KeyguardStateController
|
||||
@Mock private lateinit var userTracker: UserTracker
|
||||
@Mock private lateinit var activityStarter: ActivityStarter
|
||||
@Mock private lateinit var launchAnimator: DialogLaunchAnimator
|
||||
|
||||
private lateinit var underTest: KeyguardBottomAreaViewModel
|
||||
|
||||
@@ -191,6 +193,7 @@ class KeyguardBottomAreaViewModelTest : SysuiTestCase() {
|
||||
set(Flags.CUSTOMIZABLE_LOCK_SCREEN_QUICK_AFFORDANCES, false)
|
||||
},
|
||||
repository = { quickAffordanceRepository },
|
||||
launchAnimator = launchAnimator,
|
||||
),
|
||||
bottomAreaInteractor = KeyguardBottomAreaInteractor(repository = repository),
|
||||
burnInHelperWrapper = burnInHelperWrapper,
|
||||
|
||||
Reference in New Issue
Block a user