Merge "Do not set Notetaking shortcut to default if Stylus is not detected" into udc-dev am: 26ac560f85

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/21649738

Change-Id: Ie977cc01c75fd71409c20d96d59b41aaa7594589
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
Marcello Galhardo
2023-03-09 17:30:24 +00:00
committed by Automerger Merge Worker
2 changed files with 146 additions and 47 deletions

View File

@@ -17,6 +17,7 @@
package com.android.systemui.notetask.quickaffordance package com.android.systemui.notetask.quickaffordance
import android.content.Context import android.content.Context
import android.hardware.input.InputSettings
import com.android.systemui.R import com.android.systemui.R
import com.android.systemui.animation.Expandable import com.android.systemui.animation.Expandable
import com.android.systemui.common.shared.model.ContentDescription 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.LockScreenState
import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceConfig.OnTriggeredResult import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceConfig.OnTriggeredResult
import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceConfig.PickerScreenState 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.NoteTaskController
import com.android.systemui.notetask.NoteTaskEnabledKey import com.android.systemui.notetask.NoteTaskEnabledKey
import com.android.systemui.notetask.NoteTaskEntryPoint import com.android.systemui.notetask.NoteTaskEntryPoint
import com.android.systemui.stylus.StylusManager
import dagger.Lazy
import javax.inject.Inject 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 class NoteTaskQuickAffordanceConfig
@Inject @Inject
constructor( constructor(
context: Context, context: Context,
private val noteTaskController: NoteTaskController, private val controller: NoteTaskController,
private val stylusManager: StylusManager,
private val lazyRepository: Lazy<KeyguardQuickAffordanceRepository>,
@NoteTaskEnabledKey private val isEnabled: Boolean, @NoteTaskEnabledKey private val isEnabled: Boolean,
) : KeyguardQuickAffordanceConfig { ) : KeyguardQuickAffordanceConfig {
override val key = BuiltInKeyguardQuickAffordanceKeys.CREATE_NOTE 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 pickerName: String = context.getString(pickerNameResourceId)
override val pickerIconResourceId = R.drawable.ic_note_task_shortcut_keyguard override val pickerIconResourceId = R.drawable.ic_note_task_shortcut_keyguard
override val lockScreenState = flowOf(getLockScreenState()) // Due to a dependency cycle with KeyguardQuickAffordanceRepository, we need to lazily access
// the repository when lockScreenState is accessed for the first time.
// TODO(b/265949213) override val lockScreenState by lazy {
private fun getLockScreenState() = val stylusEverUsedFlow = createStylusEverUsedFlow(context, stylusManager)
if (isEnabled) { val configSelectedFlow = createConfigSelectedFlow(lazyRepository.get(), key)
val icon = Icon.Resource(pickerIconResourceId, ContentDescription.Loaded(pickerName)) combine(configSelectedFlow, stylusEverUsedFlow) { isSelected, isStylusEverUsed ->
if (isEnabled && (isSelected || isStylusEverUsed)) {
val contentDescription = ContentDescription.Resource(pickerNameResourceId)
val icon = Icon.Resource(pickerIconResourceId, contentDescription)
LockScreenState.Visible(icon) LockScreenState.Visible(icon)
} else { } else {
LockScreenState.Hidden LockScreenState.Hidden
} }
}
}
override suspend fun getPickerScreenState() = override suspend fun getPickerScreenState() =
if (isEnabled) { if (isEnabled) {
@@ -65,9 +82,27 @@ constructor(
} }
override fun onTriggered(expandable: Expandable?): OnTriggeredResult { override fun onTriggered(expandable: Expandable?): OnTriggeredResult {
noteTaskController.showNoteTask( controller.showNoteTask(
entryPoint = NoteTaskEntryPoint.QUICK_AFFORDANCE, entryPoint = NoteTaskEntryPoint.QUICK_AFFORDANCE,
) )
return OnTriggeredResult.Handled 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 }
}

View File

@@ -18,75 +18,139 @@
package com.android.systemui.notetask.quickaffordance package com.android.systemui.notetask.quickaffordance
import android.hardware.input.InputSettings
import android.test.suitebuilder.annotation.SmallTest 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.R
import com.android.systemui.SysuiTestCase import com.android.systemui.SysuiTestCase
import com.android.systemui.common.shared.model.ContentDescription import com.android.systemui.common.shared.model.ContentDescription
import com.android.systemui.common.shared.model.Icon import com.android.systemui.common.shared.model.Icon
import com.android.systemui.coroutines.collectLastValue 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.quickaffordance.KeyguardQuickAffordanceConfig.LockScreenState
import com.android.systemui.keyguard.data.repository.KeyguardQuickAffordanceRepository
import com.android.systemui.notetask.NoteTaskController import com.android.systemui.notetask.NoteTaskController
import com.android.systemui.notetask.NoteTaskEntryPoint 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 com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.test.runTest import kotlinx.coroutines.test.runTest
import org.junit.After
import org.junit.Before import org.junit.Before
import org.junit.Test import org.junit.Test
import org.junit.runner.RunWith import org.junit.runner.RunWith
import org.mockito.Mock import org.mockito.Mock
import org.mockito.Mockito.verify import org.mockito.Mockito.verify
import org.mockito.MockitoAnnotations import org.mockito.MockitoSession
import org.mockito.quality.Strictness
/** /** atest SystemUITests:NoteTaskQuickAffordanceConfigTest */
* Tests for [NoteTaskQuickAffordanceConfig].
*
* Build/Install/Run:
* - atest SystemUITests:NoteTaskQuickAffordanceConfigTest
*/
@SmallTest @SmallTest
@RunWith(AndroidJUnit4::class) @RunWith(AndroidTestingRunner::class)
internal class NoteTaskQuickAffordanceConfigTest : SysuiTestCase() { 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 @Before
fun setUp() { 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( NoteTaskQuickAffordanceConfig(
context = context, context = context,
noteTaskController = noteTaskController, controller = controller,
stylusManager = stylusManager,
lazyRepository = { repository },
isEnabled = isEnabled, 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_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 by collectLastValue(underTest.lockScreenState)
assertThat(actual).isEqualTo(createLockScreenStateVisible())
}
@Test
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 @Test
fun lockScreenState_isNotEnabled_shouldEmitHidden() = runTest { fun lockScreenState_isNotEnabled_shouldEmitHidden() = runTest {
val underTest = createUnderTest(isEnabled = false) val underTest = createUnderTest(isEnabled = false)
val actual = collectLastValue(underTest.lockScreenState) val actual by collectLastValue(underTest.lockScreenState)
assertThat(actual()).isEqualTo(LockScreenState.Hidden) assertThat(actual).isEqualTo(LockScreenState.Hidden)
}
@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)
} }
@Test @Test
@@ -95,6 +159,6 @@ internal class NoteTaskQuickAffordanceConfigTest : SysuiTestCase() {
underTest.onTriggered(expandable = null) underTest.onTriggered(expandable = null)
verify(noteTaskController).showNoteTask(entryPoint = NoteTaskEntryPoint.QUICK_AFFORDANCE) verify(controller).showNoteTask(entryPoint = NoteTaskEntryPoint.QUICK_AFFORDANCE)
} }
} }