summaryrefslogtreecommitdiff
path: root/PermissionController/src/com/android/permissioncontroller/permission/utils/Utils.java
diff options
context:
space:
mode:
Diffstat (limited to 'PermissionController/src/com/android/permissioncontroller/permission/utils/Utils.java')
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/utils/Utils.java326
1 files changed, 287 insertions, 39 deletions
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/utils/Utils.java b/PermissionController/src/com/android/permissioncontroller/permission/utils/Utils.java
index d4354bd72..ad384cca7 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/utils/Utils.java
+++ b/PermissionController/src/com/android/permissioncontroller/permission/utils/Utils.java
@@ -42,6 +42,7 @@ import static android.content.pm.PackageManager.FLAG_PERMISSION_USER_SENSITIVE_W
import static android.content.pm.PackageManager.FLAG_PERMISSION_USER_SENSITIVE_WHEN_GRANTED;
import static android.content.pm.PackageManager.MATCH_SYSTEM_ONLY;
import static android.health.connect.HealthConnectManager.ACTION_MANAGE_HEALTH_PERMISSIONS;
+import static android.health.connect.HealthPermissions.HEALTH_PERMISSION_GROUP;
import static android.os.UserHandle.myUserId;
import static com.android.permissioncontroller.Constants.EXTRA_SESSION_ID;
@@ -73,6 +74,7 @@ import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.hardware.SensorPrivacyManager;
+import android.health.connect.HealthConnectManager;
import android.os.Binder;
import android.os.Build;
import android.os.Parcelable;
@@ -109,6 +111,8 @@ import com.android.permissioncontroller.permission.model.AppPermissionGroup;
import com.android.permissioncontroller.permission.model.livedatatypes.LightAppPermGroup;
import com.android.permissioncontroller.permission.model.livedatatypes.LightPackageInfo;
+import kotlin.Triple;
+
import java.lang.annotation.Retention;
import java.time.ZonedDateTime;
import java.time.temporal.ChronoUnit;
@@ -120,8 +124,6 @@ import java.util.Locale;
import java.util.Random;
import java.util.Set;
-import kotlin.Triple;
-
public final class Utils {
@Retention(SOURCE)
@@ -160,9 +162,6 @@ public final class Utils {
public static final String PROPERTY_SYSTEM_EXEMPT_HIBERNATION_ENABLED =
"system_exempt_hibernation_enabled";
- /** Whether to show the Permissions Hub. */
- private static final String PROPERTY_PERMISSIONS_HUB_ENABLED = "permissions_hub_enabled";
-
/** The timeout for one-time permissions */
private static final String PROPERTY_ONE_TIME_PERMISSIONS_TIMEOUT_MILLIS =
"one_time_permissions_timeout_millis";
@@ -171,10 +170,6 @@ public final class Utils {
private static final String PROPERTY_ONE_TIME_PERMISSIONS_KILLED_DELAY_MILLIS =
"one_time_permissions_killed_delay_millis";
- /** Whether to show location access check notifications. */
- private static final String PROPERTY_LOCATION_ACCESS_CHECK_ENABLED =
- "location_access_check_enabled";
-
/** Whether to show health permission in various permission controller UIs. */
private static final String PROPERTY_HEALTH_PERMISSION_UI_ENABLED =
"health_permission_ui_enabled";
@@ -195,9 +190,6 @@ public final class Utils {
public static final String PROPERTY_PERMISSION_DECISIONS_MAX_DATA_AGE_MILLIS =
"permission_decisions_max_data_age_millis";
- /** Whether or not warning banner is displayed when device sensors are off **/
- public static final String PROPERTY_WARNING_BANNER_DISPLAY_ENABLED = "warning_banner_enabled";
-
/** All permission whitelists. */
public static final int FLAGS_PERMISSION_WHITELIST_ALL =
PackageManager.FLAG_PERMISSION_WHITELIST_SYSTEM
@@ -222,10 +214,13 @@ public final class Utils {
public static final long ONE_TIME_PERMISSIONS_KILLED_DELAY_MILLIS = 5 * 1000;
private static final ArrayMap<String, Integer> PERM_GROUP_REQUEST_RES;
+ private static final ArrayMap<String, Integer> PERM_GROUP_REQUEST_DEVICE_AWARE_RES;
private static final ArrayMap<String, Integer> PERM_GROUP_REQUEST_DETAIL_RES;
private static final ArrayMap<String, Integer> PERM_GROUP_BACKGROUND_REQUEST_RES;
+ private static final ArrayMap<String, Integer> PERM_GROUP_BACKGROUND_REQUEST_DEVICE_AWARE_RES;
private static final ArrayMap<String, Integer> PERM_GROUP_BACKGROUND_REQUEST_DETAIL_RES;
private static final ArrayMap<String, Integer> PERM_GROUP_UPGRADE_REQUEST_RES;
+ private static final ArrayMap<String, Integer> PERM_GROUP_UPGRADE_REQUEST_DEVICE_AWARE_RES;
private static final ArrayMap<String, Integer> PERM_GROUP_UPGRADE_REQUEST_DETAIL_RES;
/** Permission -> Sensor codes */
@@ -282,6 +277,38 @@ public final class Utils {
PERM_GROUP_REQUEST_RES.put(SENSORS, R.string.permgrouprequest_sensors);
PERM_GROUP_REQUEST_RES.put(NOTIFICATIONS, R.string.permgrouprequest_notifications);
+ PERM_GROUP_REQUEST_DEVICE_AWARE_RES = new ArrayMap<>();
+ PERM_GROUP_REQUEST_DEVICE_AWARE_RES.put(CONTACTS,
+ R.string.permgrouprequest_device_aware_contacts);
+ PERM_GROUP_REQUEST_DEVICE_AWARE_RES.put(LOCATION,
+ R.string.permgrouprequest_device_aware_location);
+ PERM_GROUP_REQUEST_DEVICE_AWARE_RES.put(NEARBY_DEVICES,
+ R.string.permgrouprequest_device_aware_nearby_devices);
+ PERM_GROUP_REQUEST_DEVICE_AWARE_RES.put(CALENDAR,
+ R.string.permgrouprequest_device_aware_calendar);
+ PERM_GROUP_REQUEST_DEVICE_AWARE_RES.put(SMS, R.string.permgrouprequest_device_aware_sms);
+ PERM_GROUP_REQUEST_DEVICE_AWARE_RES.put(STORAGE,
+ R.string.permgrouprequest_device_aware_storage);
+ PERM_GROUP_REQUEST_DEVICE_AWARE_RES.put(READ_MEDIA_AURAL,
+ R.string.permgrouprequest_device_aware_read_media_aural);
+ PERM_GROUP_REQUEST_DEVICE_AWARE_RES.put(READ_MEDIA_VISUAL,
+ R.string.permgrouprequest_device_aware_read_media_visual);
+ PERM_GROUP_REQUEST_DEVICE_AWARE_RES.put(MICROPHONE,
+ R.string.permgrouprequest_device_aware_microphone);
+ PERM_GROUP_REQUEST_DEVICE_AWARE_RES
+ .put(ACTIVITY_RECOGNITION,
+ R.string.permgrouprequest_device_aware_activityRecognition);
+ PERM_GROUP_REQUEST_DEVICE_AWARE_RES.put(CAMERA,
+ R.string.permgrouprequest_device_aware_camera);
+ PERM_GROUP_REQUEST_DEVICE_AWARE_RES.put(CALL_LOG,
+ R.string.permgrouprequest_device_aware_calllog);
+ PERM_GROUP_REQUEST_DEVICE_AWARE_RES.put(PHONE,
+ R.string.permgrouprequest_device_aware_phone);
+ PERM_GROUP_REQUEST_DEVICE_AWARE_RES.put(SENSORS,
+ R.string.permgrouprequest_device_aware_sensors);
+ PERM_GROUP_REQUEST_DEVICE_AWARE_RES.put(NOTIFICATIONS,
+ R.string.permgrouprequest_device_aware_notifications);
+
PERM_GROUP_REQUEST_DETAIL_RES = new ArrayMap<>();
PERM_GROUP_REQUEST_DETAIL_RES.put(LOCATION, R.string.permgrouprequestdetail_location);
PERM_GROUP_REQUEST_DETAIL_RES.put(MICROPHONE, R.string.permgrouprequestdetail_microphone);
@@ -297,6 +324,16 @@ public final class Utils {
PERM_GROUP_BACKGROUND_REQUEST_RES
.put(SENSORS, R.string.permgroupbackgroundrequest_sensors);
+ PERM_GROUP_BACKGROUND_REQUEST_DEVICE_AWARE_RES = new ArrayMap<>();
+ PERM_GROUP_BACKGROUND_REQUEST_DEVICE_AWARE_RES
+ .put(LOCATION, R.string.permgroupbackgroundrequest_device_aware_location);
+ PERM_GROUP_BACKGROUND_REQUEST_DEVICE_AWARE_RES
+ .put(MICROPHONE, R.string.permgroupbackgroundrequest_device_aware_microphone);
+ PERM_GROUP_BACKGROUND_REQUEST_DEVICE_AWARE_RES
+ .put(CAMERA, R.string.permgroupbackgroundrequest_device_aware_camera);
+ PERM_GROUP_BACKGROUND_REQUEST_DEVICE_AWARE_RES
+ .put(SENSORS, R.string.permgroupbackgroundrequest_device_aware_sensors);
+
PERM_GROUP_BACKGROUND_REQUEST_DETAIL_RES = new ArrayMap<>();
PERM_GROUP_BACKGROUND_REQUEST_DETAIL_RES
.put(LOCATION, R.string.permgroupbackgroundrequestdetail_location);
@@ -313,6 +350,16 @@ public final class Utils {
PERM_GROUP_UPGRADE_REQUEST_RES.put(CAMERA, R.string.permgroupupgraderequest_camera);
PERM_GROUP_UPGRADE_REQUEST_RES.put(SENSORS, R.string.permgroupupgraderequest_sensors);
+ PERM_GROUP_UPGRADE_REQUEST_DEVICE_AWARE_RES = new ArrayMap<>();
+ PERM_GROUP_UPGRADE_REQUEST_DEVICE_AWARE_RES.put(LOCATION,
+ R.string.permgroupupgraderequest_device_aware_location);
+ PERM_GROUP_UPGRADE_REQUEST_DEVICE_AWARE_RES.put(MICROPHONE,
+ R.string.permgroupupgraderequest_device_aware_microphone);
+ PERM_GROUP_UPGRADE_REQUEST_DEVICE_AWARE_RES.put(CAMERA,
+ R.string.permgroupupgraderequest_device_aware_camera);
+ PERM_GROUP_UPGRADE_REQUEST_DEVICE_AWARE_RES.put(SENSORS,
+ R.string.permgroupupgraderequest_device_aware_sensors);
+
PERM_GROUP_UPGRADE_REQUEST_DETAIL_RES = new ArrayMap<>();
PERM_GROUP_UPGRADE_REQUEST_DETAIL_RES
.put(LOCATION, R.string.permgroupupgraderequestdetail_location);
@@ -698,11 +745,16 @@ public final class Utils {
* @param groupName The name of the permission group
* @param context A context to resolve resources
* @param requestRes The resource id of the grant request message
- *
* @return The formatted message to be used as title when granting permissions
*/
- public static CharSequence getRequestMessage(CharSequence appLabel, String packageName,
- String groupName, Context context, @StringRes int requestRes) {
+ @NonNull
+ public static CharSequence getRequestMessage(
+ @NonNull String appLabel,
+ @NonNull String packageName,
+ @NonNull String groupName,
+ @NonNull Context context,
+ @StringRes int requestRes) {
+ String escapedAppLabel = Html.escapeHtml(appLabel);
boolean isIsolatedStorage;
try {
@@ -712,15 +764,76 @@ public final class Utils {
}
if (groupName.equals(STORAGE) && isIsolatedStorage) {
return Html.fromHtml(
- String.format(context.getResources().getConfiguration().getLocales().get(0),
+ String.format(
+ context.getResources().getConfiguration().getLocales().get(0),
context.getString(R.string.permgrouprequest_storage_isolated),
- appLabel), 0);
+ escapedAppLabel),
+ 0);
} else if (requestRes != 0) {
- return Html.fromHtml(context.getResources().getString(requestRes, appLabel), 0);
+ return Html.fromHtml(context.getResources().getString(requestRes, escapedAppLabel), 0);
}
- return Html.fromHtml(context.getString(R.string.permission_warning_template, appLabel,
- loadGroupDescription(context, groupName, context.getPackageManager())), 0);
+ return Html.fromHtml(
+ context.getString(
+ R.string.permission_warning_template,
+ escapedAppLabel,
+ loadGroupDescription(context, groupName, context.getPackageManager())),
+ 0);
+ }
+
+ /**
+ * Get the message shown to grant a permission group to an app.
+ *
+ * @param appLabel The label of the app
+ * @param packageName The package name of the app
+ * @param groupName The name of the permission group
+ * @param context A context to resolve resources
+ * @param requestRes The resource id of the grant request message
+ * @return The formatted message to be used as title when granting permissions
+ */
+ @NonNull
+ public static CharSequence getRequestMessage(
+ @NonNull String appLabel,
+ @NonNull String packageName,
+ @NonNull String groupName,
+ @NonNull String deviceLabel,
+ @NonNull Context context,
+ Boolean isDeviceAwareMessage,
+ @StringRes int requestRes) {
+ if (!isDeviceAwareMessage) {
+ return getRequestMessage(appLabel, packageName, groupName, context, requestRes);
+ }
+ String escapedAppLabel = Html.escapeHtml(appLabel);
+
+ boolean isIsolatedStorage;
+ try {
+ isIsolatedStorage = !isNonIsolatedStorage(context, packageName);
+ } catch (NameNotFoundException e) {
+ isIsolatedStorage = false;
+ }
+ if (groupName.equals(STORAGE) && isIsolatedStorage) {
+ String escapedDeviceLabel = Html.escapeHtml(deviceLabel);
+ return Html.fromHtml(
+ String.format(
+ context.getResources().getConfiguration().getLocales().get(0),
+ context.getString(
+ R.string.permgrouprequest_device_aware_storage_isolated),
+ escapedAppLabel,
+ escapedDeviceLabel),
+ 0);
+
+ } else if (requestRes != 0) {
+ String escapedDeviceLabel = Html.escapeHtml(deviceLabel);
+ return Html.fromHtml(context.getResources().getString(requestRes, escapedAppLabel,
+ escapedDeviceLabel), 0);
+ }
+
+ return Html.fromHtml(
+ context.getString(
+ R.string.permission_warning_template,
+ escapedAppLabel,
+ loadGroupDescription(context, groupName, context.getPackageManager())),
+ 0);
}
private static CharSequence loadGroupDescription(Context context, String groupName,
@@ -838,8 +951,9 @@ public final class Utils {
if (context.getPackageManager().resolveActivity(intent, 0) == null) {
return;
}
- MenuItem searchItem = menu.add(Menu.NONE, Menu.NONE, Menu.NONE, R.string.search_menu);
- searchItem.setIcon(R.drawable.ic_search_24dp);
+ MenuItem searchItem = menu.add(Menu.NONE, Menu.NONE, Menu.NONE,
+ com.android.settingslib.search.widget.R.string.search_menu);
+ searchItem.setIcon(com.android.settingslib.search.widget.R.drawable.ic_search_24dp);
searchItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
searchItem.setOnMenuItemClickListener(item -> {
try {
@@ -917,16 +1031,6 @@ public final class Utils {
}
/**
- * Whether the Location Access Check is enabled.
- *
- * @return {@code true} iff the Location Access Check is enabled.
- */
- public static boolean isLocationAccessCheckEnabled() {
- return DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_PRIVACY,
- PROPERTY_LOCATION_ACCESS_CHECK_ENABLED, true);
- }
-
- /**
* Whether we should show health permissions as platform permissions in the various
* permission controller UI.
*/
@@ -943,6 +1047,70 @@ public final class Utils {
}
/**
+ * Returns true if the group name passed is that of the Platform health group.
+ * @param permGroupName name of the group that needs to be checked.
+ */
+ @ChecksSdkIntAtLeast(api = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ public static Boolean isHealthPermissionGroup(String permGroupName) {
+ return SdkLevel.isAtLeastU() && HEALTH_PERMISSION_GROUP.equals(permGroupName);
+ }
+
+ /**
+ * Return whether health permission setting entry should be shown or not
+ *
+ * Should not show Health permissions preference if the package doesn't handle
+ * VIEW_PERMISSION_USAGE_INTENT.
+ *
+ * Will show if above is true AND permission is already granted.
+ *
+ * @param packageInfo the {@link PackageInfo} app which uses the permission
+ * @param permGroupName the health permission group name to show
+ * @return {@code TRUE} iff health permission should be shown
+ */
+ @ChecksSdkIntAtLeast(api = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ public static Boolean shouldShowHealthPermission(LightPackageInfo packageInfo,
+ String permGroupName) {
+ if (!isHealthPermissionGroup(permGroupName)) {
+ return false;
+ }
+
+ PermissionControllerApplication app = PermissionControllerApplication.get();
+ PackageManager pm = app.getPackageManager();
+ Context context = getUserContext(app, UserHandle.getUserHandleForUid(packageInfo.getUid()));
+
+ List<PermissionInfo> permissions = new ArrayList<>();
+ try {
+ permissions.addAll(getPermissionInfosForGroup(pm, permGroupName));
+ } catch (NameNotFoundException e) {
+ Log.e(LOG_TAG, "No permissions found for permission group " + permGroupName);
+ return false;
+ }
+
+ // Check in permission is already granted as we should not hide it in the UX at that point.
+ List<String> grantedPermissions = packageInfo.getGrantedPermissions();
+ for (PermissionInfo permission : permissions) {
+ boolean isCurrentlyGranted = grantedPermissions.contains(permission.name);
+ if (isCurrentlyGranted) {
+ Log.d(LOG_TAG, "At least one Health permission group permission is granted, "
+ + "show permission group entry");
+ return true;
+ }
+ }
+
+ Intent viewUsageIntent = new Intent(Intent.ACTION_VIEW_PERMISSION_USAGE);
+ viewUsageIntent.addCategory(HealthConnectManager.CATEGORY_HEALTH_PERMISSIONS);
+ viewUsageIntent.setPackage(packageInfo.getPackageName());
+
+ ResolveInfo resolveInfo = pm.resolveActivity(viewUsageIntent, PackageManager.MATCH_ALL);
+ if (resolveInfo == null) {
+ Log.e(LOG_TAG, "Package that asks for Health permission must also handle "
+ + "VIEW_PERMISSION_USAGE_INTENT.");
+ return false;
+ }
+ return true;
+ }
+
+ /**
* Get a device protected storage based shared preferences. Avoid storing sensitive data in it.
*
* @param context the context to get the shared preferences
@@ -1013,7 +1181,21 @@ public final class Utils {
* @return The id or 0 if the permission group doesn't exist or have a message
*/
public static int getRequest(String groupName) {
- return PERM_GROUP_REQUEST_RES.getOrDefault(groupName, 0);
+ return getRequest(groupName, false);
+ }
+
+ /**
+ * The resource id for the request message for a permission group for a specific device
+ *
+ * @param groupName Permission group name
+ * @return The id or 0 if the permission group doesn't exist or have a message
+ */
+ public static int getRequest(String groupName, Boolean isDeviceAwareMessage) {
+ if (isDeviceAwareMessage) {
+ return PERM_GROUP_REQUEST_DEVICE_AWARE_RES.getOrDefault(groupName, 0);
+ } else {
+ return PERM_GROUP_REQUEST_RES.getOrDefault(groupName, 0);
+ }
}
/**
@@ -1031,7 +1213,22 @@ public final class Utils {
* @return The id or 0 if the permission group doesn't exist or have a message
*/
public static int getBackgroundRequest(String groupName) {
- return PERM_GROUP_BACKGROUND_REQUEST_RES.getOrDefault(groupName, 0);
+ return getBackgroundRequest(groupName, false);
+ }
+
+ /**
+ * The resource id for the background request message for a permission group for a specific
+ * device
+ *
+ * @param groupName Permission group name
+ * @return The id or 0 if the permission group doesn't exist or have a message
+ */
+ public static int getBackgroundRequest(String groupName, Boolean isDeviceAwareMessage) {
+ if (isDeviceAwareMessage) {
+ return PERM_GROUP_BACKGROUND_REQUEST_DEVICE_AWARE_RES.getOrDefault(groupName, 0);
+ } else {
+ return PERM_GROUP_BACKGROUND_REQUEST_RES.getOrDefault(groupName, 0);
+ }
}
/**
@@ -1049,7 +1246,21 @@ public final class Utils {
* @return The id or 0 if the permission group doesn't exist or have a message
*/
public static int getUpgradeRequest(String groupName) {
- return PERM_GROUP_UPGRADE_REQUEST_RES.getOrDefault(groupName, 0);
+ return getUpgradeRequest(groupName, false);
+ }
+
+ /**
+ * The resource id for the upgrade request message for a permission group for a specific device.
+ *
+ * @param groupName Permission group name
+ * @return The id or 0 if the permission group doesn't exist or have a message
+ */
+ public static int getUpgradeRequest(String groupName, Boolean isDeviceAwareMessage) {
+ if (isDeviceAwareMessage) {
+ return PERM_GROUP_UPGRADE_REQUEST_DEVICE_AWARE_RES.getOrDefault(groupName, 0);
+ } else {
+ return PERM_GROUP_UPGRADE_REQUEST_RES.getOrDefault(groupName, 0);
+ }
}
/**
@@ -1062,6 +1273,45 @@ public final class Utils {
}
/**
+ * The resource id for the fine location request message for a specific device
+ *
+ * @return The id
+ */
+ public static int getFineLocationRequest(Boolean isDeviceAwareMessage) {
+ if (isDeviceAwareMessage) {
+ return R.string.permgrouprequest_device_aware_fineupgrade;
+ } else {
+ return R.string.permgrouprequest_fineupgrade;
+ }
+ }
+
+ /**
+ * The resource id for the coarse location request message for a specific device
+ *
+ * @return The id
+ */
+ public static int getCoarseLocationRequest(Boolean isDeviceAwareMessage) {
+ if (isDeviceAwareMessage) {
+ return R.string.permgrouprequest_device_aware_coarselocation;
+ } else {
+ return R.string.permgrouprequest_coarselocation;
+ }
+ }
+
+ /**
+ * The resource id for the get more photos request message for a specific device
+ *
+ * @return The id
+ */
+ public static int getMorePhotosRequest(Boolean isDeviceAwareMessage) {
+ if (isDeviceAwareMessage) {
+ return R.string.permgrouprequest_device_aware_more_photos;
+ } else {
+ return R.string.permgrouprequest_more_photos;
+ }
+ }
+
+ /**
* Returns a random session ID value that's guaranteed to not be {@code INVALID_SESSION_ID}.
*
* @return A valid session ID.
@@ -1249,10 +1499,8 @@ public final class Utils {
* Returns if a card should be shown if the sensor is blocked
**/
public static boolean shouldDisplayCardIfBlocked(@NonNull String permissionGroupName) {
- return DeviceConfig.getBoolean(
- DeviceConfig.NAMESPACE_PRIVACY, PROPERTY_WARNING_BANNER_DISPLAY_ENABLED, true) && (
- CAMERA.equals(permissionGroupName) || MICROPHONE.equals(permissionGroupName)
- || LOCATION.equals(permissionGroupName));
+ return CAMERA.equals(permissionGroupName) || MICROPHONE.equals(permissionGroupName)
+ || LOCATION.equals(permissionGroupName);
}
/**