1 /* <lambda>null2 * Copyright (C) 2024 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.settings.spa.app.appinfo 18 19 import android.content.Context 20 import android.content.pm.ApplicationInfo 21 import android.icu.text.ListFormatter 22 import androidx.compose.runtime.Composable 23 import androidx.compose.runtime.remember 24 import androidx.compose.ui.platform.LocalContext 25 import com.android.settings.R 26 import com.android.settingslib.applications.PermissionsSummaryHelper 27 import com.android.settingslib.spa.framework.util.formatString 28 import com.android.settingslib.spaprivileged.framework.common.asUser 29 import com.android.settingslib.spaprivileged.model.app.permissionsChangedFlow 30 import com.android.settingslib.spaprivileged.model.app.userHandle 31 import kotlin.coroutines.resume 32 import kotlinx.coroutines.Dispatchers 33 import kotlinx.coroutines.flow.Flow 34 import kotlinx.coroutines.flow.flowOn 35 import kotlinx.coroutines.flow.map 36 import kotlinx.coroutines.suspendCancellableCoroutine 37 38 data class AppPermissionSummaryState( 39 val summary: String, 40 val enabled: Boolean, 41 ) 42 43 @Composable 44 fun rememberAppPermissionSummary(app: ApplicationInfo): Flow<AppPermissionSummaryState> { 45 val context = LocalContext.current 46 return remember(app) { AppPermissionSummaryRepository(context, app).flow } 47 } 48 49 class AppPermissionSummaryRepository( 50 private val context: Context, 51 private val app: ApplicationInfo, 52 ) { 53 private val userContext = context.asUser(app.userHandle) 54 55 val flow = context.permissionsChangedFlow(app) <lambda>null56 .map { getPermissionSummary() } 57 .flowOn(Dispatchers.Default) 58 getPermissionSummarynull59 private suspend fun getPermissionSummary() = suspendCancellableCoroutine { continuation -> 60 PermissionsSummaryHelper.getPermissionSummary( 61 userContext, 62 app.packageName, 63 ) { requestedPermissionCount: Int, 64 additionalGrantedPermissionCount: Int, 65 grantedGroupLabels: List<CharSequence> -> 66 val summaryState = if (requestedPermissionCount == 0) { 67 noPermissionRequestedState() 68 } else { 69 val labels = getDisplayLabels(additionalGrantedPermissionCount, grantedGroupLabels) 70 val summary = if (labels.isNotEmpty()) { 71 ListFormatter.getInstance().format(labels) 72 } else { 73 context.getString(R.string.runtime_permissions_summary_no_permissions_granted) 74 } 75 AppPermissionSummaryState(summary = summary, enabled = true) 76 } 77 continuation.resume(summaryState) 78 } 79 } 80 noPermissionRequestedStatenull81 private fun noPermissionRequestedState() = AppPermissionSummaryState( 82 summary = context.getString(R.string.runtime_permissions_summary_no_permissions_requested), 83 enabled = false, 84 ) 85 86 private fun getDisplayLabels( 87 additionalGrantedPermissionCount: Int, 88 grantedGroupLabels: List<CharSequence>, 89 ): List<CharSequence> = if (additionalGrantedPermissionCount == 0) { 90 grantedGroupLabels 91 } else { 92 grantedGroupLabels + 93 // N additional permissions. 94 context.formatString( 95 R.string.runtime_permissions_additional_count, 96 "count" to additionalGrantedPermissionCount, 97 ) 98 } 99 } 100