summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Marcello Galhardo <mgalhardo@google.com> 2023-03-09 16:56:16 +0000
committer Android (Google) Code Review <android-gerrit@google.com> 2023-03-09 16:56:16 +0000
commit26ac560f852d5adaf084fad8cc145f846f7e946e (patch)
treef649349d0b368675e50df7da0b6353f7782b7b74
parent341c19726b06b95460a5400bf8e110e6d3af10a6 (diff)
parentd1585902273a5b8d7b16d2257ede48e9967bf9aa (diff)
Merge "Do not set Notetaking shortcut to default if Stylus is not detected" into udc-dev
-rw-r--r--packages/SystemUI/src/com/android/systemui/notetask/quickaffordance/NoteTaskQuickAffordanceConfig.kt61
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/notetask/quickaffordance/NoteTaskQuickAffordanceConfigTest.kt130
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)
}
}