summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Joe Castro <joecastro@google.com> 2023-02-04 00:26:57 +0000
committer Joe Castro <joecastro@google.com> 2023-02-18 00:03:33 +0000
commitdba921871424ac9913344419c7307593522e62b3 (patch)
tree9449c3622365de24b5af111c3db44321114525e2
parentad1faafe3e6bfe3ced93b113a847832c9b8a6bc2 (diff)
Don't unnecessarily query package metadata for SafetyLabels
Only querying metadata for packages in SafetyLabel display when we know that the package has permissions that should include safety labels. Right now that is limited to LOCATION permissions. As part of this, I consolidated some of the utilities and made it so there is less branching and less need to check in multiple places whether the feature is enabled. Bug: 260873483 Test: atest Change-Id: I30efd202985fecb95eb919952deaf555d289fc0e
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/data/LightInstallSourceInfoLiveData.kt2
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/data/SafetyLabelInfoLiveData.kt63
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/GrantPermissionsActivity.java2
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/AppPermissionFragment.java38
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/model/AppPermissionViewModel.kt47
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/model/GrantPermissionsViewModel.kt50
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/model/v34/PermissionRationaleViewModel.kt48
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/utils/PermissionMapping.kt69
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/utils/PermissionRationales.kt64
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/utils/SafetyLabelPermissionMapping.kt44
-rw-r--r--SafetyLabel/java/com/android/permission/safetylabel/DataLabel.java5
-rw-r--r--SafetyLabel/java/com/android/permission/safetylabel/DataType.java5
-rw-r--r--SafetyLabel/java/com/android/permission/safetylabel/SafetyLabel.java42
13 files changed, 204 insertions, 275 deletions
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/data/LightInstallSourceInfoLiveData.kt b/PermissionController/src/com/android/permissioncontroller/permission/data/LightInstallSourceInfoLiveData.kt
index 543d8eae2..7a817eb6d 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")
- SafetyLabelInfoLiveData.invalidateSingle(packageName to user)
+ LightInstallSourceInfoLiveData.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 d2ba7031d..e8102c2e0 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/data/SafetyLabelInfoLiveData.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/data/SafetyLabelInfoLiveData.kt
@@ -18,14 +18,10 @@ 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.permission.safetylabel.DataCategoryConstants
-import com.android.permission.safetylabel.DataLabelConstants
-import com.android.permission.safetylabel.DataTypeConstants
+import com.android.modules.utils.build.SdkLevel
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
@@ -83,6 +79,11 @@ 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
@@ -91,11 +92,16 @@ private constructor(
return
}
+ if (isPlaceholderSafetyLabelDataEnabled()) {
+ postValue(SafetyLabelInfo(SafetyLabel.getPlaceholderSafetyLabel(),
+ installSourcePackageName))
+ return
+ }
+
val safetyLabelInfo: SafetyLabelInfo =
try {
- val metadataBundle: PersistableBundle = getAppMetadata()
- val safetyLabel: SafetyLabel? =
- SafetyLabel.getSafetyLabelFromMetadata(metadataBundle)
+ val safetyLabel: SafetyLabel? = SafetyLabel.getSafetyLabelFromMetadata(
+ app.packageManager.getAppMetadata(packageName))
if (safetyLabel != null) {
SafetyLabelInfo(safetyLabel, installSourcePackageName)
} else {
@@ -109,49 +115,8 @@ 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 e97c6ef4b..8f73f6577 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 = "GrantPermissionsActivit";
+ private static final String LOG_TAG = "GrantPermissionsActivity";
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 007707363..9fad46648 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/AppPermissionFragment.java
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/AppPermissionFragment.java
@@ -73,7 +73,6 @@ 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;
@@ -87,12 +86,13 @@ 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,10 +195,9 @@ 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());
- if (KotlinUtils.INSTANCE.isPermissionRationaleEnabled()) {
- mViewModel.getSafetyLabelInfoLiveData().observe(this,
- this::showPermissionRationaleDialog);
- }
+ mViewModel.getShowPermissionRationaleLiveData().observe(this, show -> {
+ showPermissionRationaleDialog(Optional.ofNullable(show).orElse(false));
+ });
mViewModel.getButtonStateLiveData().observe(this, buttonState -> {
if (mIsInitialLoad) {
setRadioButtonsState(buttonState);
@@ -295,11 +294,6 @@ 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,
@@ -307,19 +301,9 @@ public class AppPermissionFragment extends SettingsWithLargeHeader
return root;
}
- 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();
+ private void showPermissionRationaleDialog(boolean showPermissionRationale) {
+ if (!showPermissionRationale) {
+ mAppPermissionRationaleContainer.setVisibility(View.GONE);
} else {
mAppPermissionRationaleContainer.setVisibility(View.VISIBLE);
mAppPermissionRationaleContent.setOnClickListener((v) -> {
@@ -328,10 +312,6 @@ 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 ac20a7748..2e1744f54 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/model/AppPermissionViewModel.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/model/AppPermissionViewModel.kt
@@ -60,7 +60,6 @@ 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
@@ -78,10 +77,8 @@ 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
@@ -114,8 +111,6 @@ class AppPermissionViewModel(
const val PHOTO_PICKER_REQUEST_CODE = 1
}
- val safetyLabelInfoLiveData = SafetyLabelInfoLiveData[packageName, user]
-
interface ConfirmDialogShowingFragment {
fun showConfirmDialog(
changeRequest: ChangeRequest,
@@ -184,6 +179,36 @@ 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>() {
@@ -549,14 +574,6 @@ 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.
*
@@ -564,10 +581,6 @@ 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 b82536dd5..01fd079c6 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/model/GrantPermissionsViewModel.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/model/GrantPermissionsViewModel.kt
@@ -120,9 +120,7 @@ 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
@@ -147,12 +145,16 @@ class GrantPermissionsViewModel(
private val LOG_TAG = GrantPermissionsViewModel::class.java.simpleName
private val user = Process.myUserHandle()
private val packageInfoLiveData = LightPackageInfoLiveData[packageName, user]
- private val safetyLabelInfoLiveData = SafetyLabelInfoLiveData[packageName, user]
+ private val safetyLabelInfoLiveData =
+ if (requestedPermissions.any { PermissionMapping.isSafetyLabelAwarePermission(it) }) {
+ SafetyLabelInfoLiveData[packageName, user]
+ } else {
+ null
+ }
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 {
@@ -161,7 +163,6 @@ 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.
@@ -198,12 +199,10 @@ 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 (permissionRationaleEnabled) {
+ if (safetyLabelInfoLiveData != null) {
addSource(safetyLabelInfoLiveData) { onPackageLoaded() }
}
@@ -214,17 +213,10 @@ class GrantPermissionsViewModel(
private fun onPackageLoaded() {
if (packageInfoLiveData.isStale ||
packagePermissionsLiveData.isStale ||
- (permissionRationaleEnabled && safetyLabelInfoLiveData.isStale)) {
+ (safetyLabelInfoLiveData != null && 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) {
@@ -568,14 +560,15 @@ class GrantPermissionsViewModel(
}
}
+ val safetyLabel = safetyLabelInfoLiveData?.value?.safetyLabel
+
requestInfos.add(RequestInfo(
groupInfo,
buttonVisibilities,
locationVisibilities,
message,
detailMessage,
- showPermissionRationale = shouldShowPermissionRationale(
- safetyLabel, groupState)))
+ shouldShowPermissionRationale(safetyLabel, groupState)))
}
sortPermissionGroups(requestInfos)
@@ -591,6 +584,19 @@ 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]
@@ -607,14 +613,6 @@ 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 8de8de726..54d94f913 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,23 +29,18 @@ 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.SafetyLabelPermissionMapping
+import com.android.permissioncontroller.permission.utils.PermissionMapping
import com.android.settingslib.HelpUtils
/**
@@ -90,7 +85,7 @@ class PermissionRationaleViewModel(
data class PermissionRationaleInfo(
val groupName: String,
val installSourcePackageName: String?,
- val installSourceLabel: CharSequence?,
+ val installSourceLabel: String?,
val purposeSet: Set<Int>
)
@@ -111,18 +106,15 @@ class PermissionRationaleViewModel(
}
val safetyLabelInfo = safetyLabelInfoLiveData.value
- val safetyLabel = safetyLabelInfo?.safetyLabel
- if (safetyLabelInfo == null ||
- safetyLabelInfo == UNAVAILABLE ||
- safetyLabel == null) {
+ if (safetyLabelInfo?.safetyLabel == null) {
Log.e(LOG_TAG, "Safety label for $packageName not found")
value = null
return
}
val installSourcePackageName = safetyLabelInfo.installSourcePackageName
- val installSourceLabel: CharSequence? =
+ val installSourceLabel: String? =
installSourcePackageName?.let {
KotlinUtils.getPackageLabel(app, it, Process.myUserHandle())
}
@@ -132,36 +124,8 @@ class PermissionRationaleViewModel(
permissionGroupName,
installSourcePackageName,
installSourceLabel,
- 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
+ PermissionMapping.getSafetyLabelSharingPurposesForGroup(
+ safetyLabelInfo.safetyLabel, permissionGroupName))
}
}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/utils/PermissionMapping.kt b/PermissionController/src/com/android/permissioncontroller/permission/utils/PermissionMapping.kt
index 3fde87108..45a7fb02e 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/utils/PermissionMapping.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/utils/PermissionMapping.kt
@@ -21,7 +21,13 @@ 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
@@ -31,6 +37,9 @@ 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(
@@ -326,4 +335,64 @@ 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
deleted file mode 100644
index ede87e84f..000000000
--- a/PermissionController/src/com/android/permissioncontroller/permission/utils/PermissionRationales.kt
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * 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
deleted file mode 100644
index 5fd852bb6..000000000
--- a/PermissionController/src/com/android/permissioncontroller/permission/utils/SafetyLabelPermissionMapping.kt
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * 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 564d5479f..676cfa6d7 100644
--- a/SafetyLabel/java/com/android/permission/safetylabel/DataLabel.java
+++ b/SafetyLabel/java/com/android/permission/safetylabel/DataLabel.java
@@ -32,7 +32,10 @@ import java.util.Map;
* {@link DataCategory}
*/
public class DataLabel {
- @VisibleForTesting static final String KEY_DATA_LABEL = "data_labels";
+
+ @VisibleForTesting(otherwise = VisibleForTesting.PACKAGE_PRIVATE)
+ 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 68770f823..3350a5942 100644
--- a/SafetyLabel/java/com/android/permission/safetylabel/DataType.java
+++ b/SafetyLabel/java/com/android/permission/safetylabel/DataType.java
@@ -35,7 +35,10 @@ import java.util.Set;
* metadata related to the data usage purpose.
*/
public class DataType {
- @VisibleForTesting static final String KEY_PURPOSES = "purposes";
+
+ @VisibleForTesting(otherwise = VisibleForTesting.PACKAGE_PRIVATE)
+ 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 3eb8767b9..0ada11719 100644
--- a/SafetyLabel/java/com/android/permission/safetylabel/SafetyLabel.java
+++ b/SafetyLabel/java/com/android/permission/safetylabel/SafetyLabel.java
@@ -28,6 +28,10 @@ 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;
@@ -69,6 +73,44 @@ 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() {