Loading packages/SystemUI/docs/device-entry/quickaffordance.md +5 −0 Original line number Diff line number Diff line Loading @@ -52,6 +52,11 @@ A picker experience may: * Unselect an already-selected quick affordance from a slot * Unselect all already-selected quick affordances from a slot ## Device Policy Returning `DevicePolicyManager.KEYGUARD_DISABLE_FEATURES_ALL` or `DevicePolicyManager.KEYGUARD_DISABLE_SHORTCUTS_ALL` from `DevicePolicyManager#getKeyguardDisabledFeatures` will disable the keyguard quick affordance feature on the device. ## Testing * Add a unit test for your implementation of `KeyguardQuickAffordanceConfig` * Manually verify that your implementation works in multi-user environments from both the main user and a secondary user Loading packages/SystemUI/src/com/android/systemui/keyguard/CustomizationProvider.kt +6 −6 Original line number Diff line number Diff line Loading @@ -131,7 +131,7 @@ class CustomizationProvider : throw UnsupportedOperationException() } return insertSelection(values) return runBlocking { insertSelection(values) } } override fun query( Loading Loading @@ -171,7 +171,7 @@ class CustomizationProvider : throw UnsupportedOperationException() } return deleteSelection(uri, selectionArgs) return runBlocking { deleteSelection(uri, selectionArgs) } } override fun call(method: String, arg: String?, extras: Bundle?): Bundle? { Loading @@ -189,7 +189,7 @@ class CustomizationProvider : } } private fun insertSelection(values: ContentValues?): Uri? { private suspend fun insertSelection(values: ContentValues?): Uri? { if (values == null) { throw IllegalArgumentException("Cannot insert selection, no values passed in!") } Loading Loading @@ -311,7 +311,7 @@ class CustomizationProvider : } } private fun querySlots(): Cursor { private suspend fun querySlots(): Cursor { return MatrixCursor( arrayOf( Contract.LockScreenQuickAffordances.SlotTable.Columns.ID, Loading @@ -330,7 +330,7 @@ class CustomizationProvider : } } private fun queryFlags(): Cursor { private suspend fun queryFlags(): Cursor { return MatrixCursor( arrayOf( Contract.FlagsTable.Columns.NAME, Loading @@ -353,7 +353,7 @@ class CustomizationProvider : } } private fun deleteSelection( private suspend fun deleteSelection( uri: Uri, selectionArgs: Array<out String>?, ): Int { Loading packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractor.kt +54 −8 Original line number Diff line number Diff line Loading @@ -18,12 +18,14 @@ package com.android.systemui.keyguard.domain.interactor import android.app.AlertDialog import android.app.admin.DevicePolicyManager 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.dagger.qualifiers.Background import com.android.systemui.flags.FeatureFlags import com.android.systemui.flags.Flags import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceConfig Loading @@ -41,13 +43,17 @@ import com.android.systemui.statusbar.phone.SystemUIDialog import com.android.systemui.statusbar.policy.KeyguardStateController import dagger.Lazy import javax.inject.Inject import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.ExperimentalCoroutinesApi 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 kotlinx.coroutines.withContext @OptIn(ExperimentalCoroutinesApi::class) @SysUISingleton class KeyguardQuickAffordanceInteractor @Inject Loading @@ -61,6 +67,8 @@ constructor( private val featureFlags: FeatureFlags, private val repository: Lazy<KeyguardQuickAffordanceRepository>, private val launchAnimator: DialogLaunchAnimator, private val devicePolicyManager: DevicePolicyManager, @Background private val backgroundDispatcher: CoroutineDispatcher, ) { private val isUsingRepository: Boolean get() = featureFlags.isEnabled(Flags.CUSTOMIZABLE_LOCK_SCREEN_QUICK_AFFORDANCES) Loading @@ -74,9 +82,13 @@ constructor( get() = featureFlags.isEnabled(Flags.CUSTOMIZABLE_LOCK_SCREEN_QUICK_AFFORDANCES) /** Returns an observable for the quick affordance at the given position. */ fun quickAffordance( suspend fun quickAffordance( position: KeyguardQuickAffordancePosition ): Flow<KeyguardQuickAffordanceModel> { if (isFeatureDisabledByDevicePolicy()) { return flowOf(KeyguardQuickAffordanceModel.Hidden) } return combine( quickAffordanceAlwaysVisible(position), keyguardInteractor.isDozing, Loading Loading @@ -148,13 +160,20 @@ constructor( * * @return `true` if the affordance was selected successfully; `false` otherwise. */ fun select(slotId: String, affordanceId: String): Boolean { suspend fun select(slotId: String, affordanceId: String): Boolean { check(isUsingRepository) if (isFeatureDisabledByDevicePolicy()) { return false } val slots = repository.get().getSlotPickerRepresentations() val slot = slots.find { it.id == slotId } ?: return false val selections = repository.get().getCurrentSelections().getOrDefault(slotId, emptyList()).toMutableList() repository .get() .getCurrentSelections() .getOrDefault(slotId, emptyList()) .toMutableList() val alreadySelected = selections.remove(affordanceId) if (!alreadySelected) { while (selections.size > 0 && selections.size >= slot.maxSelectedAffordances) { Loading Loading @@ -183,8 +202,11 @@ constructor( * @return `true` if the affordance was successfully removed; `false` otherwise (for example, if * the affordance was not on the slot to begin with). */ fun unselect(slotId: String, affordanceId: String?): Boolean { suspend fun unselect(slotId: String, affordanceId: String?): Boolean { check(isUsingRepository) if (isFeatureDisabledByDevicePolicy()) { return false } val slots = repository.get().getSlotPickerRepresentations() if (slots.find { it.id == slotId } == null) { Loading @@ -203,7 +225,11 @@ constructor( } val selections = repository.get().getCurrentSelections().getOrDefault(slotId, emptyList()).toMutableList() repository .get() .getCurrentSelections() .getOrDefault(slotId, emptyList()) .toMutableList() return if (selections.remove(affordanceId)) { repository .get() Loading @@ -219,6 +245,10 @@ constructor( /** Returns affordance IDs indexed by slot ID, for all known slots. */ suspend fun getSelections(): Map<String, List<KeyguardQuickAffordancePickerRepresentation>> { if (isFeatureDisabledByDevicePolicy()) { return emptyMap() } val slots = repository.get().getSlotPickerRepresentations() val selections = repository.get().getCurrentSelections() val affordanceById = Loading Loading @@ -343,13 +373,17 @@ constructor( return repository.get().getAffordancePickerRepresentations() } fun getSlotPickerRepresentations(): List<KeyguardSlotPickerRepresentation> { suspend fun getSlotPickerRepresentations(): List<KeyguardSlotPickerRepresentation> { check(isUsingRepository) if (isFeatureDisabledByDevicePolicy()) { return emptyList() } return repository.get().getSlotPickerRepresentations() } fun getPickerFlags(): List<KeyguardPickerFlag> { suspend fun getPickerFlags(): List<KeyguardPickerFlag> { return listOf( KeyguardPickerFlag( name = Contract.FlagsTable.FLAG_NAME_REVAMPED_WALLPAPER_UI, Loading @@ -357,7 +391,9 @@ constructor( ), KeyguardPickerFlag( name = Contract.FlagsTable.FLAG_NAME_CUSTOM_LOCK_SCREEN_QUICK_AFFORDANCES_ENABLED, value = featureFlags.isEnabled(Flags.CUSTOMIZABLE_LOCK_SCREEN_QUICK_AFFORDANCES), value = !isFeatureDisabledByDevicePolicy() && featureFlags.isEnabled(Flags.CUSTOMIZABLE_LOCK_SCREEN_QUICK_AFFORDANCES), ), KeyguardPickerFlag( name = Contract.FlagsTable.FLAG_NAME_CUSTOM_CLOCKS_ENABLED, Loading @@ -374,6 +410,16 @@ constructor( ) } private suspend fun isFeatureDisabledByDevicePolicy(): Boolean { val flags = withContext(backgroundDispatcher) { devicePolicyManager.getKeyguardDisabledFeatures(null, userTracker.userId) } val flagsToCheck = DevicePolicyManager.KEYGUARD_DISABLE_FEATURES_ALL // TODO(b/268218507): "or" with DevicePolicyManager.KEYGUARD_DISABLE_SHORTCUTS_ALL return flagsToCheck and flags != 0 } companion object { private const val TAG = "KeyguardQuickAffordanceInteractor" private const val DELIMITER = "::" Loading packages/SystemUI/tests/src/com/android/systemui/keyguard/CustomizationProviderTest.kt +4 −0 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ package com.android.systemui.keyguard import android.app.admin.DevicePolicyManager import android.content.ContentValues import android.content.pm.PackageManager import android.content.pm.ProviderInfo Loading Loading @@ -90,6 +91,7 @@ class CustomizationProviderTest : SysuiTestCase() { @Mock private lateinit var previewSurfacePackage: SurfaceControlViewHost.SurfacePackage @Mock private lateinit var launchAnimator: DialogLaunchAnimator @Mock private lateinit var commandQueue: CommandQueue @Mock private lateinit var devicePolicyManager: DevicePolicyManager private lateinit var underTest: CustomizationProvider private lateinit var testScope: TestScope Loading Loading @@ -183,6 +185,8 @@ class CustomizationProviderTest : SysuiTestCase() { featureFlags = featureFlags, repository = { quickAffordanceRepository }, launchAnimator = launchAnimator, devicePolicyManager = devicePolicyManager, backgroundDispatcher = testDispatcher, ) underTest.previewManager = KeyguardRemotePreviewManager( Loading packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractorParameterizedTest.kt +55 −43 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ package com.android.systemui.keyguard.domain.interactor import android.app.admin.DevicePolicyManager import android.content.Intent import android.os.UserHandle import androidx.test.filters.SmallTest Loading Loading @@ -54,7 +55,10 @@ import com.android.systemui.util.mockito.whenever import com.android.systemui.util.settings.FakeSettings import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.test.runBlockingTest import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.test.StandardTestDispatcher import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.runTest import org.junit.Before import org.junit.Test import org.junit.runner.RunWith Loading @@ -70,6 +74,7 @@ import org.mockito.Mockito.verify import org.mockito.Mockito.verifyZeroInteractions import org.mockito.MockitoAnnotations @OptIn(ExperimentalCoroutinesApi::class) @SmallTest @RunWith(Parameterized::class) class KeyguardQuickAffordanceInteractorParameterizedTest : SysuiTestCase() { Loading Loading @@ -219,8 +224,10 @@ class KeyguardQuickAffordanceInteractorParameterizedTest : SysuiTestCase() { @Mock private lateinit var expandable: Expandable @Mock private lateinit var launchAnimator: DialogLaunchAnimator @Mock private lateinit var commandQueue: CommandQueue @Mock private lateinit var devicePolicyManager: DevicePolicyManager private lateinit var underTest: KeyguardQuickAffordanceInteractor private lateinit var testScope: TestScope @JvmField @Parameter(0) var needStrongAuthAfterBoot: Boolean = false @JvmField @Parameter(1) var canShowWhileLocked: Boolean = false Loading Loading @@ -292,6 +299,8 @@ class KeyguardQuickAffordanceInteractorParameterizedTest : SysuiTestCase() { set(Flags.CUSTOMIZABLE_LOCK_SCREEN_QUICK_AFFORDANCES, false) set(Flags.FACE_AUTH_REFACTOR, true) } val testDispatcher = StandardTestDispatcher() testScope = TestScope(testDispatcher) underTest = KeyguardQuickAffordanceInteractor( keyguardInteractor = Loading Loading @@ -322,11 +331,14 @@ class KeyguardQuickAffordanceInteractorParameterizedTest : SysuiTestCase() { featureFlags = featureFlags, repository = { quickAffordanceRepository }, launchAnimator = launchAnimator, devicePolicyManager = devicePolicyManager, backgroundDispatcher = testDispatcher, ) } @Test fun onQuickAffordanceTriggered() = runBlockingTest { fun onQuickAffordanceTriggered() = testScope.runTest { setUpMocks( needStrongAuthAfterBoot = needStrongAuthAfterBoot, keyguardIsUnlocked = keyguardIsUnlocked, Loading Loading
packages/SystemUI/docs/device-entry/quickaffordance.md +5 −0 Original line number Diff line number Diff line Loading @@ -52,6 +52,11 @@ A picker experience may: * Unselect an already-selected quick affordance from a slot * Unselect all already-selected quick affordances from a slot ## Device Policy Returning `DevicePolicyManager.KEYGUARD_DISABLE_FEATURES_ALL` or `DevicePolicyManager.KEYGUARD_DISABLE_SHORTCUTS_ALL` from `DevicePolicyManager#getKeyguardDisabledFeatures` will disable the keyguard quick affordance feature on the device. ## Testing * Add a unit test for your implementation of `KeyguardQuickAffordanceConfig` * Manually verify that your implementation works in multi-user environments from both the main user and a secondary user Loading
packages/SystemUI/src/com/android/systemui/keyguard/CustomizationProvider.kt +6 −6 Original line number Diff line number Diff line Loading @@ -131,7 +131,7 @@ class CustomizationProvider : throw UnsupportedOperationException() } return insertSelection(values) return runBlocking { insertSelection(values) } } override fun query( Loading Loading @@ -171,7 +171,7 @@ class CustomizationProvider : throw UnsupportedOperationException() } return deleteSelection(uri, selectionArgs) return runBlocking { deleteSelection(uri, selectionArgs) } } override fun call(method: String, arg: String?, extras: Bundle?): Bundle? { Loading @@ -189,7 +189,7 @@ class CustomizationProvider : } } private fun insertSelection(values: ContentValues?): Uri? { private suspend fun insertSelection(values: ContentValues?): Uri? { if (values == null) { throw IllegalArgumentException("Cannot insert selection, no values passed in!") } Loading Loading @@ -311,7 +311,7 @@ class CustomizationProvider : } } private fun querySlots(): Cursor { private suspend fun querySlots(): Cursor { return MatrixCursor( arrayOf( Contract.LockScreenQuickAffordances.SlotTable.Columns.ID, Loading @@ -330,7 +330,7 @@ class CustomizationProvider : } } private fun queryFlags(): Cursor { private suspend fun queryFlags(): Cursor { return MatrixCursor( arrayOf( Contract.FlagsTable.Columns.NAME, Loading @@ -353,7 +353,7 @@ class CustomizationProvider : } } private fun deleteSelection( private suspend fun deleteSelection( uri: Uri, selectionArgs: Array<out String>?, ): Int { Loading
packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractor.kt +54 −8 Original line number Diff line number Diff line Loading @@ -18,12 +18,14 @@ package com.android.systemui.keyguard.domain.interactor import android.app.AlertDialog import android.app.admin.DevicePolicyManager 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.dagger.qualifiers.Background import com.android.systemui.flags.FeatureFlags import com.android.systemui.flags.Flags import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceConfig Loading @@ -41,13 +43,17 @@ import com.android.systemui.statusbar.phone.SystemUIDialog import com.android.systemui.statusbar.policy.KeyguardStateController import dagger.Lazy import javax.inject.Inject import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.ExperimentalCoroutinesApi 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 kotlinx.coroutines.withContext @OptIn(ExperimentalCoroutinesApi::class) @SysUISingleton class KeyguardQuickAffordanceInteractor @Inject Loading @@ -61,6 +67,8 @@ constructor( private val featureFlags: FeatureFlags, private val repository: Lazy<KeyguardQuickAffordanceRepository>, private val launchAnimator: DialogLaunchAnimator, private val devicePolicyManager: DevicePolicyManager, @Background private val backgroundDispatcher: CoroutineDispatcher, ) { private val isUsingRepository: Boolean get() = featureFlags.isEnabled(Flags.CUSTOMIZABLE_LOCK_SCREEN_QUICK_AFFORDANCES) Loading @@ -74,9 +82,13 @@ constructor( get() = featureFlags.isEnabled(Flags.CUSTOMIZABLE_LOCK_SCREEN_QUICK_AFFORDANCES) /** Returns an observable for the quick affordance at the given position. */ fun quickAffordance( suspend fun quickAffordance( position: KeyguardQuickAffordancePosition ): Flow<KeyguardQuickAffordanceModel> { if (isFeatureDisabledByDevicePolicy()) { return flowOf(KeyguardQuickAffordanceModel.Hidden) } return combine( quickAffordanceAlwaysVisible(position), keyguardInteractor.isDozing, Loading Loading @@ -148,13 +160,20 @@ constructor( * * @return `true` if the affordance was selected successfully; `false` otherwise. */ fun select(slotId: String, affordanceId: String): Boolean { suspend fun select(slotId: String, affordanceId: String): Boolean { check(isUsingRepository) if (isFeatureDisabledByDevicePolicy()) { return false } val slots = repository.get().getSlotPickerRepresentations() val slot = slots.find { it.id == slotId } ?: return false val selections = repository.get().getCurrentSelections().getOrDefault(slotId, emptyList()).toMutableList() repository .get() .getCurrentSelections() .getOrDefault(slotId, emptyList()) .toMutableList() val alreadySelected = selections.remove(affordanceId) if (!alreadySelected) { while (selections.size > 0 && selections.size >= slot.maxSelectedAffordances) { Loading Loading @@ -183,8 +202,11 @@ constructor( * @return `true` if the affordance was successfully removed; `false` otherwise (for example, if * the affordance was not on the slot to begin with). */ fun unselect(slotId: String, affordanceId: String?): Boolean { suspend fun unselect(slotId: String, affordanceId: String?): Boolean { check(isUsingRepository) if (isFeatureDisabledByDevicePolicy()) { return false } val slots = repository.get().getSlotPickerRepresentations() if (slots.find { it.id == slotId } == null) { Loading @@ -203,7 +225,11 @@ constructor( } val selections = repository.get().getCurrentSelections().getOrDefault(slotId, emptyList()).toMutableList() repository .get() .getCurrentSelections() .getOrDefault(slotId, emptyList()) .toMutableList() return if (selections.remove(affordanceId)) { repository .get() Loading @@ -219,6 +245,10 @@ constructor( /** Returns affordance IDs indexed by slot ID, for all known slots. */ suspend fun getSelections(): Map<String, List<KeyguardQuickAffordancePickerRepresentation>> { if (isFeatureDisabledByDevicePolicy()) { return emptyMap() } val slots = repository.get().getSlotPickerRepresentations() val selections = repository.get().getCurrentSelections() val affordanceById = Loading Loading @@ -343,13 +373,17 @@ constructor( return repository.get().getAffordancePickerRepresentations() } fun getSlotPickerRepresentations(): List<KeyguardSlotPickerRepresentation> { suspend fun getSlotPickerRepresentations(): List<KeyguardSlotPickerRepresentation> { check(isUsingRepository) if (isFeatureDisabledByDevicePolicy()) { return emptyList() } return repository.get().getSlotPickerRepresentations() } fun getPickerFlags(): List<KeyguardPickerFlag> { suspend fun getPickerFlags(): List<KeyguardPickerFlag> { return listOf( KeyguardPickerFlag( name = Contract.FlagsTable.FLAG_NAME_REVAMPED_WALLPAPER_UI, Loading @@ -357,7 +391,9 @@ constructor( ), KeyguardPickerFlag( name = Contract.FlagsTable.FLAG_NAME_CUSTOM_LOCK_SCREEN_QUICK_AFFORDANCES_ENABLED, value = featureFlags.isEnabled(Flags.CUSTOMIZABLE_LOCK_SCREEN_QUICK_AFFORDANCES), value = !isFeatureDisabledByDevicePolicy() && featureFlags.isEnabled(Flags.CUSTOMIZABLE_LOCK_SCREEN_QUICK_AFFORDANCES), ), KeyguardPickerFlag( name = Contract.FlagsTable.FLAG_NAME_CUSTOM_CLOCKS_ENABLED, Loading @@ -374,6 +410,16 @@ constructor( ) } private suspend fun isFeatureDisabledByDevicePolicy(): Boolean { val flags = withContext(backgroundDispatcher) { devicePolicyManager.getKeyguardDisabledFeatures(null, userTracker.userId) } val flagsToCheck = DevicePolicyManager.KEYGUARD_DISABLE_FEATURES_ALL // TODO(b/268218507): "or" with DevicePolicyManager.KEYGUARD_DISABLE_SHORTCUTS_ALL return flagsToCheck and flags != 0 } companion object { private const val TAG = "KeyguardQuickAffordanceInteractor" private const val DELIMITER = "::" Loading
packages/SystemUI/tests/src/com/android/systemui/keyguard/CustomizationProviderTest.kt +4 −0 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ package com.android.systemui.keyguard import android.app.admin.DevicePolicyManager import android.content.ContentValues import android.content.pm.PackageManager import android.content.pm.ProviderInfo Loading Loading @@ -90,6 +91,7 @@ class CustomizationProviderTest : SysuiTestCase() { @Mock private lateinit var previewSurfacePackage: SurfaceControlViewHost.SurfacePackage @Mock private lateinit var launchAnimator: DialogLaunchAnimator @Mock private lateinit var commandQueue: CommandQueue @Mock private lateinit var devicePolicyManager: DevicePolicyManager private lateinit var underTest: CustomizationProvider private lateinit var testScope: TestScope Loading Loading @@ -183,6 +185,8 @@ class CustomizationProviderTest : SysuiTestCase() { featureFlags = featureFlags, repository = { quickAffordanceRepository }, launchAnimator = launchAnimator, devicePolicyManager = devicePolicyManager, backgroundDispatcher = testDispatcher, ) underTest.previewManager = KeyguardRemotePreviewManager( Loading
packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractorParameterizedTest.kt +55 −43 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ package com.android.systemui.keyguard.domain.interactor import android.app.admin.DevicePolicyManager import android.content.Intent import android.os.UserHandle import androidx.test.filters.SmallTest Loading Loading @@ -54,7 +55,10 @@ import com.android.systemui.util.mockito.whenever import com.android.systemui.util.settings.FakeSettings import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.test.runBlockingTest import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.test.StandardTestDispatcher import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.runTest import org.junit.Before import org.junit.Test import org.junit.runner.RunWith Loading @@ -70,6 +74,7 @@ import org.mockito.Mockito.verify import org.mockito.Mockito.verifyZeroInteractions import org.mockito.MockitoAnnotations @OptIn(ExperimentalCoroutinesApi::class) @SmallTest @RunWith(Parameterized::class) class KeyguardQuickAffordanceInteractorParameterizedTest : SysuiTestCase() { Loading Loading @@ -219,8 +224,10 @@ class KeyguardQuickAffordanceInteractorParameterizedTest : SysuiTestCase() { @Mock private lateinit var expandable: Expandable @Mock private lateinit var launchAnimator: DialogLaunchAnimator @Mock private lateinit var commandQueue: CommandQueue @Mock private lateinit var devicePolicyManager: DevicePolicyManager private lateinit var underTest: KeyguardQuickAffordanceInteractor private lateinit var testScope: TestScope @JvmField @Parameter(0) var needStrongAuthAfterBoot: Boolean = false @JvmField @Parameter(1) var canShowWhileLocked: Boolean = false Loading Loading @@ -292,6 +299,8 @@ class KeyguardQuickAffordanceInteractorParameterizedTest : SysuiTestCase() { set(Flags.CUSTOMIZABLE_LOCK_SCREEN_QUICK_AFFORDANCES, false) set(Flags.FACE_AUTH_REFACTOR, true) } val testDispatcher = StandardTestDispatcher() testScope = TestScope(testDispatcher) underTest = KeyguardQuickAffordanceInteractor( keyguardInteractor = Loading Loading @@ -322,11 +331,14 @@ class KeyguardQuickAffordanceInteractorParameterizedTest : SysuiTestCase() { featureFlags = featureFlags, repository = { quickAffordanceRepository }, launchAnimator = launchAnimator, devicePolicyManager = devicePolicyManager, backgroundDispatcher = testDispatcher, ) } @Test fun onQuickAffordanceTriggered() = runBlockingTest { fun onQuickAffordanceTriggered() = testScope.runTest { setUpMocks( needStrongAuthAfterBoot = needStrongAuthAfterBoot, keyguardIsUnlocked = keyguardIsUnlocked, Loading