diff options
author | 2023-12-07 00:40:53 +0000 | |
---|---|---|
committer | 2023-12-07 00:40:53 +0000 | |
commit | 331f36e7cb6a2a1478f08ff198a1f79c7ab4624c (patch) | |
tree | 89919ab93d0767f31d415ee9476dcc3faacef0db | |
parent | 775ff4356c80b7d4f8592f20efc1c6e3a0dda0b1 (diff) | |
parent | 220ba6395fef8f1ef3928ee3c6a36f0a749e1428 (diff) |
Merge "Show usage timestamps in WearPermissionApps" into main
3 files changed, 107 insertions, 9 deletions
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearPermissionAppsFragment.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearPermissionAppsFragment.kt index 4fb5b264b..d8eb71e0e 100644 --- a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearPermissionAppsFragment.kt +++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearPermissionAppsFragment.kt @@ -18,19 +18,26 @@ package com.android.permissioncontroller.permission.ui.wear import android.Manifest import android.content.Intent +import android.os.Build import android.os.Bundle import android.os.UserHandle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import androidx.annotation.RequiresApi import androidx.compose.ui.platform.ComposeView import androidx.fragment.app.Fragment import androidx.lifecycle.ViewModelProvider import com.android.modules.utils.build.SdkLevel import com.android.permissioncontroller.Constants +import com.android.permissioncontroller.permission.model.v31.AppPermissionUsage +import com.android.permissioncontroller.permission.model.v31.PermissionUsages +import com.android.permissioncontroller.permission.model.v31.PermissionUsages.PermissionsUsagesChangeCallback import com.android.permissioncontroller.permission.ui.handheld.AppPermissionFragment import com.android.permissioncontroller.permission.ui.model.PermissionAppsViewModel import com.android.permissioncontroller.permission.ui.model.PermissionAppsViewModelFactory +import com.android.permissioncontroller.permission.ui.wear.model.WearAppPermissionUsagesViewModel +import com.android.permissioncontroller.permission.ui.wear.model.WearAppPermissionUsagesViewModelFactory /** * This is a condensed version of @@ -41,9 +48,15 @@ import com.android.permissioncontroller.permission.ui.model.PermissionAppsViewMo * * <p>Shows a list of apps which request at least on permission of this group. */ -class WearPermissionAppsFragment : Fragment() { +class WearPermissionAppsFragment : Fragment(), PermissionsUsagesChangeCallback { private val LOG_TAG = "PermissionAppsFragment" + private lateinit var permissionUsages: PermissionUsages + private lateinit var wearViewModel: WearAppPermissionUsagesViewModel + + // Suppress warning of the deprecated class [android.app.LoaderManager] since other form factors + // are using the class to load PermissionUsages. + @Suppress("DEPRECATION") override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, @@ -62,6 +75,9 @@ class WearPermissionAppsFragment : Fragment() { val factory = PermissionAppsViewModelFactory(activity.getApplication(), permGroupName, this, Bundle()) val viewModel = ViewModelProvider(this, factory).get(PermissionAppsViewModel::class.java) + wearViewModel = + ViewModelProvider(this, WearAppPermissionUsagesViewModelFactory()) + .get(WearAppPermissionUsagesViewModel::class.java) val onAppClick: (String, UserHandle, String) -> Unit = { packageName, user, category -> run { @@ -105,6 +121,26 @@ class WearPermissionAppsFragment : Fragment() { } } + // If the build type is below S, the app ops for permission usage can't be found. Thus, we + // shouldn't load permission usages, for them. + if (SdkLevel.isAtLeastS()) { + permissionUsages = PermissionUsages(requireContext()) + + val filterTimeBeginMillis: Long = viewModel.getFilterTimeBeginMillis() + permissionUsages.load( + null, + null, + filterTimeBeginMillis, + Long.MAX_VALUE, + PermissionUsages.USAGE_FLAG_LAST, + requireActivity().getLoaderManager(), + false, + false, + this, + false + ) + } + return ComposeView(requireContext()).apply { setContent { WearPermissionAppsScreen( @@ -112,6 +148,7 @@ class WearPermissionAppsFragment : Fragment() { activity.getApplication(), permGroupName, viewModel, + wearViewModel, isStorageAndLessThanT, onAppClick, onShowSystemClick, @@ -121,4 +158,17 @@ class WearPermissionAppsFragment : Fragment() { } } } + + @RequiresApi(Build.VERSION_CODES.S) + override fun onPermissionUsagesChanged() { + if (permissionUsages.usages.isEmpty()) { + return + } + if (context == null) { + // Async result has come in after our context is gone. + return + } + wearViewModel.appPermissionUsages.value = + ArrayList<AppPermissionUsage>(permissionUsages.usages) + } } diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearPermissionAppsHelper.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearPermissionAppsHelper.kt index 8d1247e6a..559160b38 100644 --- a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearPermissionAppsHelper.kt +++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearPermissionAppsHelper.kt @@ -19,12 +19,16 @@ package com.android.permissioncontroller.permission.ui.wear import android.app.Application import android.graphics.drawable.Drawable import android.os.UserHandle +import com.android.permission.flags.Flags import com.android.permissioncontroller.R +import com.android.permissioncontroller.permission.model.v31.AppPermissionUsage import com.android.permissioncontroller.permission.ui.Category import com.android.permissioncontroller.permission.ui.model.PermissionAppsViewModel +import com.android.permissioncontroller.permission.ui.wear.model.WearAppPermissionUsagesViewModel import com.android.permissioncontroller.permission.utils.KotlinUtils import com.android.permissioncontroller.permission.utils.KotlinUtils.getPermGroupDescription import com.android.permissioncontroller.permission.utils.KotlinUtils.getPermGroupLabel +import com.android.permissioncontroller.permission.utils.Utils import com.android.settingslib.utils.applications.AppUtils import java.text.Collator import java.util.Random @@ -34,6 +38,7 @@ class WearPermissionAppsHelper( val application: Application, val permGroupName: String, val viewModel: PermissionAppsViewModel, + val wearViewModel: WearAppPermissionUsagesViewModel, private val isStorageAndLessThanT: Boolean, private val onAppClick: (String, UserHandle, String) -> Unit, val onShowSystemClick: (Boolean) -> Unit, @@ -46,10 +51,15 @@ class WearPermissionAppsHelper( fun getTitle() = getPermGroupLabel(application, permGroupName).toString() fun getSubTitle() = getPermGroupDescription(application, permGroupName).toString() fun getChipsByCategory( - categorizedApps: Map<Category, List<Pair<String, UserHandle>>> + categorizedApps: Map<Category, List<Pair<String, UserHandle>>>, + appPermissionUsages: List<AppPermissionUsage> ): Map<String, List<ChipInfo>> { val chipsByCategory: MutableMap<String, MutableList<ChipInfo>> = HashMap() + // A mapping of user + packageName to their last access timestamps for the permission group. + val groupUsageLastAccessTime: Map<String, Long> = + viewModel.extractGroupUsageLastAccessTime(appPermissionUsages) + val context = application val collator = Collator.getInstance(context.resources.configuration.locales.get(0)) val comparator = ChipComparator(collator) @@ -64,7 +74,13 @@ class WearPermissionAppsHelper( .let { if (it.first.isNotEmpty()) { chipsByCategory[STORAGE_ALLOWED_FULL] = - convertToChips(category, it.first, viewIdForLogging, comparator) + convertToChips( + category, + it.first, + viewIdForLogging, + comparator, + groupUsageLastAccessTime + ) } if (it.second.isNotEmpty()) { chipsByCategory[STORAGE_ALLOWED_SCOPED] = @@ -72,7 +88,8 @@ class WearPermissionAppsHelper( category, it.second, viewIdForLogging, - comparator + comparator, + groupUsageLastAccessTime ) } } @@ -82,7 +99,13 @@ class WearPermissionAppsHelper( val list = categorizedApps[category] if (!list.isNullOrEmpty()) { chipsByCategory[category.categoryName] = - convertToChips(category, list, viewIdForLogging, comparator) + convertToChips( + category, + list, + viewIdForLogging, + comparator, + groupUsageLastAccessTime + ) } } @@ -95,17 +118,20 @@ class WearPermissionAppsHelper( category: Category, list: List<Pair<String, UserHandle>>, viewIdForLogging: Long, - comparator: Comparator<ChipInfo> + comparator: Comparator<ChipInfo>, + groupUsageLastAccessTime: Map<String, Long> ) = list .map { p -> + val lastAccessTime = groupUsageLastAccessTime[(p.second.toString() + p.first)] createAppChipInfo( application, p.first, p.second, category, onAppClick, - viewIdForLogging + viewIdForLogging, + lastAccessTime ) } .sortedWith(comparator) @@ -121,7 +147,8 @@ class WearPermissionAppsHelper( user: UserHandle, category: Category, onClick: (packageName: String, user: UserHandle, category: String) -> Unit, - viewIdForLogging: Long + viewIdForLogging: Long, + lastAccessTime: Long? ): ChipInfo { if (!viewModel.creationLogged) { logFragmentCreated( @@ -133,8 +160,24 @@ class WearPermissionAppsHelper( category == Category.DENIED ) } + val summary = + if (Flags.wearPrivacyDashboardEnabled()) { + lastAccessTime?.let { + viewModel.getPreferenceSummary( + application.resources, + Utils.getPermissionLastAccessSummaryTimestamp( + lastAccessTime, + application, + permGroupName + ) + ) + } + } else { + null + } return ChipInfo( title = KotlinUtils.getPackageLabel(application, packageName, user), + summary = summary, contentDescription = AppUtils.getAppContentDescription(application, packageName, user.getIdentifier()), icon = KotlinUtils.getBadgedPackageIcon(application, packageName, user), @@ -184,6 +227,7 @@ class WearPermissionAppsHelper( class ChipInfo( val title: String, + val summary: String? = null, val contentDescription: String? = null, val onClick: () -> Unit = {}, val icon: Drawable? = null, diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearPermissionAppsScreen.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearPermissionAppsScreen.kt index 08733d3b2..154fd0bff 100644 --- a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearPermissionAppsScreen.kt +++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearPermissionAppsScreen.kt @@ -38,12 +38,14 @@ fun WearPermissionAppsScreen(helper: WearPermissionAppsHelper) { val categorizedApps = helper.categorizedAppsLiveData().observeAsState(emptyMap()) val hasSystemApps = helper.hasSystemAppsLiveData().observeAsState(false) val showSystem = helper.shouldShowSystemLiveData().observeAsState(false) + val appPermissionUsages = helper.wearViewModel.appPermissionUsages.observeAsState(emptyList()) var isLoading by remember { mutableStateOf(true) } val title = helper.getTitle() val subTitle = helper.getSubTitle() val showAlways = helper.showAlways() - val chipsByCategory = helper.getChipsByCategory(categorizedApps.value) + val chipsByCategory = + helper.getChipsByCategory(categorizedApps.value, appPermissionUsages.value) WearPermissionAppsContent( chipsByCategory, @@ -89,6 +91,8 @@ internal fun WearPermissionAppsContent( Chip( label = it.title, labelMaxLines = Int.MAX_VALUE, + secondaryLabel = it.summary, + secondaryLabelMaxLines = Int.MAX_VALUE, icon = it.icon, enabled = it.enabled, onClick = { it.onClick() }, |