1 /* <lambda>null2 * Copyright (C) 2022 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.content.pm.PackageManager.OnPermissionsChangedListener 22 import android.icu.text.ListFormatter 23 import androidx.compose.runtime.Composable 24 import androidx.compose.runtime.remember 25 import androidx.compose.ui.platform.LocalContext 26 import androidx.lifecycle.LiveData 27 import com.android.settings.R 28 import com.android.settingslib.applications.PermissionsSummaryHelper 29 import com.android.settingslib.applications.PermissionsSummaryHelper.PermissionsResultCallback 30 import com.android.settingslib.spa.framework.util.formatString 31 import com.android.settingslib.spaprivileged.framework.common.asUser 32 import com.android.settingslib.spaprivileged.model.app.userHandle 33 34 data class AppPermissionSummaryState( 35 val summary: String, 36 val enabled: Boolean, 37 ) 38 39 @Composable 40 fun rememberAppPermissionSummary(app: ApplicationInfo): AppPermissionSummaryLiveData { 41 val context = LocalContext.current 42 return remember { AppPermissionSummaryLiveData(context, app) } 43 } 44 45 class AppPermissionSummaryLiveData( 46 private val context: Context, 47 private val app: ApplicationInfo, 48 ) : LiveData<AppPermissionSummaryState>() { 49 private val userContext = context.asUser(app.userHandle) 50 private val userPackageManager = userContext.packageManager 51 uidnull52 private val onPermissionsChangedListener = OnPermissionsChangedListener { uid -> 53 if (uid == app.uid) update() 54 } 55 onActivenull56 override fun onActive() { 57 userPackageManager.addOnPermissionsChangeListener(onPermissionsChangedListener) 58 update() 59 } 60 onInactivenull61 override fun onInactive() { 62 userPackageManager.removeOnPermissionsChangeListener(onPermissionsChangedListener) 63 } 64 updatenull65 private fun update() { 66 PermissionsSummaryHelper.getPermissionSummary( 67 userContext, app.packageName, permissionsCallback 68 ) 69 } 70 71 private val permissionsCallback = object : PermissionsResultCallback { onPermissionSummaryResultnull72 override fun onPermissionSummaryResult( 73 requestedPermissionCount: Int, 74 additionalGrantedPermissionCount: Int, 75 grantedGroupLabels: List<CharSequence>, 76 ) { 77 if (requestedPermissionCount == 0) { 78 postValue(noPermissionRequestedState()) 79 return 80 } 81 val labels = getDisplayLabels(additionalGrantedPermissionCount, grantedGroupLabels) 82 val summary = if (labels.isNotEmpty()) { 83 ListFormatter.getInstance().format(labels) 84 } else { 85 context.getString(R.string.runtime_permissions_summary_no_permissions_granted) 86 } 87 postValue(AppPermissionSummaryState(summary = summary, enabled = true)) 88 } 89 } 90 noPermissionRequestedStatenull91 private fun noPermissionRequestedState() = AppPermissionSummaryState( 92 summary = context.getString(R.string.runtime_permissions_summary_no_permissions_requested), 93 enabled = false, 94 ) 95 96 private fun getDisplayLabels( 97 additionalGrantedPermissionCount: Int, 98 grantedGroupLabels: List<CharSequence>, 99 ): List<CharSequence> = when (additionalGrantedPermissionCount) { 100 0 -> grantedGroupLabels 101 else -> { 102 grantedGroupLabels + 103 // N additional permissions. 104 context.formatString( 105 R.string.runtime_permissions_additional_count, 106 "count" to additionalGrantedPermissionCount, 107 ) 108 } 109 } 110 } 111