diff options
author | 2025-03-20 14:35:43 +0000 | |
---|---|---|
committer | 2025-04-01 20:40:13 -0700 | |
commit | 140ff5c85a1ed8108934f73531b7e869ae93c29c (patch) | |
tree | 00b9e637bee4aa68e5ab4348047fd2ba85b08f26 | |
parent | b7c747aaca88ed8b714b7803eb708d29a9d96606 (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
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 }, ) ) }, |