diff options
| author | 2023-03-09 16:56:16 +0000 | |
|---|---|---|
| committer | 2023-03-09 16:56:16 +0000 | |
| commit | 26ac560f852d5adaf084fad8cc145f846f7e946e (patch) | |
| tree | f649349d0b368675e50df7da0b6353f7782b7b74 | |
| parent | 341c19726b06b95460a5400bf8e110e6d3af10a6 (diff) | |
| parent | d1585902273a5b8d7b16d2257ede48e9967bf9aa (diff) | |
Merge "Do not set Notetaking shortcut to default if Stylus is not detected" into udc-dev
2 files changed, 145 insertions, 46 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/notetask/quickaffordance/NoteTaskQuickAffordanceConfig.kt b/packages/SystemUI/src/com/android/systemui/notetask/quickaffordance/NoteTaskQuickAffordanceConfig.kt index 30660c492baa..8aed9958a7a2 100644 --- a/packages/SystemUI/src/com/android/systemui/notetask/quickaffordance/NoteTaskQuickAffordanceConfig.kt +++ b/packages/SystemUI/src/com/android/systemui/notetask/quickaffordance/NoteTaskQuickAffordanceConfig.kt @@ -17,6 +17,7 @@ package com.android.systemui.notetask.quickaffordance import android.content.Context +import android.hardware.input.InputSettings import com.android.systemui.R import com.android.systemui.animation.Expandable import com.android.systemui.common.shared.model.ContentDescription @@ -26,36 +27,52 @@ import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanc import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceConfig.LockScreenState import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceConfig.OnTriggeredResult import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceConfig.PickerScreenState +import com.android.systemui.keyguard.data.repository.KeyguardQuickAffordanceRepository import com.android.systemui.notetask.NoteTaskController import com.android.systemui.notetask.NoteTaskEnabledKey import com.android.systemui.notetask.NoteTaskEntryPoint +import com.android.systemui.stylus.StylusManager +import dagger.Lazy import javax.inject.Inject -import kotlinx.coroutines.flow.flowOf +import kotlinx.coroutines.channels.awaitClose +import kotlinx.coroutines.channels.trySendBlocking +import kotlinx.coroutines.flow.callbackFlow +import kotlinx.coroutines.flow.combine +import kotlinx.coroutines.flow.map class NoteTaskQuickAffordanceConfig @Inject constructor( context: Context, - private val noteTaskController: NoteTaskController, + private val controller: NoteTaskController, + private val stylusManager: StylusManager, + private val lazyRepository: Lazy<KeyguardQuickAffordanceRepository>, @NoteTaskEnabledKey private val isEnabled: Boolean, ) : KeyguardQuickAffordanceConfig { override val key = BuiltInKeyguardQuickAffordanceKeys.CREATE_NOTE - override val pickerName: String = context.getString(R.string.note_task_button_label) + private val pickerNameResourceId = R.string.note_task_button_label - override val pickerIconResourceId = R.drawable.ic_note_task_shortcut_keyguard + override val pickerName: String = context.getString(pickerNameResourceId) - override val lockScreenState = flowOf(getLockScreenState()) + override val pickerIconResourceId = R.drawable.ic_note_task_shortcut_keyguard - // TODO(b/265949213) - private fun getLockScreenState() = - if (isEnabled) { - val icon = Icon.Resource(pickerIconResourceId, ContentDescription.Loaded(pickerName)) - LockScreenState.Visible(icon) - } else { - LockScreenState.Hidden + // Due to a dependency cycle with KeyguardQuickAffordanceRepository, we need to lazily access + // the repository when lockScreenState is accessed for the first time. + override val lockScreenState by lazy { + val stylusEverUsedFlow = createStylusEverUsedFlow(context, stylusManager) + val configSelectedFlow = createConfigSelectedFlow(lazyRepository.get(), key) + combine(configSelectedFlow, stylusEverUsedFlow) { isSelected, isStylusEverUsed -> + if (isEnabled && (isSelected || isStylusEverUsed)) { + val contentDescription = ContentDescription.Resource(pickerNameResourceId) + val icon = Icon.Resource(pickerIconResourceId, contentDescription) + LockScreenState.Visible(icon) + } else { + LockScreenState.Hidden + } } + } override suspend fun getPickerScreenState() = if (isEnabled) { @@ -65,9 +82,27 @@ constructor( } override fun onTriggered(expandable: Expandable?): OnTriggeredResult { - noteTaskController.showNoteTask( + controller.showNoteTask( entryPoint = NoteTaskEntryPoint.QUICK_AFFORDANCE, ) return OnTriggeredResult.Handled } } + +private fun createStylusEverUsedFlow(context: Context, stylusManager: StylusManager) = + callbackFlow { + trySendBlocking(InputSettings.isStylusEverUsed(context)) + val callback = + object : StylusManager.StylusCallback { + override fun onStylusFirstUsed() { + trySendBlocking(InputSettings.isStylusEverUsed(context)) + } + } + stylusManager.registerCallback(callback) + awaitClose { stylusManager.unregisterCallback(callback) } + } + +private fun createConfigSelectedFlow(repository: KeyguardQuickAffordanceRepository, key: String) = + repository.selections.map { selected -> + selected.values.flatten().any { selectedConfig -> selectedConfig.key == key } + } diff --git a/packages/SystemUI/tests/src/com/android/systemui/notetask/quickaffordance/NoteTaskQuickAffordanceConfigTest.kt b/packages/SystemUI/tests/src/com/android/systemui/notetask/quickaffordance/NoteTaskQuickAffordanceConfigTest.kt index e57d0d943aab..d44012f31fa5 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/notetask/quickaffordance/NoteTaskQuickAffordanceConfigTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/notetask/quickaffordance/NoteTaskQuickAffordanceConfigTest.kt @@ -18,75 +18,139 @@ package com.android.systemui.notetask.quickaffordance +import android.hardware.input.InputSettings import android.test.suitebuilder.annotation.SmallTest -import androidx.test.runner.AndroidJUnit4 +import android.testing.AndroidTestingRunner +import com.android.dx.mockito.inline.extended.ExtendedMockito import com.android.systemui.R import com.android.systemui.SysuiTestCase 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.data.quickaffordance.KeyguardQuickAffordanceConfig import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceConfig.LockScreenState +import com.android.systemui.keyguard.data.repository.KeyguardQuickAffordanceRepository import com.android.systemui.notetask.NoteTaskController import com.android.systemui.notetask.NoteTaskEntryPoint +import com.android.systemui.stylus.StylusManager +import com.android.systemui.util.mockito.whenever import com.google.common.truth.Truth.assertThat import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.test.runTest +import org.junit.After import org.junit.Before import org.junit.Test import org.junit.runner.RunWith import org.mockito.Mock import org.mockito.Mockito.verify -import org.mockito.MockitoAnnotations +import org.mockito.MockitoSession +import org.mockito.quality.Strictness -/** - * Tests for [NoteTaskQuickAffordanceConfig]. - * - * Build/Install/Run: - * - atest SystemUITests:NoteTaskQuickAffordanceConfigTest - */ +/** atest SystemUITests:NoteTaskQuickAffordanceConfigTest */ @SmallTest -@RunWith(AndroidJUnit4::class) +@RunWith(AndroidTestingRunner::class) internal class NoteTaskQuickAffordanceConfigTest : SysuiTestCase() { - @Mock lateinit var noteTaskController: NoteTaskController + @Mock lateinit var controller: NoteTaskController + @Mock lateinit var stylusManager: StylusManager + @Mock lateinit var repository: KeyguardQuickAffordanceRepository + + private lateinit var mockitoSession: MockitoSession @Before fun setUp() { - MockitoAnnotations.initMocks(this) + mockitoSession = + ExtendedMockito.mockitoSession() + .initMocks(this) + .mockStatic(InputSettings::class.java) + .strictness(Strictness.LENIENT) + .startMocking() + + whenever(InputSettings.isStylusEverUsed(mContext)).then { true } + whenever(repository.selections).then { + val map = mapOf("" to listOf(createUnderTest())) + MutableStateFlow(map) + } } - private fun createUnderTest(isEnabled: Boolean) = + @After + fun tearDown() { + mockitoSession.finishMocking() + } + + private fun createUnderTest(isEnabled: Boolean = true): KeyguardQuickAffordanceConfig = NoteTaskQuickAffordanceConfig( context = context, - noteTaskController = noteTaskController, + controller = controller, + stylusManager = stylusManager, + lazyRepository = { repository }, isEnabled = isEnabled, ) + private fun createLockScreenStateVisible(): LockScreenState = + LockScreenState.Visible( + icon = + Icon.Resource( + res = R.drawable.ic_note_task_shortcut_keyguard, + contentDescription = + ContentDescription.Resource(R.string.note_task_button_label), + ) + ) + @Test - fun lockScreenState_isNotEnabled_shouldEmitHidden() = runTest { - val underTest = createUnderTest(isEnabled = false) + fun lockScreenState_stylusUsed_noCustomShortcutSelected_shouldEmitVisible() = runTest { + val underTest = createUnderTest() + + val actual by collectLastValue(underTest.lockScreenState) + + assertThat(actual).isEqualTo(createLockScreenStateVisible()) + } + + @Test + fun lockScreenState_noStylusEverUsed_noCustomShortcutSelected_shouldEmitVisible() = runTest { + whenever(InputSettings.isStylusEverUsed(mContext)).then { false } + val underTest = createUnderTest() - val actual = collectLastValue(underTest.lockScreenState) + val actual by collectLastValue(underTest.lockScreenState) - assertThat(actual()).isEqualTo(LockScreenState.Hidden) + assertThat(actual).isEqualTo(createLockScreenStateVisible()) } @Test - fun lockScreenState_isEnabled_shouldEmitVisible() = runTest { - val stringResult = "Notetaking" - val underTest = createUnderTest(isEnabled = true) - - val actual = collectLastValue(underTest.lockScreenState) - - val expected = - LockScreenState.Visible( - icon = - Icon.Resource( - res = R.drawable.ic_note_task_shortcut_keyguard, - contentDescription = ContentDescription.Loaded(stringResult), - ) - ) - assertThat(actual()).isEqualTo(expected) + fun lockScreenState_stylusUsed_customShortcutSelected_shouldEmitVisible() = runTest { + whenever(repository.selections).then { + val map = mapOf<String, List<KeyguardQuickAffordanceConfig>>() + MutableStateFlow(map) + } + val underTest = createUnderTest() + + val actual by collectLastValue(underTest.lockScreenState) + + assertThat(actual).isEqualTo(createLockScreenStateVisible()) + } + + @Test + fun lockScreenState_noIsStylusEverUsed_noCustomShortcutSelected_shouldEmitHidden() = runTest { + whenever(InputSettings.isStylusEverUsed(mContext)).then { false } + whenever(repository.selections).then { + val map = mapOf<String, List<KeyguardQuickAffordanceConfig>>() + MutableStateFlow(map) + } + val underTest = createUnderTest() + + val actual by collectLastValue(underTest.lockScreenState) + + assertThat(actual).isEqualTo(LockScreenState.Hidden) + } + + @Test + fun lockScreenState_isNotEnabled_shouldEmitHidden() = runTest { + val underTest = createUnderTest(isEnabled = false) + + val actual by collectLastValue(underTest.lockScreenState) + + assertThat(actual).isEqualTo(LockScreenState.Hidden) } @Test @@ -95,6 +159,6 @@ internal class NoteTaskQuickAffordanceConfigTest : SysuiTestCase() { underTest.onTriggered(expandable = null) - verify(noteTaskController).showNoteTask(entryPoint = NoteTaskEntryPoint.QUICK_AFFORDANCE) + verify(controller).showNoteTask(entryPoint = NoteTaskEntryPoint.QUICK_AFFORDANCE) } } |