Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit da55b812 authored by Joshua Mokut's avatar Joshua Mokut Committed by Android (Google) Code Review
Browse files

Merge "Fixed crashes due to HSUM issues" into main

parents 2839ddd9 c165fabf
Loading
Loading
Loading
Loading
+15 −71
Original line number Diff line number Diff line
@@ -16,10 +16,7 @@

package com.android.systemui.keyboard.shortcut.ui.composable

import android.content.Context
import android.content.pm.PackageManager.NameNotFoundException
import android.graphics.drawable.Icon
import android.util.Log
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.core.animateFloatAsState
import androidx.compose.foundation.Image
@@ -55,12 +52,8 @@ import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.OpenInNew
import androidx.compose.material.icons.filled.Apps
import androidx.compose.material.icons.filled.ExpandMore
import androidx.compose.material.icons.filled.Keyboard
import androidx.compose.material.icons.filled.Search
import androidx.compose.material.icons.filled.Tv
import androidx.compose.material.icons.filled.VerticalSplit
import androidx.compose.material3.CenterAlignedTopAppBar
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.HorizontalDivider
@@ -111,16 +104,15 @@ import androidx.compose.ui.util.fastForEachIndexed
import com.android.compose.modifiers.thenIf
import com.android.compose.ui.graphics.painter.rememberDrawablePainter
import com.android.systemui.keyboard.shortcut.shared.model.Shortcut as ShortcutModel
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.ShortcutCommand
import com.android.systemui.keyboard.shortcut.shared.model.ShortcutIcon
import com.android.systemui.keyboard.shortcut.shared.model.ShortcutKey
import com.android.systemui.keyboard.shortcut.shared.model.ShortcutSubCategory
import com.android.systemui.keyboard.shortcut.ui.model.IconSource
import com.android.systemui.keyboard.shortcut.ui.model.ShortcutCategoryUi
import com.android.systemui.keyboard.shortcut.ui.model.ShortcutsUiState
import com.android.systemui.res.R
import com.android.systemui.statusbar.phone.CentralSurfaces

