Migrate AppPermissionSummary to flow

Bug: 321163306
Test: manual - on App Info
Test: unit test
Change-Id: I36f6a479d530fc646a55f68fbaf681b72eff00dd
This commit is contained in:
Chaohui Wang
2024-01-19 14:44:27 +08:00
parent 420625217c
commit 5255867976
5 changed files with 93 additions and 136 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2022 The Android Open Source Project
* 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.
@@ -22,15 +22,15 @@ import android.content.Intent
import android.content.pm.ApplicationInfo
import android.util.Log
import androidx.compose.runtime.Composable
import androidx.compose.runtime.livedata.observeAsState
import androidx.compose.runtime.remember
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.lifecycle.LiveData
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.android.settings.R
import com.android.settingslib.spa.widget.preference.Preference
import com.android.settingslib.spa.widget.preference.PreferenceModel
import com.android.settingslib.spaprivileged.framework.compose.placeholder
import com.android.settingslib.spaprivileged.model.app.userHandle
import kotlinx.coroutines.flow.Flow
private const val TAG = "AppPermissionPreference"
private const val EXTRA_HIDE_INFO_BUTTON = "hideInfoButton"
@@ -38,14 +38,11 @@ private const val EXTRA_HIDE_INFO_BUTTON = "hideInfoButton"
@Composable
fun AppPermissionPreference(
app: ApplicationInfo,
summaryLiveData: LiveData<AppPermissionSummaryState> = rememberAppPermissionSummary(app),
summaryFlow: Flow<AppPermissionSummaryState> = rememberAppPermissionSummary(app),
) {
val context = LocalContext.current
val summaryState = summaryLiveData.observeAsState(
initial = AppPermissionSummaryState(
summary = stringResource(R.string.summary_placeholder),
enabled = false,
)
val summaryState = summaryFlow.collectAsStateWithLifecycle(
initialValue = AppPermissionSummaryState(summary = placeholder(), enabled = false),
)
Preference(
model = remember {

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2022 The Android Open Source Project
* 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.
@@ -18,18 +18,22 @@ package com.android.settings.spa.app.appinfo
import android.content.Context
import android.content.pm.ApplicationInfo
import android.content.pm.PackageManager.OnPermissionsChangedListener
import android.icu.text.ListFormatter
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.platform.LocalContext
import androidx.lifecycle.LiveData
import com.android.settings.R
import com.android.settingslib.applications.PermissionsSummaryHelper
import com.android.settingslib.applications.PermissionsSummaryHelper.PermissionsResultCallback
import com.android.settingslib.spa.framework.util.formatString
import com.android.settingslib.spaprivileged.framework.common.asUser
import com.android.settingslib.spaprivileged.model.app.permissionsChangedFlow
import com.android.settingslib.spaprivileged.model.app.userHandle
import kotlin.coroutines.resume
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.suspendCancellableCoroutine
data class AppPermissionSummaryState(
val summary: String,
@@ -37,58 +41,40 @@ data class AppPermissionSummaryState(
)
@Composable
fun rememberAppPermissionSummary(app: ApplicationInfo): AppPermissionSummaryLiveData {
fun rememberAppPermissionSummary(app: ApplicationInfo): Flow<AppPermissionSummaryState> {
val context = LocalContext.current
return remember(app) { AppPermissionSummaryLiveData(context, app) }
return remember(app) { AppPermissionSummaryRepository(context, app).flow }
}
class AppPermissionSummaryLiveData(
class AppPermissionSummaryRepository(
private val context: Context,
private val app: ApplicationInfo,
) : LiveData<AppPermissionSummaryState>() {
) {
private val userContext = context.asUser(app.userHandle)
private val userPackageManager = userContext.packageManager
private val onPermissionsChangedListener = OnPermissionsChangedListener { uid ->
if (uid == app.uid) update()
}
val flow = context.permissionsChangedFlow(app)
.map { getPermissionSummary() }
.flowOn(Dispatchers.Default)
override fun onActive() {
userPackageManager.addOnPermissionsChangeListener(onPermissionsChangedListener)
if (app.isArchived) {
postValue(noPermissionRequestedState())
} else {
update()
}
}
override fun onInactive() {
userPackageManager.removeOnPermissionsChangeListener(onPermissionsChangedListener)
}
private fun update() {
private suspend fun getPermissionSummary() = suspendCancellableCoroutine { continuation ->
PermissionsSummaryHelper.getPermissionSummary(
userContext, app.packageName, permissionsCallback
)
}
private val permissionsCallback = object : PermissionsResultCallback {
override fun onPermissionSummaryResult(
requestedPermissionCount: Int,
userContext,
app.packageName,
) { requestedPermissionCount: Int,
additionalGrantedPermissionCount: Int,
grantedGroupLabels: List<CharSequence>,
) {
if (requestedPermissionCount == 0) {
postValue(noPermissionRequestedState())
return
}
val labels = getDisplayLabels(additionalGrantedPermissionCount, grantedGroupLabels)
val summary = if (labels.isNotEmpty()) {
ListFormatter.getInstance().format(labels)
grantedGroupLabels: List<CharSequence> ->
val summaryState = if (requestedPermissionCount == 0) {
noPermissionRequestedState()
} else {
context.getString(R.string.runtime_permissions_summary_no_permissions_granted)
val labels = getDisplayLabels(additionalGrantedPermissionCount, grantedGroupLabels)
val summary = if (labels.isNotEmpty()) {
ListFormatter.getInstance().format(labels)
} else {
context.getString(R.string.runtime_permissions_summary_no_permissions_granted)
}
AppPermissionSummaryState(summary = summary, enabled = true)
}
postValue(AppPermissionSummaryState(summary = summary, enabled = true))
continuation.resume(summaryState)
}
}
@@ -100,15 +86,14 @@ class AppPermissionSummaryLiveData(
private fun getDisplayLabels(
additionalGrantedPermissionCount: Int,
grantedGroupLabels: List<CharSequence>,
): List<CharSequence> = when (additionalGrantedPermissionCount) {
0 -> grantedGroupLabels
else -> {
grantedGroupLabels +
// N additional permissions.
context.formatString(
R.string.runtime_permissions_additional_count,
"count" to additionalGrantedPermissionCount,
)
}
): List<CharSequence> = if (additionalGrantedPermissionCount == 0) {
grantedGroupLabels
} else {
grantedGroupLabels +
// N additional permissions.
context.formatString(
R.string.runtime_permissions_additional_count,
"count" to additionalGrantedPermissionCount,
)
}
}