diff options
5 files changed, 92 insertions, 15 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/view/ShortcutHelperActivity.kt b/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/view/ShortcutHelperActivity.kt index b8d0c23e6c29..20397431659b 100644 --- a/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/view/ShortcutHelperActivity.kt +++ b/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/view/ShortcutHelperActivity.kt @@ -26,8 +26,10 @@ import android.view.WindowInsets import androidx.activity.BackEventCompat import androidx.activity.ComponentActivity import androidx.activity.OnBackPressedCallback +import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.runtime.getValue import androidx.compose.ui.platform.ComposeView +import androidx.compose.ui.platform.LocalContext import androidx.core.view.updatePadding import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.lifecycle.flowWithLifecycle @@ -36,6 +38,7 @@ import com.android.compose.theme.PlatformTheme import com.android.systemui.keyboard.shortcut.ui.composable.ShortcutHelper import com.android.systemui.keyboard.shortcut.ui.viewmodel.ShortcutHelperViewModel import com.android.systemui.res.R +import com.android.systemui.settings.UserTracker import com.google.android.material.bottomsheet.BottomSheetBehavior import com.google.android.material.bottomsheet.BottomSheetBehavior.BottomSheetCallback import com.google.android.material.bottomsheet.BottomSheetBehavior.STATE_HIDDEN @@ -49,6 +52,7 @@ import kotlinx.coroutines.launch class ShortcutHelperActivity @Inject constructor( + private val userTracker: UserTracker, private val viewModel: ShortcutHelperViewModel, ) : ComponentActivity() { @@ -79,13 +83,16 @@ constructor( private fun setUpComposeView() { requireViewById<ComposeView>(R.id.shortcut_helper_compose_container).apply { setContent { - PlatformTheme { - val shortcutsUiState by viewModel.shortcutsUiState.collectAsStateWithLifecycle() - ShortcutHelper( - shortcutsUiState = shortcutsUiState, - onKeyboardSettingsClicked = ::onKeyboardSettingsClicked, - onSearchQueryChanged = { viewModel.onSearchQueryChanged(it) }, - ) + CompositionLocalProvider(LocalContext provides userTracker.userContext) { + PlatformTheme { + val shortcutsUiState by + viewModel.shortcutsUiState.collectAsStateWithLifecycle() + ShortcutHelper( + shortcutsUiState = shortcutsUiState, + onKeyboardSettingsClicked = ::onKeyboardSettingsClicked, + onSearchQueryChanged = { viewModel.onSearchQueryChanged(it) }, + ) + } } } } @@ -93,7 +100,10 @@ constructor( private fun onKeyboardSettingsClicked() { try { - startActivity(Intent(Settings.ACTION_HARD_KEYBOARD_SETTINGS)) + startActivityAsUser( + Intent(Settings.ACTION_HARD_KEYBOARD_SETTINGS), + userTracker.userHandle + ) } catch (e: ActivityNotFoundException) { // From the Settings docs: In some cases, a matching Activity may not exist, so ensure // you safeguard against this. diff --git a/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/viewmodel/ShortcutHelperViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/viewmodel/ShortcutHelperViewModel.kt index e64cc807ab25..19b46e3689aa 100644 --- a/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/viewmodel/ShortcutHelperViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/viewmodel/ShortcutHelperViewModel.kt @@ -16,6 +16,7 @@ package com.android.systemui.keyboard.shortcut.ui.viewmodel +import android.app.role.RoleManager import com.android.systemui.dagger.qualifiers.Background import com.android.systemui.keyboard.shortcut.domain.interactor.ShortcutHelperCategoriesInteractor import com.android.systemui.keyboard.shortcut.domain.interactor.ShortcutHelperStateInteractor @@ -25,6 +26,7 @@ import com.android.systemui.keyboard.shortcut.shared.model.ShortcutCategoryType import com.android.systemui.keyboard.shortcut.shared.model.ShortcutCategoryType.CurrentApp import com.android.systemui.keyboard.shortcut.shared.model.ShortcutSubCategory import com.android.systemui.keyboard.shortcut.ui.model.ShortcutsUiState +import com.android.systemui.settings.UserTracker import javax.inject.Inject import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.CoroutineScope @@ -35,10 +37,13 @@ import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.flowOn import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.stateIn +import kotlinx.coroutines.withContext class ShortcutHelperViewModel @Inject constructor( + private val roleManager: RoleManager, + private val userTracker: UserTracker, @Background private val backgroundScope: CoroutineScope, @Background private val backgroundDispatcher: CoroutineDispatcher, private val stateInteractor: ShortcutHelperStateInteractor, @@ -72,13 +77,22 @@ constructor( initialValue = ShortcutsUiState.Inactive ) - private fun getDefaultSelectedCategory( + private suspend fun getDefaultSelectedCategory( categories: List<ShortcutCategory> ): ShortcutCategoryType? { - val currentAppShortcuts = categories.firstOrNull { it.type is CurrentApp } + val currentAppShortcuts = + categories.firstOrNull { it.type is CurrentApp && !isAppLauncher(it.type.packageName) } return currentAppShortcuts?.type ?: categories.firstOrNull()?.type } + private suspend fun isAppLauncher(packageName: String): Boolean { + return withContext(backgroundDispatcher) { + roleManager + .getRoleHoldersAsUser(RoleManager.ROLE_HOME, userTracker.userHandle) + .firstOrNull() == packageName + } + } + private fun filterCategoriesBySearchQuery( query: String, categories: List<ShortcutCategory> diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyboard/shortcut/ui/viewmodel/ShortcutHelperViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyboard/shortcut/ui/viewmodel/ShortcutHelperViewModelTest.kt index 004317370c22..6b607400edfd 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyboard/shortcut/ui/viewmodel/ShortcutHelperViewModelTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/keyboard/shortcut/ui/viewmodel/ShortcutHelperViewModelTest.kt @@ -16,6 +16,8 @@ package com.android.systemui.keyboard.shortcut.ui.viewmodel +import android.app.role.RoleManager +import android.app.role.mockRoleManager import android.view.KeyEvent import android.view.KeyboardShortcutGroup import android.view.KeyboardShortcutInfo @@ -45,7 +47,9 @@ import com.android.systemui.kosmos.testCase import com.android.systemui.kosmos.testDispatcher import com.android.systemui.kosmos.testScope import com.android.systemui.model.sysUiState +import com.android.systemui.settings.fakeUserTracker import com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_SHORTCUT_HELPER_SHOWING +import com.android.systemui.util.mockito.whenever import com.google.common.truth.Truth.assertThat import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.test.UnconfinedTestDispatcher @@ -77,12 +81,15 @@ class ShortcutHelperViewModelTest : SysuiTestCase() { private val testScope = kosmos.testScope private val testHelper = kosmos.shortcutHelperTestHelper private val sysUiState = kosmos.sysUiState + private val fakeUserTracker = kosmos.fakeUserTracker + private val mockRoleManager = kosmos.mockRoleManager private val viewModel = kosmos.shortcutHelperViewModel @Before fun setUp() { fakeSystemSource.setGroups(TestShortcuts.systemGroups) fakeMultiTaskingSource.setGroups(TestShortcuts.multitaskingGroups) + fakeCurrentAppsSource.setGroups(TestShortcuts.currentAppGroups) } @Test @@ -216,21 +223,21 @@ class ShortcutHelperViewModelTest : SysuiTestCase() { } @Test - fun shortcutsUiState_featureActive_emitsActiveWithFirstCategorySelectedByDefault() = + fun shortcutsUiState_noCurrentAppCategory_defaultSelectedCategoryIsSystem() = testScope.runTest { + fakeCurrentAppsSource.setGroups(emptyList()) + val uiState by collectLastValue(viewModel.shortcutsUiState) testHelper.showFromActivity() val activeUiState = uiState as ShortcutsUiState.Active - assertThat(activeUiState.defaultSelectedCategory) - .isEqualTo(activeUiState.shortcutCategories.first().type) + assertThat(activeUiState.defaultSelectedCategory).isEqualTo(System) } @Test - fun shortcutsUiState_featureActive_emitsActiveWithCurrentAppsCategorySelectedWhenPresent() = + fun shortcutsUiState_currentAppCategoryPresent_currentAppIsDefaultSelected() = testScope.runTest { - fakeCurrentAppsSource.setGroups(TestShortcuts.currentAppGroups) val uiState by collectLastValue(viewModel.shortcutsUiState) testHelper.showFromActivity() @@ -241,6 +248,24 @@ class ShortcutHelperViewModelTest : SysuiTestCase() { } @Test + fun shortcutsUiState_currentAppIsLauncher_defaultSelectedCategoryIsSystem() = + testScope.runTest { + whenever( + mockRoleManager.getRoleHoldersAsUser( + RoleManager.ROLE_HOME, + fakeUserTracker.userHandle + ) + ) + .thenReturn(listOf(TestShortcuts.currentAppPackageName)) + val uiState by collectLastValue(viewModel.shortcutsUiState) + + testHelper.showFromActivity() + + val activeUiState = uiState as ShortcutsUiState.Active + assertThat(activeUiState.defaultSelectedCategory).isEqualTo(System) + } + + @Test fun shortcutsUiState_userTypedQuery_filtersMatchingShortcutLabels() = testScope.runTest { fakeSystemSource.setGroups( diff --git a/packages/SystemUI/tests/utils/src/android/app/role/RoleManagerKosmos.kt b/packages/SystemUI/tests/utils/src/android/app/role/RoleManagerKosmos.kt new file mode 100644 index 000000000000..356bc86b83df --- /dev/null +++ b/packages/SystemUI/tests/utils/src/android/app/role/RoleManagerKosmos.kt @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.app.role + +import com.android.systemui.kosmos.Kosmos +import com.android.systemui.util.mockito.mock + +val Kosmos.mockRoleManager: RoleManager by Kosmos.Fixture { mock() } + +var Kosmos.roleManager: RoleManager by Kosmos.Fixture { mockRoleManager } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyboard/shortcut/KeyboardShortcutHelperKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyboard/shortcut/KeyboardShortcutHelperKosmos.kt index c423b626b3a7..c2a03d46cd30 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyboard/shortcut/KeyboardShortcutHelperKosmos.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyboard/shortcut/KeyboardShortcutHelperKosmos.kt @@ -16,6 +16,7 @@ package com.android.systemui.keyboard.shortcut +import android.app.role.mockRoleManager import android.content.applicationContext import android.content.res.mainResources import android.hardware.input.fakeInputManager @@ -41,6 +42,7 @@ import com.android.systemui.kosmos.testDispatcher import com.android.systemui.kosmos.testScope import com.android.systemui.model.sysUiState import com.android.systemui.settings.displayTracker +import com.android.systemui.settings.fakeUserTracker var Kosmos.shortcutHelperAppCategoriesShortcutsSource: KeyboardShortcutGroupsSource by Kosmos.Fixture { @@ -117,6 +119,8 @@ val Kosmos.shortcutHelperCategoriesInteractor by val Kosmos.shortcutHelperViewModel by Kosmos.Fixture { ShortcutHelperViewModel( + mockRoleManager, + fakeUserTracker, applicationCoroutineScope, testDispatcher, shortcutHelperStateInteractor, |