summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Josh <jmokut@google.com> 2025-03-20 14:35:43 +0000
committer Android Build Coastguard Worker <android-build-coastguard-worker@google.com> 2025-04-01 20:40:13 -0700
commit140ff5c85a1ed8108934f73531b7e869ae93c29c (patch)
tree00b9e637bee4aa68e5ab4348047fd2ba85b08f26
parentb7c747aaca88ed8b714b7803eb708d29a9d96606 (diff)
use shortcut command as key for retrieving shortcut to be deleted
Shortcut commands can uniquely identify key Input Gestures to be deleted, while Key_gesture_type may not be unique, E.g For Application shortcuts they all share the same key_gesture_type Flag: com.android.systemui.extended_apps_shortcut_category Test: customShortcutCategoriesRepositoryTest Fix: 405058325 (cherry picked from https://googleplex-android-review.googlesource.com/q/commit:45f3acfb441bd86af105321bde3357c9e8aa6bfc) Merged-In: I891ab972456e0799700bc1bbaff29a4b9c6faed5 Change-Id: I891ab972456e0799700bc1bbaff29a4b9c6faed5
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/keyboard/shortcut/data/repository/CustomShortcutCategoriesRepositoryTest.kt44
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/keyboard/shortcut/data/source/TestShortcuts.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyboard/shortcut/data/repository/CustomShortcutCategoriesRepository.kt78
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyboard/shortcut/shared/model/ShortcutCustomizationRequestInfo.kt9
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/composable/ShortcutHelper.kt5
5 files changed, 118 insertions, 20 deletions
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyboard/shortcut/data/repository/CustomShortcutCategoriesRepositoryTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyboard/shortcut/data/repository/CustomShortcutCategoriesRepositoryTest.kt
index 522572dcffb7..0064c09f24ec 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyboard/shortcut/data/repository/CustomShortcutCategoriesRepositoryTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyboard/shortcut/data/repository/CustomShortcutCategoriesRepositoryTest.kt
@@ -30,6 +30,7 @@ import android.hardware.input.fakeInputManager
import android.platform.test.annotations.DisableFlags
import android.platform.test.annotations.EnableFlags
import android.view.KeyEvent.KEYCODE_A
+import android.view.KeyEvent.KEYCODE_B
import android.view.KeyEvent.KEYCODE_SLASH
import android.view.KeyEvent.META_ALT_ON
import android.view.KeyEvent.META_CAPS_LOCK_ON
@@ -55,9 +56,12 @@ import com.android.systemui.keyboard.shortcut.data.source.TestShortcuts.goHomeIn
import com.android.systemui.keyboard.shortcut.data.source.TestShortcuts.launchCalendarShortcutAddRequest
import com.android.systemui.keyboard.shortcut.data.source.TestShortcuts.standardKeyCombination
import com.android.systemui.keyboard.shortcut.shared.model.KeyCombination
+import com.android.systemui.keyboard.shortcut.shared.model.ShortcutCategoryType
import com.android.systemui.keyboard.shortcut.shared.model.ShortcutCustomizationRequestInfo
import com.android.systemui.keyboard.shortcut.shared.model.ShortcutCustomizationRequestInfo.SingleShortcutCustomization
import com.android.systemui.keyboard.shortcut.shared.model.ShortcutKey
+import com.android.systemui.keyboard.shortcut.shared.model.shortcutCommand
+import com.android.systemui.keyboard.shortcut.shortcutHelperInputDeviceRepository
import com.android.systemui.keyboard.shortcut.shortcutHelperTestHelper
import com.android.systemui.kosmos.testScope
import com.android.systemui.kosmos.useUnconfinedTestDispatcher
@@ -293,6 +297,32 @@ class CustomShortcutCategoriesRepositoryTest : SysuiTestCase() {
@Test
@EnableFlags(FLAG_ENABLE_CUSTOMIZABLE_INPUT_GESTURES, FLAG_USE_KEY_GESTURE_EVENT_HANDLER)
+ fun removeAppCategoryShortcut_successfullyRetrievesGestureDataAndDeletesTheCorrectShortcut() {
+ testScope.runTest {
+ // We are collecting this because the flow is a cold flow but we need its value as a
+ // stateflow when deleting a custom shortcut.
+ // TODO remove when refactoring test - use Fakes Instead. b/405358441
+ collectLastValue(kosmos.shortcutHelperInputDeviceRepository.activeInputDevice)
+ var customInputGestures = listOf(ctrlAltAShortcut, ctrlAltBShortcut)
+ whenever(inputManager.getCustomInputGestures(anyOrNull())).then {
+ return@then customInputGestures
+ }
+ whenever(inputManager.removeCustomInputGesture(any())).then {
+ val inputGestureToRemove = it.getArgument<InputGestureData>(0)
+ val containsGesture = customInputGestures.contains(inputGestureToRemove)
+ customInputGestures = customInputGestures - inputGestureToRemove
+ return@then if (containsGesture) CUSTOM_INPUT_GESTURE_RESULT_SUCCESS
+ else CUSTOM_INPUT_GESTURE_RESULT_ERROR_DOES_NOT_EXIST
+ }
+ helper.toggle(deviceId = 123)
+
+ customizeShortcut(customizationRequest = ctrlAltAShortcutDeleteRequest)
+ assertThat(customInputGestures).containsExactly(ctrlAltBShortcut)
+ }
+ }
+
+ @Test
+ @EnableFlags(FLAG_ENABLE_CUSTOMIZABLE_INPUT_GESTURES, FLAG_USE_KEY_GESTURE_EVENT_HANDLER)
fun categories_isUpdatedAfterCustomShortcutIsDeleted() {
testScope.runTest {
// TODO(b/380445594) refactor tests and move these stubbing to ShortcutHelperTestHelper
@@ -436,4 +466,18 @@ class CustomShortcutCategoriesRepositoryTest : SysuiTestCase() {
.setAppLaunchData(appLaunchData)
.build()
}
+
+ private val ctrlAltAShortcut = simpleInputGestureDataForAppLaunchShortcut()
+ private val ctrlAltBShortcut = simpleInputGestureDataForAppLaunchShortcut(keyCode = KEYCODE_B)
+ private val ctrlAltAShortcutDeleteRequest =
+ SingleShortcutCustomization.Delete(
+ categoryType = ShortcutCategoryType.AppCategories,
+ subCategoryLabel = context.getString(R.string.keyboard_shortcut_group_applications),
+ customShortcutCommand =
+ shortcutCommand {
+ key("Ctrl")
+ key("Alt")
+ key("A")
+ },
+ )
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyboard/shortcut/data/source/TestShortcuts.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyboard/shortcut/data/source/TestShortcuts.kt
index 1f74ad496bbb..6f40a21ed639 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyboard/shortcut/data/source/TestShortcuts.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyboard/shortcut/data/source/TestShortcuts.kt
@@ -603,7 +603,7 @@ object TestShortcuts {
label = "Calendar",
categoryType = ShortcutCategoryType.AppCategories,
subCategoryLabel = "Applications",
- shortcutCommand =
+ defaultShortcutCommand =
shortcutCommand {
key("Ctrl")
key("Alt")
diff --git a/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/data/repository/CustomShortcutCategoriesRepository.kt b/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/data/repository/CustomShortcutCategoriesRepository.kt
index 6ae948d2da2e..4e200a3f182f 100644
--- a/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/data/repository/CustomShortcutCategoriesRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/data/repository/CustomShortcutCategoriesRepository.kt
@@ -18,13 +18,15 @@ package com.android.systemui.keyboard.shortcut.data.repository
import android.hardware.input.InputGestureData
import android.hardware.input.InputGestureData.Builder
+import android.hardware.input.InputGestureData.KeyTrigger
import android.hardware.input.InputGestureData.Trigger
import android.hardware.input.InputGestureData.createKeyTrigger
import android.hardware.input.InputManager
+import android.hardware.input.KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_APPLICATION
import android.hardware.input.KeyGestureEvent.KeyGestureType
+import android.hardware.input.KeyGlyphMap
import android.util.Log
import androidx.annotation.VisibleForTesting
-import androidx.compose.runtime.mutableStateOf
import com.android.systemui.Flags.shortcutHelperKeyGlyph
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Background
@@ -34,20 +36,21 @@ import com.android.systemui.keyboard.shortcut.shared.model.ShortcutCategory
import com.android.systemui.keyboard.shortcut.shared.model.ShortcutCategoryType
import com.android.systemui.keyboard.shortcut.shared.model.ShortcutCustomizationRequestInfo
import com.android.systemui.keyboard.shortcut.shared.model.ShortcutCustomizationRequestInfo.SingleShortcutCustomization
+import com.android.systemui.keyboard.shortcut.shared.model.ShortcutCustomizationRequestInfo.SingleShortcutCustomization.Delete
import com.android.systemui.keyboard.shortcut.shared.model.ShortcutKey
+import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.stateIn
-import javax.inject.Inject
@SysUISingleton
class CustomShortcutCategoriesRepository
@Inject
constructor(
- inputDeviceRepository: ShortcutHelperInputDeviceRepository,
+ private val inputDeviceRepository: ShortcutHelperInputDeviceRepository,
@Background private val backgroundScope: CoroutineScope,
private val shortcutCategoriesUtils: ShortcutCategoriesUtils,
private val inputGestureDataAdapter: InputGestureDataAdapter,
@@ -57,7 +60,7 @@ constructor(
) : ShortcutCategoriesRepository {
private val _selectedKeyCombination = MutableStateFlow<KeyCombination?>(null)
- private val _shortcutBeingCustomized = mutableStateOf<ShortcutCustomizationRequestInfo?>(null)
+ private val _shortcutBeingCustomized = MutableStateFlow<ShortcutCustomizationRequestInfo?>(null)
val pressedKeys =
_selectedKeyCombination
@@ -65,10 +68,7 @@ constructor(
if (inputDevice == null || keyCombination == null) {
return@combine emptyList()
} else {
- val keyGlyphMap =
- if (shortcutHelperKeyGlyph()) {
- inputManager.getKeyGlyphMap(inputDevice.id)
- } else null
+ val keyGlyphMap = getKeyGlyphMap(inputDevice.id)
val modifiers =
shortcutCategoriesUtils.toShortcutModifierKeys(
keyCombination.modifiers,
@@ -150,9 +150,27 @@ constructor(
}
private fun retrieveInputGestureDataForShortcutBeingDeleted(): InputGestureData? {
- val keyGestureType = getKeyGestureTypeForShortcutBeingCustomized()
- return customInputGesturesRepository.retrieveCustomInputGestures().firstOrNull {
- it.action.keyGestureType() == keyGestureType
+ val keyGestureTypeForShortcutBeingDeleted = getKeyGestureTypeForShortcutBeingCustomized()
+ val inputGesturesMatchingKeyGestureType =
+ customInputGesturesRepository.retrieveCustomInputGestures().filter {
+ it.action.keyGestureType() == keyGestureTypeForShortcutBeingDeleted
+ }
+
+ return if (keyGestureTypeForShortcutBeingDeleted == KEY_GESTURE_TYPE_LAUNCH_APPLICATION) {
+ val shortcutBeingDeleted = getShortcutBeingCustomized() as Delete
+ if (shortcutBeingDeleted.customShortcutCommand == null){
+ Log.w(TAG, "Requested to delete custom shortcut but customShortcutCommand was null")
+ return null
+ }
+
+ inputGesturesMatchingKeyGestureType.firstOrNull {
+ checkShortcutKeyTriggerEquality(
+ it.trigger,
+ shortcutBeingDeleted.customShortcutCommand.keys,
+ ) ?: false
+ }
+ } else {
+ inputGesturesMatchingKeyGestureType.firstOrNull()
}
}
@@ -181,6 +199,41 @@ constructor(
return customInputGesturesRepository.getInputGestureByTrigger(trigger) == null
}
+ private fun checkShortcutKeyTriggerEquality(
+ trigger: Trigger,
+ keys: List<ShortcutKey>,
+ ): Boolean? {
+ return getConvertedKeyTrigger(trigger)?.containsAll(keys)
+ }
+
+ private fun getConvertedKeyTrigger(trigger: Trigger): List<ShortcutKey>? {
+ if (trigger is KeyTrigger) {
+ val inputDevice = inputDeviceRepository.activeInputDevice.value ?: return null
+
+ val modifierKeys =
+ shortcutCategoriesUtils.toShortcutModifierKeys(
+ keyGlyphMap = getKeyGlyphMap(inputDevice.id),
+ modifiers = trigger.modifierState,
+ ) ?: return null
+
+ val keyCodeShortcutKey =
+ shortcutCategoriesUtils.toShortcutKey(
+ keyGlyphMap = getKeyGlyphMap(inputDevice.id),
+ keyCharacterMap = inputDevice.keyCharacterMap,
+ keyCode = trigger.keycode,
+ ) ?: return null
+
+ return modifierKeys + keyCodeShortcutKey
+ }
+ return null
+ }
+
+ private fun getKeyGlyphMap(deviceId: Int): KeyGlyphMap? {
+ return if (shortcutHelperKeyGlyph()) {
+ inputManager.getKeyGlyphMap(deviceId)
+ } else null
+ }
+
private fun Builder.addKeyGestureTypeForShortcutBeingCustomized(): Builder {
val keyGestureType = getKeyGestureTypeForShortcutBeingCustomized()
@@ -202,8 +255,7 @@ constructor(
return this
}
- val defaultShortcutCommand = shortcutBeingCustomized.shortcutCommand
-
+ val defaultShortcutCommand = shortcutBeingCustomized.defaultShortcutCommand ?: return this
val appLaunchData =
appLaunchDataRepository.getAppLaunchDataForShortcutWithCommand(defaultShortcutCommand)
diff --git a/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/shared/model/ShortcutCustomizationRequestInfo.kt b/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/shared/model/ShortcutCustomizationRequestInfo.kt
index f183247bb355..216af1a8849e 100644
--- a/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/shared/model/ShortcutCustomizationRequestInfo.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/shared/model/ShortcutCustomizationRequestInfo.kt
@@ -18,24 +18,25 @@ package com.android.systemui.keyboard.shortcut.shared.model
sealed interface ShortcutCustomizationRequestInfo {
- sealed interface SingleShortcutCustomization: ShortcutCustomizationRequestInfo {
+ sealed interface SingleShortcutCustomization : ShortcutCustomizationRequestInfo {
val label: String
val categoryType: ShortcutCategoryType
val subCategoryLabel: String
- val shortcutCommand: ShortcutCommand
+ val defaultShortcutCommand: ShortcutCommand?
data class Add(
override val label: String = "",
override val categoryType: ShortcutCategoryType = ShortcutCategoryType.System,
override val subCategoryLabel: String = "",
- override val shortcutCommand: ShortcutCommand = ShortcutCommand(),
+ override val defaultShortcutCommand: ShortcutCommand? = null,
) : SingleShortcutCustomization
data class Delete(
override val label: String = "",
override val categoryType: ShortcutCategoryType = ShortcutCategoryType.System,
override val subCategoryLabel: String = "",
- override val shortcutCommand: ShortcutCommand = ShortcutCommand(),
+ override val defaultShortcutCommand: ShortcutCommand? = null,
+ val customShortcutCommand: ShortcutCommand? = null,
) : SingleShortcutCustomization
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/composable/ShortcutHelper.kt b/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/composable/ShortcutHelper.kt
index 72b984e226e2..92c00fda4a9e 100644
--- a/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/composable/ShortcutHelper.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/composable/ShortcutHelper.kt
@@ -667,7 +667,7 @@ private fun Shortcut(
onShortcutCustomizationRequested(
ShortcutCustomizationRequestInfo.SingleShortcutCustomization.Add(
label = shortcut.label,
- shortcutCommand = shortcut.commands.first(),
+ defaultShortcutCommand = shortcut.commands.firstOrNull { !it.isCustom },
)
)
},
@@ -675,7 +675,8 @@ private fun Shortcut(
onShortcutCustomizationRequested(
ShortcutCustomizationRequestInfo.SingleShortcutCustomization.Delete(
label = shortcut.label,
- shortcutCommand = shortcut.commands.first(),
+ defaultShortcutCommand = shortcut.commands.firstOrNull { !it.isCustom },
+ customShortcutCommand = shortcut.commands.firstOrNull { it.isCustom },
)
)
},