@Composable
fun ShortcutHelper(
@@ -187,7 +179,7 @@ private fun ActiveShortcutHelper(
private fun ShortcutHelperSinglePane(
    searchQuery: String,
    onSearchQueryChanged: (String) -> Unit,
    categories: List<ShortcutCategory>,
    categories: List<ShortcutCategoryUi>,
    selectedCategoryType: ShortcutCategoryType?,
    onCategorySelected: (ShortcutCategoryType?) -> Unit,
    onKeyboardSettingsClicked: () -> Unit,
@@ -228,7 +220,7 @@ private fun ShortcutHelperSinglePane(
@Composable
private fun CategoriesPanelSinglePane(
    searchQuery: String,
    categories: List<ShortcutCategory>,
    categories: List<ShortcutCategoryUi>,
    selectedCategoryType: ShortcutCategoryType?,
    onCategorySelected: (ShortcutCategoryType?) -> Unit,
) {
@@ -267,7 +259,7 @@ private fun CategoriesPanelSinglePane(
@Composable
private fun CategoryItemSinglePane(
    searchQuery: String,
    category: ShortcutCategory,
    category: ShortcutCategoryUi,
    isExpanded: Boolean,
    onClick: () -> Unit,
    shape: Shape,
@@ -278,9 +270,9 @@ private fun CategoryItemSinglePane(
                verticalAlignment = Alignment.CenterVertically,
                modifier = Modifier.fillMaxWidth().heightIn(min = 88.dp).padding(horizontal = 16.dp),
            ) {
                ShortcutCategoryIcon(modifier = Modifier.size(24.dp), source = category.icon)
                ShortcutCategoryIcon(modifier = Modifier.size(24.dp), source = category.iconSource)
                Spacer(modifier = Modifier.width(16.dp))
                Text(category.label(LocalContext.current))
                Text(category.label)
                Spacer(modifier = Modifier.weight(1f))
                RotatingExpandCollapseIcon(isExpanded)
            }
@@ -291,23 +283,6 @@ private fun CategoryItemSinglePane(
    }
}

private val ShortcutCategory.icon: IconSource
    @Composable
    get() =
        when (type) {
            ShortcutCategoryType.System -> IconSource(imageVector = Icons.Default.Tv)
            ShortcutCategoryType.MultiTasking ->
                IconSource(imageVector = Icons.Default.VerticalSplit)
            ShortcutCategoryType.InputMethodEditor ->
                IconSource(imageVector = Icons.Default.Keyboard)
            ShortcutCategoryType.AppCategories -> IconSource(imageVector = Icons.Default.Apps)
            is ShortcutCategoryType.CurrentApp -> {
                val context = LocalContext.current
                val iconDrawable = context.packageManager.getApplicationIcon(type.packageName)
                IconSource(painter = rememberDrawablePainter(drawable = iconDrawable))
            }
        }

@Composable
fun ShortcutCategoryIcon(
    source: IconSource,
@@ -322,37 +297,6 @@ fun ShortcutCategoryIcon(
    }
}

private fun ShortcutCategory.label(context: Context): String =
    when (type) {
        ShortcutCategoryType.System -> context.getString(R.string.shortcut_helper_category_system)
        ShortcutCategoryType.MultiTasking ->
            context.getString(R.string.shortcut_helper_category_multitasking)
        ShortcutCategoryType.InputMethodEditor ->
            context.getString(R.string.shortcut_helper_category_input)
        ShortcutCategoryType.AppCategories ->
            context.getString(R.string.shortcut_helper_category_app_shortcuts)
        is ShortcutCategoryType.CurrentApp -> getApplicationLabelForCurrentApp(type, context)
    }

private fun getApplicationLabelForCurrentApp(
    type: ShortcutCategoryType.CurrentApp,
    context: Context,
): String {
    val packageManagerForUser = CentralSurfaces.getPackageManagerForUser(context, context.userId)
    return try {
        val currentAppInfo =
            packageManagerForUser.getApplicationInfoAsUser(
                type.packageName,
                /* flags = */ 0,
                context.userId,
            )
        packageManagerForUser.getApplicationLabel(currentAppInfo).toString()
    } catch (e: NameNotFoundException) {
        Log.wtf(ShortcutHelper.TAG, "Couldn't find app info by package name ${type.packageName}")
        context.getString(R.string.shortcut_helper_category_current_app_shortcuts)
    }
}

@Composable
private fun RotatingExpandCollapseIcon(isExpanded: Boolean) {
    val expandIconRotationDegrees by
@@ -384,7 +328,7 @@ private fun RotatingExpandCollapseIcon(isExpanded: Boolean) {
}

@Composable
private fun ShortcutCategoryDetailsSinglePane(searchQuery: String, category: ShortcutCategory) {
private fun ShortcutCategoryDetailsSinglePane(searchQuery: String, category: ShortcutCategoryUi) {
    Column(Modifier.padding(horizontal = 16.dp)) {
        category.subCategories.fastForEach { subCategory ->
            ShortcutSubCategorySinglePane(searchQuery, subCategory)
@@ -409,7 +353,7 @@ private fun ShortcutHelperTwoPane(
    searchQuery: String,
    onSearchQueryChanged: (String) -> Unit,
    modifier: Modifier = Modifier,
    categories: List<ShortcutCategory>,
    categories: List<ShortcutCategoryUi>,
    selectedCategoryType: ShortcutCategoryType?,
    onCategorySelected: (ShortcutCategoryType?) -> Unit,
    onKeyboardSettingsClicked: () -> Unit,
@@ -434,7 +378,7 @@ private fun ShortcutHelperTwoPane(
}

@Composable
private fun EndSidePanel(searchQuery: String, modifier: Modifier, category: ShortcutCategory?) {
private fun EndSidePanel(searchQuery: String, modifier: Modifier, category: ShortcutCategoryUi?) {
    val listState = rememberLazyListState()
    LaunchedEffect(key1 = category) { if (category != null) listState.animateScrollToItem(0) }
    if (category == null) {
@@ -670,10 +614,10 @@ private fun textWithHighlightedSearchQuery(text: String, searchValue: String) =
private fun StartSidePanel(
    onSearchQueryChanged: (String) -> Unit,
    modifier: Modifier,
    categories: List<ShortcutCategory>,
    categories: List<ShortcutCategoryUi>,
    onKeyboardSettingsClicked: () -> Unit,
    selectedCategory: ShortcutCategoryType?,
    onCategoryClicked: (ShortcutCategory) -> Unit,
    onCategoryClicked: (ShortcutCategoryUi) -> Unit,
) {
    Column(modifier) {
        ShortcutsSearchBar(onSearchQueryChanged)
@@ -690,15 +634,15 @@ private fun StartSidePanel(

@Composable
private fun CategoriesPanelTwoPane(
    categories: List<ShortcutCategory>,
    categories: List<ShortcutCategoryUi>,
    selectedCategory: ShortcutCategoryType?,
    onCategoryClicked: (ShortcutCategory) -> Unit,
    onCategoryClicked: (ShortcutCategoryUi) -> Unit,
) {
    Column {
        categories.fastForEach {
            CategoryItemTwoPane(
                label = it.label(LocalContext.current),
                iconSource = it.icon,
                label = it.label,
                iconSource = it.iconSource,
                selected = selectedCategory == it.type,
                onClick = { onCategoryClicked(it) },
            )
+34 −0
Original line number Diff line number Diff line
/*
 * 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 com.android.systemui.keyboard.shortcut.ui.model

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.ShortcutSubCategory

data class ShortcutCategoryUi(
    val label: String,
    val iconSource: IconSource,
    val type: ShortcutCategoryType,
    val subCategories: List<ShortcutSubCategory>,
) {
    constructor(
        label: String,
        iconSource: IconSource,
        shortcutCategory: ShortcutCategory,
    ) : this(label, iconSource, shortcutCategory.type, shortcutCategory.subCategories)
}
+1 −2
Original line number Diff line number Diff line
@@ -16,14 +16,13 @@

package com.android.systemui.keyboard.shortcut.ui.model

import com.android.systemui.keyboard.shortcut.shared.model.ShortcutCategory
import com.android.systemui.keyboard.shortcut.shared.model.ShortcutCategoryType

sealed interface ShortcutsUiState {

    data class Active(
        val searchQuery: String,
        val shortcutCategories: List<ShortcutCategory>,
        val shortcutCategories: List<ShortcutCategoryUi>,
        val defaultSelectedCategory: ShortcutCategoryType?,
    ) : ShortcutsUiState

+82 −4
Original line number Diff line number Diff line
@@ -17,6 +17,15 @@
package com.android.systemui.keyboard.shortcut.ui.viewmodel

import android.app.role.RoleManager
import android.content.pm.PackageManager.NameNotFoundException
import android.util.Log
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Android
import androidx.compose.material.icons.filled.Apps
import androidx.compose.material.icons.filled.Keyboard
import androidx.compose.material.icons.filled.Tv
import androidx.compose.material.icons.filled.VerticalSplit
import com.android.compose.ui.graphics.painter.DrawablePainter
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,7 +34,10 @@ 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.ShortcutCategoryType.CurrentApp
import com.android.systemui.keyboard.shortcut.shared.model.ShortcutSubCategory
import com.android.systemui.keyboard.shortcut.ui.model.IconSource
import com.android.systemui.keyboard.shortcut.ui.model.ShortcutCategoryUi
import com.android.systemui.keyboard.shortcut.ui.model.ShortcutsUiState
import com.android.systemui.res.R
import com.android.systemui.settings.UserTracker
import javax.inject.Inject
import kotlinx.coroutines.CoroutineDispatcher
@@ -51,6 +63,7 @@ constructor(
) {

    private val searchQuery = MutableStateFlow("")
    private val userContext = userTracker.createCurrentUserContext(userTracker.userContext)

    val shouldShow =
        categoriesInteractor.shortcutCategories
@@ -68,9 +81,10 @@ constructor(
                    val categoriesWithLauncherExcluded = excludeLauncherApp(categories)
                    val filteredCategories =
                        filterCategoriesBySearchQuery(query, categoriesWithLauncherExcluded)
                    val shortcutCategoriesUi = convertCategoriesModelToUiModel(filteredCategories)
                    ShortcutsUiState.Active(
                        searchQuery = query,
                        shortcutCategories = filteredCategories,
                        shortcutCategories = shortcutCategoriesUi,
                        defaultSelectedCategory = getDefaultSelectedCategory(filteredCategories),
                    )
                }
@@ -78,9 +92,73 @@ constructor(
            .stateIn(
                scope = backgroundScope,
                started = SharingStarted.Lazily,
                initialValue = ShortcutsUiState.Inactive
                initialValue = ShortcutsUiState.Inactive,
            )

    private fun convertCategoriesModelToUiModel(
        categories: List<ShortcutCategory>
    ): List<ShortcutCategoryUi> {
        return categories.map { category ->
            ShortcutCategoryUi(
                label = getShortcutCategoryLabel(category.type),
                iconSource = getShortcutCategoryIcon(category.type),
                shortcutCategory = category,
            )
        }
    }

    private fun getShortcutCategoryIcon(type: ShortcutCategoryType): IconSource {
        return when (type) {
            ShortcutCategoryType.System -> IconSource(imageVector = Icons.Default.Tv)
            ShortcutCategoryType.MultiTasking ->
                IconSource(imageVector = Icons.Default.VerticalSplit)
            ShortcutCategoryType.InputMethodEditor ->
                IconSource(imageVector = Icons.Default.Keyboard)
            ShortcutCategoryType.AppCategories -> IconSource(imageVector = Icons.Default.Apps)
            is CurrentApp -> {
                try {
                    val iconDrawable =
                        userContext.packageManager.getApplicationIcon(type.packageName)
                    IconSource(painter = DrawablePainter(drawable = iconDrawable))
                } catch (e: NameNotFoundException) {
                    Log.wtf(
                        "ShortcutHelperViewModel",
                        "Package not found when retrieving icon for ${type.packageName}",
                    )
                    IconSource(imageVector = Icons.Default.Android)
                }
            }
        }
    }

    private fun getShortcutCategoryLabel(type: ShortcutCategoryType): String =
        when (type) {
            ShortcutCategoryType.System ->
                userContext.getString(R.string.shortcut_helper_category_system)
            ShortcutCategoryType.MultiTasking ->
                userContext.getString(R.string.shortcut_helper_category_multitasking)
            ShortcutCategoryType.InputMethodEditor ->
                userContext.getString(R.string.shortcut_helper_category_input)
            ShortcutCategoryType.AppCategories ->
                userContext.getString(R.string.shortcut_helper_category_app_shortcuts)
            is CurrentApp -> getApplicationLabelForCurrentApp(type)
        }

    private fun getApplicationLabelForCurrentApp(type: CurrentApp): String {
        try {
            val packageManagerForUser = userContext.packageManager
            val currentAppInfo =
                packageManagerForUser.getApplicationInfo(type.packageName, /* flags= */ 0)
            return packageManagerForUser.getApplicationLabel(currentAppInfo).toString()
        } catch (e: NameNotFoundException) {
            Log.wtf(
                "ShortcutHelperViewModel",
                "Package Not found when retrieving Label for ${type.packageName}",
            )
            return "Current App"
        }
    }

    private suspend fun excludeLauncherApp(
        categories: List<ShortcutCategory>
    ): List<ShortcutCategory> {
@@ -111,7 +189,7 @@ constructor(

    private fun filterCategoriesBySearchQuery(
        query: String,
        categories: List<ShortcutCategory>
        categories: List<ShortcutCategory>,
    ): List<ShortcutCategory> {
        val lowerCaseTrimmedQuery = query.trim().lowercase()
        if (lowerCaseTrimmedQuery.isEmpty()) {
@@ -132,7 +210,7 @@ constructor(

    private fun filterSubCategoriesBySearchQuery(
        subCategories: List<ShortcutSubCategory>,
        query: String
        query: String,
    ) =
        subCategories
            .map { subCategory ->
+8 −4
Original line number Diff line number Diff line
@@ -18,14 +18,18 @@ package com.android.systemui.settings

import android.content.Context

/** Implemented by [UserTrackerImpl]. */
interface UserContextProvider {
    /**
 * Implemented by [UserTrackerImpl].
     * provides system context, not current user context.
     *
     * To get current user context use [createCurrentUserContext] passing [userContext] as context
     */
interface UserContextProvider {
    val userContext: Context

    /**
     * Creates the {@code context} with the current user.
     *
     * @see Context#createContextAsUser(UserHandle, int)
     */
    fun createCurrentUserContext(context: Context): Context
Loading