diff options
Diffstat (limited to 'PermissionController/src/com/android/permissioncontroller/permission/utils/Utils.java')
-rw-r--r-- | PermissionController/src/com/android/permissioncontroller/permission/utils/Utils.java | 326 |
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); } /** |