diff options
author | 2023-02-22 14:31:05 +0000 | |
---|---|---|
committer | 2023-02-22 14:31:05 +0000 | |
commit | dcc53073c5b079a8e3f9b975169418df832feedd (patch) | |
tree | 9ac37f7facb5a216e9dfa9203eae407a30dcff4e | |
parent | dba921871424ac9913344419c7307593522e62b3 (diff) |
Revert "Don't unnecessarily query package metadata for SafetyLabels"
This reverts commit dba921871424ac9913344419c7307593522e62b3.
Reason for revert: DM P0 breakage (b/270255253)
Change-Id: Ibf50d32e2d0cb4cc8e25ff604ecd8d92c97a56dc
13 files changed, 275 insertions, 204 deletions
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/data/LightInstallSourceInfoLiveData.kt b/PermissionController/src/com/android/permissioncontroller/permission/data/LightInstallSourceInfoLiveData.kt index 7a817eb6d..543d8eae2 100644 --- a/PermissionController/src/com/android/permissioncontroller/permission/data/LightInstallSourceInfoLiveData.kt +++ b/PermissionController/src/com/android/permissioncontroller/permission/data/LightInstallSourceInfoLiveData.kt @@ -74,7 +74,7 @@ private constructor( getInstallSourceInfo(userContext, packageName).installingPackageName) } catch (e: PackageManager.NameNotFoundException) { Log.w(LOG_TAG, "InstallSourceInfo for $packageName not found") - LightInstallSourceInfoLiveData.invalidateSingle(packageName to user) + SafetyLabelInfoLiveData.invalidateSingle(packageName to user) UNKNOWN_INSTALL_SOURCE } postValue(lightInstallSourceInfo) diff --git a/PermissionController/src/com/android/permissioncontroller/permission/data/SafetyLabelInfoLiveData.kt b/PermissionController/src/com/android/permissioncontroller/permission/data/SafetyLabelInfoLiveData.kt index e8102c2e0..d2ba7031d 100644 --- a/PermissionController/src/com/android/permissioncontroller/permission/data/SafetyLabelInfoLiveData.kt +++ b/PermissionController/src/com/android/permissioncontroller/permission/data/SafetyLabelInfoLiveData.kt @@ -18,10 +18,14 @@ package com.android.permissioncontroller.permission.data import android.app.Application import android.content.pm.PackageManager +import android.os.PersistableBundle import android.os.UserHandle import android.util.Log -import com.android.modules.utils.build.SdkLevel +import com.android.permission.safetylabel.DataCategoryConstants +import com.android.permission.safetylabel.DataLabelConstants +import com.android.permission.safetylabel.DataTypeConstants import com.android.permission.safetylabel.SafetyLabel +import com.android.permission.safetylabel.SafetyLabel.KEY_VERSION import com.android.permissioncontroller.PermissionControllerApplication import com.android.permissioncontroller.permission.model.livedatatypes.SafetyLabelInfo import com.android.permissioncontroller.permission.utils.KotlinUtils.isPlaceholderSafetyLabelDataEnabled @@ -79,11 +83,6 @@ private constructor( return } - if (!SdkLevel.isAtLeastU()) { - postValue(SafetyLabelInfo.UNAVAILABLE) - return - } - // TODO(b/261607291): Add support preinstall apps that provide SafetyLabel. Installing // package is null until updated from an app store val installSourcePackageName = lightInstallSourceInfoLiveData.value?.installingPackageName @@ -92,16 +91,11 @@ private constructor( return } - if (isPlaceholderSafetyLabelDataEnabled()) { - postValue(SafetyLabelInfo(SafetyLabel.getPlaceholderSafetyLabel(), - installSourcePackageName)) - return - } - val safetyLabelInfo: SafetyLabelInfo = try { - val safetyLabel: SafetyLabel? = SafetyLabel.getSafetyLabelFromMetadata( - app.packageManager.getAppMetadata(packageName)) + val metadataBundle: PersistableBundle = getAppMetadata() + val safetyLabel: SafetyLabel? = + SafetyLabel.getSafetyLabelFromMetadata(metadataBundle) if (safetyLabel != null) { SafetyLabelInfo(safetyLabel, installSourcePackageName) } else { @@ -115,8 +109,49 @@ private constructor( postValue(safetyLabelInfo) } + private fun getAppMetadata(): PersistableBundle { + return if (isPlaceholderSafetyLabelDataEnabled()) { + placeholderMetadataBundle() + } else { + app.packageManager.getAppMetadata(packageName) + } + } + + private fun placeholderMetadataBundle(): PersistableBundle { + val approximateLocationBundle = + PersistableBundle().apply { putIntArray("purposes", (1..7).toList().toIntArray()) } + + val locationBundle = + PersistableBundle().apply { + putPersistableBundle( + DataTypeConstants.LOCATION_APPROX_LOCATION, approximateLocationBundle) + } + + val dataSharedBundle = + PersistableBundle().apply { + putPersistableBundle(DataCategoryConstants.CATEGORY_LOCATION, locationBundle) + } + + val dataLabelBundle = + PersistableBundle().apply { + putPersistableBundle(DataLabelConstants.DATA_USAGE_SHARED, dataSharedBundle) + } + + val safetyLabelBundle = PersistableBundle().apply { + putLong(KEY_VERSION, INITIAL_SAFETY_LABELS_VERSION) + putPersistableBundle("data_labels", dataLabelBundle) + } + + return PersistableBundle().apply { + putLong(KEY_VERSION, INITIAL_METADATA_VERSION) + putPersistableBundle("safety_labels", safetyLabelBundle) + } + } + companion object : DataRepositoryForPackage<Pair<String, UserHandle>, SafetyLabelInfoLiveData>( ) { + private const val INITIAL_METADATA_VERSION = 1L + private const val INITIAL_SAFETY_LABELS_VERSION = 1L private val LOG_TAG = SafetyLabelInfoLiveData::class.java.simpleName override fun newValue(key: Pair<String, UserHandle>): SafetyLabelInfoLiveData { diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/GrantPermissionsActivity.java b/PermissionController/src/com/android/permissioncontroller/permission/ui/GrantPermissionsActivity.java index 8f73f6577..e97c6ef4b 100644 --- a/PermissionController/src/com/android/permissioncontroller/permission/ui/GrantPermissionsActivity.java +++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/GrantPermissionsActivity.java @@ -89,7 +89,7 @@ import java.util.Random; public class GrantPermissionsActivity extends SettingsActivity implements GrantPermissionsViewHandler.ResultListener { - private static final String LOG_TAG = "GrantPermissionsActivity"; + private static final String LOG_TAG = "GrantPermissionsActivit"; private static final String KEY_SESSION_ID = GrantPermissionsActivity.class.getName() + "_REQUEST_ID"; diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/AppPermissionFragment.java b/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/AppPermissionFragment.java index 9fad46648..007707363 100644 --- a/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/AppPermissionFragment.java +++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/AppPermissionFragment.java @@ -73,6 +73,7 @@ import androidx.lifecycle.ViewModelProvider; import com.android.permissioncontroller.R; import com.android.permissioncontroller.permission.data.FullStoragePermissionAppsLiveData.FullStoragePackageState; +import com.android.permissioncontroller.permission.model.livedatatypes.SafetyLabelInfo; import com.android.permissioncontroller.permission.ui.AdvancedConfirmDialogArgs; import com.android.permissioncontroller.permission.ui.GrantPermissionsViewHandler; import com.android.permissioncontroller.permission.ui.model.AppPermissionViewModel; @@ -86,13 +87,12 @@ import com.android.settingslib.RestrictedLockUtils; import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin; import com.android.settingslib.widget.ActionBarShadowController; -import kotlin.Pair; - import java.util.Map; import java.util.Objects; -import java.util.Optional; import java.util.Set; +import kotlin.Pair; + /** * Show and manage a single permission group for an app. * @@ -195,9 +195,10 @@ public class AppPermissionFragment extends SettingsWithLargeHeader getActivity().getApplication(), mPackageName, mPermGroupName, mUser, mSessionId); mViewModel = new ViewModelProvider(this, factory).get(AppPermissionViewModel.class); Handler delayHandler = new Handler(Looper.getMainLooper()); - mViewModel.getShowPermissionRationaleLiveData().observe(this, show -> { - showPermissionRationaleDialog(Optional.ofNullable(show).orElse(false)); - }); + if (KotlinUtils.INSTANCE.isPermissionRationaleEnabled()) { + mViewModel.getSafetyLabelInfoLiveData().observe(this, + this::showPermissionRationaleDialog); + } mViewModel.getButtonStateLiveData().observe(this, buttonState -> { if (mIsInitialLoad) { setRadioButtonsState(buttonState); @@ -294,6 +295,11 @@ public class AppPermissionFragment extends SettingsWithLargeHeader root.requireViewById(R.id.app_permission_rationale_container); mAppPermissionRationaleContent = root.requireViewById(R.id.app_permission_rationale_content); + if (!KotlinUtils.INSTANCE.isPermissionRationaleEnabled()) { + hidePermissionRationaleContainer(); + } else { + setPermissionRationaleContainer(root, context); + } getActivity().setTitle( getPreferenceManager().getContext().getString(R.string.app_permission_title, @@ -301,9 +307,19 @@ public class AppPermissionFragment extends SettingsWithLargeHeader return root; } - private void showPermissionRationaleDialog(boolean showPermissionRationale) { - if (!showPermissionRationale) { - mAppPermissionRationaleContainer.setVisibility(View.GONE); + private void setPermissionRationaleContainer(View root, Context context) { + ((TextView) root.requireViewById(R.id.app_permission_rationale_message)).setText( + context.getString(R.string.app_permission_rationale_message)); + ((TextView) root.requireViewById(R.id.app_permission_rationale_title)).setText( + context.getString(R.string.app_location_permission_rationale_title)); + ((TextView) root.requireViewById(R.id.app_permission_rationale_subtitle)).setText( + context.getString(R.string.app_location_permission_rationale_subtitle)); + } + + private void showPermissionRationaleDialog(@Nullable SafetyLabelInfo safetyLabelInfo) { + if (safetyLabelInfo == null + || !mViewModel.shouldShowPermissionRationale(safetyLabelInfo, mPermGroupName)) { + hidePermissionRationaleContainer(); } else { mAppPermissionRationaleContainer.setVisibility(View.VISIBLE); mAppPermissionRationaleContent.setOnClickListener((v) -> { @@ -312,6 +328,10 @@ public class AppPermissionFragment extends SettingsWithLargeHeader } } + private void hidePermissionRationaleContainer() { + mAppPermissionRationaleContainer.setVisibility(View.GONE); + } + private void setBottomLinkState(TextView view, String caller, String action) { if ((Objects.equals(caller, AppPermissionGroupsFragment.class.getName()) && action.equals(Intent.ACTION_MANAGE_APP_PERMISSIONS)) diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/model/AppPermissionViewModel.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/model/AppPermissionViewModel.kt index 2e1744f54..ac20a7748 100644 --- a/PermissionController/src/com/android/permissioncontroller/permission/ui/model/AppPermissionViewModel.kt +++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/model/AppPermissionViewModel.kt @@ -60,6 +60,7 @@ import com.android.permissioncontroller.permission.data.SmartUpdateMediatorLiveD import com.android.permissioncontroller.permission.data.get import com.android.permissioncontroller.permission.model.livedatatypes.LightAppPermGroup import com.android.permissioncontroller.permission.model.livedatatypes.LightPermission +import com.android.permissioncontroller.permission.model.livedatatypes.SafetyLabelInfo import com.android.permissioncontroller.permission.service.PermissionChangeStorageImpl import com.android.permissioncontroller.permission.service.v33.PermissionDecisionStorageImpl import com.android.permissioncontroller.permission.ui.AdvancedConfirmDialogArgs @@ -77,8 +78,10 @@ import com.android.permissioncontroller.permission.ui.v34.PermissionRationaleAct import com.android.permissioncontroller.permission.utils.KotlinUtils import com.android.permissioncontroller.permission.utils.KotlinUtils.getDefaultPrecision import com.android.permissioncontroller.permission.utils.KotlinUtils.isLocationAccuracyEnabled +import com.android.permissioncontroller.permission.utils.KotlinUtils.isPermissionRationaleEnabled import com.android.permissioncontroller.permission.utils.LocationUtils import com.android.permissioncontroller.permission.utils.PermissionMapping +import com.android.permissioncontroller.permission.utils.PermissionRationales import com.android.permissioncontroller.permission.utils.SafetyNetLogger import com.android.permissioncontroller.permission.utils.Utils import com.android.permissioncontroller.permission.utils.navigateSafe @@ -111,6 +114,8 @@ class AppPermissionViewModel( const val PHOTO_PICKER_REQUEST_CODE = 1 } + val safetyLabelInfoLiveData = SafetyLabelInfoLiveData[packageName, user] + interface ConfirmDialogShowingFragment { fun showConfirmDialog( changeRequest: ChangeRequest, @@ -179,36 +184,6 @@ class AppPermissionViewModel( val showAdminSupportLiveData = MutableLiveData<RestrictedLockUtils.EnforcedAdmin>() /** - * A livedata for determining the display state of safety label information - */ - val showPermissionRationaleLiveData = object : SmartUpdateMediatorLiveData<Boolean>() { - private val safetyLabelInfoLiveData = SafetyLabelInfoLiveData[packageName, user] - - init { - if (PermissionMapping.isSafetyLabelAwarePermission(permGroupName)) { - addSource(safetyLabelInfoLiveData) { update() } - } else { - value = false - } - } - - override fun onUpdate() { - if (safetyLabelInfoLiveData.isStale) { - return - } - - val safetyLabel = safetyLabelInfoLiveData.value?.safetyLabel - if (safetyLabel == null) { - value = false - return - } - - value = PermissionMapping.getSafetyLabelSharingPurposesForGroup( - safetyLabel, permGroupName).any() - } - } - - /** * A livedata which determines which detail string, if any, should be shown */ val fullStorageStateLiveData = object : SmartUpdateMediatorLiveData<FullStoragePackageState>() { @@ -574,6 +549,14 @@ class AppPermissionViewModel( return true } + fun shouldShowPermissionRationale( + safetyLabelInfo: SafetyLabelInfo, + groupName: String + ): Boolean { + return PermissionRationales.shouldShowPermissionRationale( + safetyLabelInfo.safetyLabel, groupName) + } + /** * Shows the Permission Rationale Dialog. For use with U+ only, otherwise no-op. * @@ -581,6 +564,10 @@ class AppPermissionViewModel( * @param groupName The name of the permission group whose fragment should be opened */ fun showPermissionRationaleActivity(activity: Activity, groupName: String) { + if (!isPermissionRationaleEnabled()) { + return + } + val intent = Intent(activity, PermissionRationaleActivity::class.java).apply { putExtra(Intent.EXTRA_PACKAGE_NAME, packageName) putExtra(Intent.EXTRA_PERMISSION_GROUP_NAME, groupName) diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/model/GrantPermissionsViewModel.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/model/GrantPermissionsViewModel.kt index 01fd079c6..b82536dd5 100644 --- a/PermissionController/src/com/android/permissioncontroller/permission/ui/model/GrantPermissionsViewModel.kt +++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/model/GrantPermissionsViewModel.kt @@ -120,7 +120,9 @@ import com.android.permissioncontroller.permission.utils.KotlinUtils.getDefaultP import com.android.permissioncontroller.permission.utils.KotlinUtils.grantBackgroundRuntimePermissions import com.android.permissioncontroller.permission.utils.KotlinUtils.grantForegroundRuntimePermissions import com.android.permissioncontroller.permission.utils.KotlinUtils.isLocationAccuracyEnabled +import com.android.permissioncontroller.permission.utils.KotlinUtils.isPermissionRationaleEnabled import com.android.permissioncontroller.permission.utils.PermissionMapping +import com.android.permissioncontroller.permission.utils.PermissionRationales import com.android.permissioncontroller.permission.utils.SafetyNetLogger import com.android.permissioncontroller.permission.utils.Utils @@ -145,16 +147,12 @@ class GrantPermissionsViewModel( private val LOG_TAG = GrantPermissionsViewModel::class.java.simpleName private val user = Process.myUserHandle() private val packageInfoLiveData = LightPackageInfoLiveData[packageName, user] - private val safetyLabelInfoLiveData = - if (requestedPermissions.any { PermissionMapping.isSafetyLabelAwarePermission(it) }) { - SafetyLabelInfoLiveData[packageName, user] - } else { - null - } + private val safetyLabelInfoLiveData = SafetyLabelInfoLiveData[packageName, user] private val dpm = app.getSystemService(DevicePolicyManager::class.java)!! private val permissionPolicy = dpm.getPermissionPolicy(null) private val permGroupsToSkip = mutableListOf<String>() private var groupStates = mutableMapOf<Pair<String, Boolean>, GroupState>() + private val permissionRationaleEnabled: Boolean by lazy { isPermissionRationaleEnabled() } private var autoGrantNotifier: AutoGrantPermissionsNotifier? = null private fun getAutoGrantNotifier(): AutoGrantPermissionsNotifier { @@ -163,6 +161,7 @@ class GrantPermissionsViewModel( } private lateinit var packageInfo: LightPackageInfo + private var safetyLabel: SafetyLabel? = null // All permissions that could possibly be affected by the provided requested permissions, before // filtering system fixed, auto grant, etc. @@ -199,10 +198,12 @@ class GrantPermissionsViewModel( private val LOG_TAG = GrantPermissionsViewModel::class.java.simpleName private val packagePermissionsLiveData = PackagePermissionsLiveData[packageName, user] + // TODO(b/260873483): only query safety label for supported permission groups. should only + // query location, but currently queries for all groups init { addSource(packagePermissionsLiveData) { onPackageLoaded() } addSource(packageInfoLiveData) { onPackageLoaded() } - if (safetyLabelInfoLiveData != null) { + if (permissionRationaleEnabled) { addSource(safetyLabelInfoLiveData) { onPackageLoaded() } } @@ -213,10 +214,17 @@ class GrantPermissionsViewModel( private fun onPackageLoaded() { if (packageInfoLiveData.isStale || packagePermissionsLiveData.isStale || - (safetyLabelInfoLiveData != null && safetyLabelInfoLiveData.isStale)) { + (permissionRationaleEnabled && safetyLabelInfoLiveData.isStale)) { return } + safetyLabel = + if (permissionRationaleEnabled) { + safetyLabelInfoLiveData.value?.safetyLabel + } else { + null + } + val groups = packagePermissionsLiveData.value val pI = packageInfoLiveData.value if (groups == null || groups.isEmpty() || pI == null) { @@ -560,15 +568,14 @@ class GrantPermissionsViewModel( } } - val safetyLabel = safetyLabelInfoLiveData?.value?.safetyLabel - requestInfos.add(RequestInfo( groupInfo, buttonVisibilities, locationVisibilities, message, detailMessage, - shouldShowPermissionRationale(safetyLabel, groupState))) + showPermissionRationale = shouldShowPermissionRationale( + safetyLabel, groupState))) } sortPermissionGroups(requestInfos) @@ -584,19 +591,6 @@ class GrantPermissionsViewModel( } } - private fun shouldShowPermissionRationale( - safetyLabel: SafetyLabel?, - groupState: GroupState - ): Boolean { - if (safetyLabel == null) { - return false - } - - val purposes = PermissionMapping.getSafetyLabelSharingPurposesForGroup(safetyLabel, - groupState.group.permGroupName) - return purposes.isNotEmpty() - } - fun sortPermissionGroups(requestInfos: MutableList<RequestInfo>) { requestInfos.sortWith { rhs, lhs -> val rhsHasOneTime = rhs.buttonVisibilities[ALLOW_ONE_TIME_BUTTON] @@ -613,6 +607,14 @@ class GrantPermissionsViewModel( } } + private fun shouldShowPermissionRationale( + safetyLabel: SafetyLabel?, + groupState: GroupState + ): Boolean { + return PermissionRationales.shouldShowPermissionRationale( + safetyLabel, groupState.group.permGroupName) + } + /** * Converts a list of LightAppPermGroups into a list of GroupStates */ diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/model/v34/PermissionRationaleViewModel.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/model/v34/PermissionRationaleViewModel.kt index 54d94f913..8de8de726 100644 --- a/PermissionController/src/com/android/permissioncontroller/permission/ui/model/v34/PermissionRationaleViewModel.kt +++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/model/v34/PermissionRationaleViewModel.kt @@ -29,18 +29,23 @@ import android.util.Log import androidx.annotation.RequiresApi import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModelProvider +import com.android.permission.safetylabel.DataCategory +import com.android.permission.safetylabel.DataType +import com.android.permission.safetylabel.DataTypeConstants +import com.android.permission.safetylabel.SafetyLabel import com.android.permissioncontroller.Constants import com.android.permissioncontroller.R import com.android.permissioncontroller.permission.data.SafetyLabelInfoLiveData import com.android.permissioncontroller.permission.data.SmartUpdateMediatorLiveData import com.android.permissioncontroller.permission.data.get +import com.android.permissioncontroller.permission.model.livedatatypes.SafetyLabelInfo.Companion.UNAVAILABLE import com.android.permissioncontroller.permission.ui.ManagePermissionsActivity import com.android.permissioncontroller.permission.ui.ManagePermissionsActivity.EXTRA_RESULT_PERMISSION_INTERACTED import com.android.permissioncontroller.permission.ui.ManagePermissionsActivity.EXTRA_RESULT_PERMISSION_RESULT import com.android.permissioncontroller.permission.ui.v34.PermissionRationaleActivity import com.android.permissioncontroller.permission.utils.KotlinUtils import com.android.permissioncontroller.permission.utils.KotlinUtils.getAppStoreIntent -import com.android.permissioncontroller.permission.utils.PermissionMapping +import com.android.permissioncontroller.permission.utils.SafetyLabelPermissionMapping import com.android.settingslib.HelpUtils /** @@ -85,7 +90,7 @@ class PermissionRationaleViewModel( data class PermissionRationaleInfo( val groupName: String, val installSourcePackageName: String?, - val installSourceLabel: String?, + val installSourceLabel: CharSequence?, val purposeSet: Set<Int> ) @@ -106,15 +111,18 @@ class PermissionRationaleViewModel( } val safetyLabelInfo = safetyLabelInfoLiveData.value + val safetyLabel = safetyLabelInfo?.safetyLabel - if (safetyLabelInfo?.safetyLabel == null) { + if (safetyLabelInfo == null || + safetyLabelInfo == UNAVAILABLE || + safetyLabel == null) { Log.e(LOG_TAG, "Safety label for $packageName not found") value = null return } val installSourcePackageName = safetyLabelInfo.installSourcePackageName - val installSourceLabel: String? = + val installSourceLabel: CharSequence? = installSourcePackageName?.let { KotlinUtils.getPackageLabel(app, it, Process.myUserHandle()) } @@ -124,8 +132,36 @@ class PermissionRationaleViewModel( permissionGroupName, installSourcePackageName, installSourceLabel, - PermissionMapping.getSafetyLabelSharingPurposesForGroup( - safetyLabelInfo.safetyLabel, permissionGroupName)) + getSafetyLabelSharingPurposesForGroup(safetyLabel, permissionGroupName)) + } + + private fun getSafetyLabelSharingPurposesForGroup( + safetyLabel: SafetyLabel, + groupName: String + ): Set<Int> { + val purposeSet = mutableSetOf<Int>() + val categoriesForPermission: List<String> = + SafetyLabelPermissionMapping.getCategoriesForPermissionGroup(groupName) + categoriesForPermission.forEach categoryLoop@{ category -> + val dataCategory: DataCategory? = safetyLabel.dataLabel.dataShared[category] + if (dataCategory == null) { + // Continue to next + return@categoryLoop + } + val typesForCategory = DataTypeConstants.getValidDataTypesForCategory(category) + typesForCategory.forEach typeLoop@{ type -> + val dataType: DataType? = dataCategory.dataTypes[type] + if (dataType == null) { + // Continue to next + return@typeLoop + } + if (dataType.purposeSet.isNotEmpty()) { + purposeSet.addAll(dataType.purposeSet) + } + } + } + + return purposeSet } } diff --git a/PermissionController/src/com/android/permissioncontroller/permission/utils/PermissionMapping.kt b/PermissionController/src/com/android/permissioncontroller/permission/utils/PermissionMapping.kt index 45a7fb02e..3fde87108 100644 --- a/PermissionController/src/com/android/permissioncontroller/permission/utils/PermissionMapping.kt +++ b/PermissionController/src/com/android/permissioncontroller/permission/utils/PermissionMapping.kt @@ -21,13 +21,7 @@ import android.content.pm.PackageManager import android.content.pm.PermissionInfo import android.health.connect.HealthPermissions.HEALTH_PERMISSION_GROUP import android.util.Log - import com.android.modules.utils.build.SdkLevel -import com.android.permission.safetylabel.DataCategory -import com.android.permission.safetylabel.DataCategoryConstants -import com.android.permission.safetylabel.DataType -import com.android.permission.safetylabel.DataTypeConstants -import com.android.permission.safetylabel.SafetyLabel /** * This file contains the canonical mapping of permission to permission group, used in the @@ -37,9 +31,6 @@ object PermissionMapping { private val LOG_TAG = "PermissionMapping" - private val PERMISSION_GROUPS_TO_DATA_CATEGORIES: Map<String, List<String>> = mapOf( - Manifest.permission_group.LOCATION to listOf(DataCategoryConstants.CATEGORY_LOCATION)) - @JvmField val SENSOR_DATA_PERMISSIONS: List<String> = listOf( @@ -335,64 +326,4 @@ object PermissionMapping { fun isHealthPermission(permissionName: String): Boolean { return HEALTH_PERMISSIONS_SET.contains(permissionName) } - - /** - * Get the sharing purposes for a SafetyLabel related to a specific permission group. - */ - @JvmStatic - fun getSafetyLabelSharingPurposesForGroup( - safetyLabel: SafetyLabel, - groupName: String - ): Set<Int> { - val purposeSet = mutableSetOf<Int>() - val categoriesForPermission = getDataCategoriesForPermissionGroup(groupName) - categoriesForPermission.forEach categoryLoop@{ category -> - val dataCategory: DataCategory? = safetyLabel.dataLabel.dataShared[category] - if (dataCategory == null) { - // Continue to next - return@categoryLoop - } - val typesForCategory = DataTypeConstants.getValidDataTypesForCategory(category) - typesForCategory.forEach typeLoop@{ type -> - val dataType: DataType? = dataCategory.dataTypes[type] - if (dataType == null) { - // Continue to next - return@typeLoop - } - if (dataType.purposeSet.isNotEmpty()) { - purposeSet.addAll(dataType.purposeSet) - } - } - } - - return purposeSet - } - - /** - * Get the SafetyLabel categories pertaining to a specified permission group. - * - * @return The categories, or an empty list if the group does not have a supported mapping - * to safety label category - */ - fun getDataCategoriesForPermissionGroup(permissionGroupName: String): List<String> { - return if (isSafetyLabelAwarePermission(permissionGroupName)) { - PERMISSION_GROUPS_TO_DATA_CATEGORIES[permissionGroupName] ?: emptyList() - } else { - emptyList() - } - } - - /** - * Whether this permission group maps to a SafetyLabel data category. - * - * @param permissionGroupName the permission group name - */ - @JvmStatic - fun isSafetyLabelAwarePermission(permissionGroupName: String): Boolean { - if (!KotlinUtils.isPermissionRationaleEnabled()) { - return false - } - - return PERMISSION_GROUPS_TO_DATA_CATEGORIES.containsKey(permissionGroupName) - } } diff --git a/PermissionController/src/com/android/permissioncontroller/permission/utils/PermissionRationales.kt b/PermissionController/src/com/android/permissioncontroller/permission/utils/PermissionRationales.kt new file mode 100644 index 000000000..ede87e84f --- /dev/null +++ b/PermissionController/src/com/android/permissioncontroller/permission/utils/PermissionRationales.kt @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2023 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.permissioncontroller.permission.utils + +import com.android.permission.safetylabel.DataCategory +import com.android.permission.safetylabel.DataType +import com.android.permission.safetylabel.DataTypeConstants +import com.android.permission.safetylabel.SafetyLabel + +/** + * A set of util functions used for permission rationale dialog. + */ +object PermissionRationales { + + /** + * Returns if the permission rationale dialog should be shown. + * @param safetyLabel the [SafetyLabel] bundle provided + * @param groupName the permission group name + * @return true if the permission dialog should be shown, otherwise false. + */ + fun shouldShowPermissionRationale( + safetyLabel: SafetyLabel?, + groupName: String + ): Boolean { + if (safetyLabel == null || safetyLabel.dataLabel.dataShared.isEmpty()) { + return false + } + val categoriesForPermission: List<String> = + SafetyLabelPermissionMapping.getCategoriesForPermissionGroup(groupName) + categoriesForPermission.forEach categoryLoop@{ category -> + val dataCategory: DataCategory? = safetyLabel.dataLabel.dataShared[category] + if (dataCategory == null) { + // Continue to next + return@categoryLoop + } + val typesForCategory = DataTypeConstants.getValidDataTypesForCategory(category) + typesForCategory.forEach typeLoop@{ type -> + val dataType: DataType? = dataCategory.dataTypes[type] + if (dataType == null) { + // Continue to next + return@typeLoop + } + if (dataType.purposeSet.isNotEmpty()) { + return true + } + } + } + return false + } +}
\ No newline at end of file diff --git a/PermissionController/src/com/android/permissioncontroller/permission/utils/SafetyLabelPermissionMapping.kt b/PermissionController/src/com/android/permissioncontroller/permission/utils/SafetyLabelPermissionMapping.kt new file mode 100644 index 000000000..5fd852bb6 --- /dev/null +++ b/PermissionController/src/com/android/permissioncontroller/permission/utils/SafetyLabelPermissionMapping.kt @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2022 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.permissioncontroller.permission.utils + +import android.Manifest +import com.android.permission.safetylabel.DataCategoryConstants + +/** + * This file contains the canonical mapping of permission and permission group to Safety Label + * categories and types used in the Permission settings screens and grant dialog. It also includes + * methods related to that mapping. + */ +object SafetyLabelPermissionMapping { + + /** + * Get the Safety Label categories pertaining to a specified permission group. + * + * @param groupName the permission group name + * + * @return The categories or an empty list if the group does not have supported and mapped group + * to safety label category + */ + fun getCategoriesForPermissionGroup(groupName: String): List<String> { + return if (groupName == Manifest.permission_group.LOCATION) { + listOf(DataCategoryConstants.CATEGORY_LOCATION) + } else { + emptyList() + } + } +} diff --git a/SafetyLabel/java/com/android/permission/safetylabel/DataLabel.java b/SafetyLabel/java/com/android/permission/safetylabel/DataLabel.java index 676cfa6d7..564d5479f 100644 --- a/SafetyLabel/java/com/android/permission/safetylabel/DataLabel.java +++ b/SafetyLabel/java/com/android/permission/safetylabel/DataLabel.java @@ -32,10 +32,7 @@ import java.util.Map; * {@link DataCategory} */ public class DataLabel { - - @VisibleForTesting(otherwise = VisibleForTesting.PACKAGE_PRIVATE) - static final String KEY_DATA_LABEL = "data_labels"; - + @VisibleForTesting static final String KEY_DATA_LABEL = "data_labels"; private final Map<String, DataCategory> mDataCollected; private final Map<String, DataCategory> mDataShared; diff --git a/SafetyLabel/java/com/android/permission/safetylabel/DataType.java b/SafetyLabel/java/com/android/permission/safetylabel/DataType.java index 3350a5942..68770f823 100644 --- a/SafetyLabel/java/com/android/permission/safetylabel/DataType.java +++ b/SafetyLabel/java/com/android/permission/safetylabel/DataType.java @@ -35,10 +35,7 @@ import java.util.Set; * metadata related to the data usage purpose. */ public class DataType { - - @VisibleForTesting(otherwise = VisibleForTesting.PACKAGE_PRIVATE) - static final String KEY_PURPOSES = "purposes"; - + @VisibleForTesting static final String KEY_PURPOSES = "purposes"; @VisibleForTesting static final String KEY_IS_COLLECTION_OPTIONAL = "is_collection_optional"; @VisibleForTesting static final String KEY_EPHEMERAL = "ephemeral"; diff --git a/SafetyLabel/java/com/android/permission/safetylabel/SafetyLabel.java b/SafetyLabel/java/com/android/permission/safetylabel/SafetyLabel.java index 0ada11719..3eb8767b9 100644 --- a/SafetyLabel/java/com/android/permission/safetylabel/SafetyLabel.java +++ b/SafetyLabel/java/com/android/permission/safetylabel/SafetyLabel.java @@ -28,10 +28,6 @@ import java.util.Locale; /** Safety Label representation containing zero or more {@link DataCategory} for data shared */ public class SafetyLabel { private static final String TAG = "SafetyLabel"; - - private static final long INITIAL_METADATA_VERSION = 1L; - private static final long INITIAL_SAFETY_LABELS_VERSION = 1L; - @VisibleForTesting static final String KEY_SAFETY_LABEL = "safety_labels"; public static final String KEY_VERSION = "version"; private final DataLabel mDataLabel; @@ -73,44 +69,6 @@ public class SafetyLabel { return new SafetyLabel(dataLabel); } - /** - * Create a placeholder SafetyLabel for use for testing. - * This is accessible through device configs. - */ - @NonNull - public static SafetyLabel getPlaceholderSafetyLabel() { - return getSafetyLabelFromMetadata(getPlaceholderMetadataBundle()); - } - - @NonNull - private static PersistableBundle getPlaceholderMetadataBundle() { - PersistableBundle approximateLocationBundle = new PersistableBundle(); - approximateLocationBundle.putIntArray(DataType.KEY_PURPOSES, - new int[] { 1, 2, 3, 4, 5, 6, 7 }); - - PersistableBundle locationBundle = new PersistableBundle(); - locationBundle.putPersistableBundle(DataTypeConstants.LOCATION_APPROX_LOCATION, - approximateLocationBundle); - - PersistableBundle dataSharedBundle = new PersistableBundle(); - dataSharedBundle.putPersistableBundle(DataCategoryConstants.CATEGORY_LOCATION, - locationBundle); - - PersistableBundle dataLabelBundle = new PersistableBundle(); - dataLabelBundle.putPersistableBundle(DataLabelConstants.DATA_USAGE_SHARED, - dataSharedBundle); - - PersistableBundle safetyLabelBundle = new PersistableBundle(); - safetyLabelBundle.putLong(KEY_VERSION, INITIAL_SAFETY_LABELS_VERSION); - safetyLabelBundle.putPersistableBundle(DataLabel.KEY_DATA_LABEL, dataLabelBundle); - - PersistableBundle metadataBundle = new PersistableBundle(); - metadataBundle.putLong(KEY_VERSION, INITIAL_METADATA_VERSION); - metadataBundle.putPersistableBundle(KEY_SAFETY_LABEL, safetyLabelBundle); - - return metadataBundle; - } - /** Returns the data label for the safety label */ @NonNull public DataLabel getDataLabel() { |