summaryrefslogtreecommitdiff
path: root/PermissionController/src/com/android/permissioncontroller/permission/utils
diff options
context:
space:
mode:
Diffstat (limited to 'PermissionController/src/com/android/permissioncontroller/permission/utils')
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/utils/AndroidUtils.kt55
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/utils/DebugUtils.kt23
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/utils/KotlinUtils.kt36
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/utils/PermissionMapping.kt49
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/utils/SystemTimeSource.kt6
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/utils/TimeSource.kt14
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/utils/UserSensitiveFlagsUtils.kt57
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/utils/v34/SafetyLabelUtils.kt4
8 files changed, 127 insertions, 117 deletions
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/utils/AndroidUtils.kt b/PermissionController/src/com/android/permissioncontroller/permission/utils/AndroidUtils.kt
index 6a6623da7..a5f78aa53 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/utils/AndroidUtils.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/utils/AndroidUtils.kt
@@ -26,19 +26,19 @@ import android.content.pm.PackageManager
import android.content.pm.ResolveInfo
import android.os.Looper
import android.os.UserHandle
-import kotlinx.coroutines.asCoroutineDispatcher
import java.util.concurrent.Executors
+import kotlinx.coroutines.asCoroutineDispatcher
-/**
- * Gets an [Application] instance from a regular [Context]
- */
-val Context.application: Application get() = when (this) {
- is Application -> this
- is Activity -> application
- is Service -> application
- is ContextWrapper -> baseContext.application
- else -> applicationContext as Application
-}
+/** Gets an [Application] instance from a regular [Context] */
+val Context.application: Application
+ get() =
+ when (this) {
+ is Application -> this
+ is Activity -> application
+ is Service -> application
+ is ContextWrapper -> baseContext.application
+ else -> applicationContext as Application
+ }
/**
* The number of threads in the IPC thread pool. Set to the maximum number of binder threads allowed
@@ -46,21 +46,16 @@ val Context.application: Application get() = when (this) {
*/
const val IPC_THREAD_POOL_COUNT = 8
-/**
- * A coroutine dispatcher with a fixed thread pool size, to be used for background tasks
- */
+/** A coroutine dispatcher with a fixed thread pool size, to be used for background tasks */
val IPC = Executors.newFixedThreadPool(IPC_THREAD_POOL_COUNT).asCoroutineDispatcher()
-/**
- * Assert that an operation is running on main thread
- */
-fun ensureMainThread() = check(Looper.myLooper() == Looper.getMainLooper()) {
- "Only meant to be used on the main thread"
-}
+/** Assert that an operation is running on main thread */
+fun ensureMainThread() =
+ check(Looper.myLooper() == Looper.getMainLooper()) {
+ "Only meant to be used on the main thread"
+ }
-/**
- * A more readable version of [PackageManager.updatePermissionFlags]
- */
+/** A more readable version of [PackageManager.updatePermissionFlags] */
fun PackageManager.updatePermissionFlags(
permissionName: String,
packageName: String,
@@ -68,18 +63,14 @@ fun PackageManager.updatePermissionFlags(
vararg flags: Pair<Int, Boolean>
) {
val mask = flags.fold(0, { mask, (flag, _) -> mask or flag })
- val value = flags.fold(0,
- { mask2, (flag, flagValue) -> if (flagValue) mask2 or flag else mask2 })
+ val value =
+ flags.fold(0, { mask2, (flag, flagValue) -> if (flagValue) mask2 or flag else mask2 })
updatePermissionFlags(permissionName, packageName, mask, value, user)
}
-/**
- * Gets a [ComponentInfo] from a [ResolveInfo]
- */
+/** Gets a [ComponentInfo] from a [ResolveInfo] */
val ResolveInfo.componentInfo: ComponentInfo
get() {
return (activityInfo as ComponentInfo?)
- ?: serviceInfo
- ?: providerInfo
- ?: throw IllegalStateException("Missing ComponentInfo!")
- } \ No newline at end of file
+ ?: serviceInfo ?: providerInfo ?: throw IllegalStateException("Missing ComponentInfo!")
+ }
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/utils/DebugUtils.kt b/PermissionController/src/com/android/permissioncontroller/permission/utils/DebugUtils.kt
index cf8a69b40..96d634ded 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/utils/DebugUtils.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/utils/DebugUtils.kt
@@ -25,24 +25,21 @@ import java.util.Collections.reverse
*/
fun shortStackTrace() = permissionsStackTrace().toShortString()
-/**
- * [StackTraceElement]s of only the permission-related frames
- */
-fun permissionsStackTrace() = stackTraceWithin("com.android.permissioncontroller")
- .dropLastWhile { it.className.contains(".DebugUtils") }
+/** [StackTraceElement]s of only the permission-related frames */
+fun permissionsStackTrace() =
+ stackTraceWithin("com.android.permissioncontroller").dropLastWhile {
+ it.className.contains(".DebugUtils")
+ }
/**
* [StackTraceElement]s of only frames who's [full class name][StackTraceElement.getClassName]
* starts with [pkgPrefix]
*/
-fun stackTraceWithin(pkgPrefix: String) = Thread
- .currentThread()
- .stackTrace
- .dropWhile {
- !it.className.startsWith(pkgPrefix)
- }.takeWhile {
- it.className.startsWith(pkgPrefix)
- }
+fun stackTraceWithin(pkgPrefix: String) =
+ Thread.currentThread()
+ .stackTrace
+ .dropWhile { !it.className.startsWith(pkgPrefix) }
+ .takeWhile { it.className.startsWith(pkgPrefix) }
/**
* Renders a stack trace slice to a short-ish single-line string.
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/utils/KotlinUtils.kt b/PermissionController/src/com/android/permissioncontroller/permission/utils/KotlinUtils.kt
index 358f86f4b..f2aa0ae66 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/utils/KotlinUtils.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/utils/KotlinUtils.kt
@@ -25,6 +25,7 @@ import android.Manifest.permission.POST_NOTIFICATIONS
import android.Manifest.permission.READ_MEDIA_IMAGES
import android.Manifest.permission.READ_MEDIA_VIDEO
import android.Manifest.permission_group.NOTIFICATIONS
+import android.app.Activity
import android.app.ActivityManager
import android.app.AppOpsManager
import android.app.AppOpsManager.MODE_ALLOWED
@@ -59,8 +60,10 @@ import android.health.connect.HealthConnectManager
import android.os.Build
import android.os.Bundle
import android.os.UserHandle
+import android.os.UserManager
import android.permission.PermissionManager
import android.provider.DeviceConfig
+import android.provider.MediaStore
import android.provider.Settings
import android.safetylabel.SafetyLabelConstants.PERMISSION_RATIONALE_ENABLED
import android.safetylabel.SafetyLabelConstants.SAFETY_LABEL_CHANGE_NOTIFICATIONS_ENABLED
@@ -297,17 +300,14 @@ object KotlinUtils {
)
}
- /**
- * Whether the Photo Picker Prompt is supported by the device
- *
- */
+ /** Whether the Photo Picker Prompt is supported by the device */
@ChecksSdkIntAtLeast(api = Build.VERSION_CODES.UPSIDE_DOWN_CAKE, codename = "UpsideDownCake")
fun isPhotoPickerPromptSupported(): Boolean {
val app = PermissionControllerApplication.get()
return SdkLevel.isAtLeastU() &&
- !DeviceUtils.isAuto(app) &&
- !DeviceUtils.isTelevision(app) &&
- !DeviceUtils.isWear(app)
+ !DeviceUtils.isAuto(app) &&
+ !DeviceUtils.isTelevision(app) &&
+ !DeviceUtils.isWear(app)
}
/*
@@ -650,6 +650,28 @@ object KotlinUtils {
}
}
+ fun openPhotoPickerForApp(
+ activity: Activity,
+ uid: Int,
+ requestedPermissions: List<String>,
+ requestCode: Int
+ ) {
+ // A clone profile doesn't have a MediaProvider. If the app's user is a clone profile, open
+ // the photo picker in the parent profile
+ val appUser = UserHandle.getUserHandleForUid(uid)
+ val userManager =
+ activity.createContextAsUser(appUser, 0).getSystemService(UserManager::class.java)!!
+ val user = if (userManager.isCloneProfile) {
+ userManager.getProfileParent(appUser) ?: appUser
+ } else {
+ appUser
+ }
+ val pickerIntent = Intent(MediaStore.ACTION_USER_SELECT_IMAGES_FOR_APP)
+ .putExtra(Intent.EXTRA_UID, uid)
+ .setType(getMimeTypeForPermissions(requestedPermissions))
+ activity.startActivityForResultAsUser(pickerIntent, requestCode, user)
+ }
+
/** Return a specific MIME type, if a set of permissions is associated with one */
fun getMimeTypeForPermissions(permissions: List<String>): String? {
if (permissions.contains(READ_MEDIA_IMAGES) && !permissions.contains(READ_MEDIA_VIDEO)) {
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/utils/PermissionMapping.kt b/PermissionController/src/com/android/permissioncontroller/permission/utils/PermissionMapping.kt
index 32d3a5325..840a033c3 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/utils/PermissionMapping.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/utils/PermissionMapping.kt
@@ -23,10 +23,9 @@ 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.permissioncontroller.permission.model.livedatatypes.LightAppPermGroup
import com.android.permission.safetylabel.DataCategoryConstants
+import com.android.permissioncontroller.permission.model.livedatatypes.LightAppPermGroup
/**
* This file contains the canonical mapping of permission to permission group, used in the
@@ -36,15 +35,16 @@ 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))
+ 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(
Manifest.permission_group.LOCATION,
Manifest.permission_group.CAMERA,
- Manifest.permission_group.MICROPHONE)
+ Manifest.permission_group.MICROPHONE
+ )
@JvmField
val STORAGE_SUPERGROUP_PERMISSIONS: List<String> =
@@ -53,7 +53,8 @@ object PermissionMapping {
listOf(
Manifest.permission_group.STORAGE,
Manifest.permission_group.READ_MEDIA_AURAL,
- Manifest.permission_group.READ_MEDIA_VISUAL)
+ Manifest.permission_group.READ_MEDIA_VISUAL
+ )
val PARTIAL_MEDIA_PERMISSIONS: MutableSet<String> = mutableSetOf()
@@ -68,7 +69,6 @@ object PermissionMapping {
private val HEALTH_PERMISSIONS_SET: MutableSet<String> = mutableSetOf()
-
init {
PLATFORM_PERMISSIONS[Manifest.permission.READ_CONTACTS] = Manifest.permission_group.CONTACTS
PLATFORM_PERMISSIONS[Manifest.permission.WRITE_CONTACTS] =
@@ -202,7 +202,6 @@ object PermissionMapping {
* platform permission.
*
* @param permission the permission to resolve
- *
* @return The group the permission belongs to
*/
@JvmStatic
@@ -214,7 +213,6 @@ object PermissionMapping {
* Get name of the permission group a permission belongs to.
*
* @param permission the [info][PermissionInfo] of the permission to resolve
- *
* @return The group the permission belongs to
*/
@JvmStatic
@@ -230,9 +228,8 @@ object PermissionMapping {
* Get the names for all platform permissions belonging to a group.
*
* @param group the group
- *
* @return The permission names or an empty list if the group does not have platform runtime
- * permissions
+ * permissions
*/
@JvmStatic
fun getPlatformPermissionNamesOfGroup(group: String): List<String> {
@@ -245,19 +242,19 @@ object PermissionMapping {
*
* @param pm Package manager to use to resolve permission infos
* @param group the group
- *
* @return The infos for platform permissions belonging to the group or an empty list if the
- * group does not have platform runtime permissions
+ * group does not have platform runtime permissions
*/
@JvmStatic
fun getPlatformPermissionsOfGroup(pm: PackageManager, group: String): List<PermissionInfo> {
val permInfos = mutableListOf<PermissionInfo>()
for (permName in PLATFORM_PERMISSION_GROUPS[group] ?: emptyList()) {
- val permInfo: PermissionInfo = try {
+ val permInfo: PermissionInfo =
+ try {
pm.getPermissionInfo(permName, 0)
- } catch (e: PackageManager.NameNotFoundException) {
- throw IllegalStateException("$permName not defined by platform", e)
- }
+ } catch (e: PackageManager.NameNotFoundException) {
+ throw IllegalStateException("$permName not defined by platform", e)
+ }
permInfos.add(permInfo)
}
return permInfos
@@ -300,6 +297,7 @@ object PermissionMapping {
/**
* Whether the permission group supports one-time
+ *
* @param permissionGroup The permission group to check
* @return `true` iff the group supports one-time
*/
@@ -308,9 +306,7 @@ object PermissionMapping {
return ONE_TIME_PERMISSION_GROUPS.contains(permissionGroup)
}
- /**
- * Adds health permissions as platform permissions.
- */
+ /** Adds health permissions as platform permissions. */
@JvmStatic
fun addHealthPermissionsToPlatform(permissions: Set<String>) {
if (permissions.isEmpty()) {
@@ -338,8 +334,9 @@ object PermissionMapping {
return emptySet()
}
- val appSupportsPickerPrompt = group
- .permissions[Manifest.permission.READ_MEDIA_VISUAL_USER_SELECTED]?.isImplicit == false
+ val appSupportsPickerPrompt =
+ group.permissions[Manifest.permission.READ_MEDIA_VISUAL_USER_SELECTED]?.isImplicit ==
+ false
return if (appSupportsPickerPrompt) {
PARTIAL_MEDIA_PERMISSIONS
@@ -348,9 +345,7 @@ object PermissionMapping {
}
}
- /**
- * Returns true if the given permission is a health platform permission.
- */
+ /** Returns true if the given permission is a health platform permission. */
@JvmStatic
fun isHealthPermission(permissionName: String): Boolean {
return HEALTH_PERMISSIONS_SET.contains(permissionName)
@@ -386,8 +381,8 @@ object PermissionMapping {
/**
* 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
+ * @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 (isSafetyLabelAwarePermissionGroup(permissionGroupName)) {
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/utils/SystemTimeSource.kt b/PermissionController/src/com/android/permissioncontroller/permission/utils/SystemTimeSource.kt
index dc05ededc..116c498be 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/utils/SystemTimeSource.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/utils/SystemTimeSource.kt
@@ -18,9 +18,7 @@ package com.android.permissioncontroller.permission.utils
import android.os.SystemClock
-/**
- * Time source that uses the system time.
- */
+/** Time source that uses the system time. */
class SystemTimeSource : TimeSource {
override fun currentTimeMillis(): Long {
@@ -30,4 +28,4 @@ class SystemTimeSource : TimeSource {
override fun elapsedRealtime(): Long {
return SystemClock.elapsedRealtime()
}
-} \ No newline at end of file
+}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/utils/TimeSource.kt b/PermissionController/src/com/android/permissioncontroller/permission/utils/TimeSource.kt
index 00b93f405..29883e1f3 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/utils/TimeSource.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/utils/TimeSource.kt
@@ -16,18 +16,12 @@
package com.android.permissioncontroller.permission.utils
-/**
- * Interface for system time components.
- */
+/** Interface for system time components. */
interface TimeSource {
- /**
- * Returns the current time in milliseconds.
- */
+ /** Returns the current time in milliseconds. */
fun currentTimeMillis(): Long
- /**
- * Returns milliseconds since boot, including time spent in sleep.
- */
+ /** Returns milliseconds since boot, including time spent in sleep. */
fun elapsedRealtime(): Long
-} \ No newline at end of file
+}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/utils/UserSensitiveFlagsUtils.kt b/PermissionController/src/com/android/permissioncontroller/permission/utils/UserSensitiveFlagsUtils.kt
index 3cd9891ee..50cacf876 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/utils/UserSensitiveFlagsUtils.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/utils/UserSensitiveFlagsUtils.kt
@@ -25,9 +25,9 @@ import com.android.permissioncontroller.PermissionControllerApplication
import com.android.permissioncontroller.permission.data.UserSensitivityLiveData
import com.android.permissioncontroller.permission.model.livedatatypes.UidSensitivityState
import com.android.permissioncontroller.permission.utils.Utils.FLAGS_ALWAYS_USER_SENSITIVE
+import java.lang.IllegalStateException
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
-import java.lang.IllegalStateException
private const val LOG_TAG = "UserSensitiveFlagsUtils"
@@ -35,10 +35,9 @@ private const val LOG_TAG = "UserSensitiveFlagsUtils"
* Update the [PackageManager.FLAG_PERMISSION_USER_SENSITIVE_WHEN_GRANTED] and
* [PackageManager.FLAG_PERMISSION_USER_SENSITIVE_WHEN_DENIED] for all apps of this user.
*
- * @see UserSensitivityLiveData.loadDataAndPostValue
- *
* @param user The user for whom packages will be updated
* @param callback A callback which will be executed when finished
+ * @see UserSensitivityLiveData.loadDataAndPostValue
*/
fun updateUserSensitiveForUser(user: UserHandle, callback: Runnable) {
GlobalScope.launch(IPC) {
@@ -47,7 +46,8 @@ fun updateUserSensitiveForUser(user: UserHandle, callback: Runnable) {
if (uidUserSensitivity == null) {
callback.run()
throw IllegalStateException(
- "All uids sensitivity liveData should not be null if initialized")
+ "All uids sensitivity liveData should not be null if initialized"
+ )
}
updateUserSensitiveForUidsInternal(uidUserSensitivity, user, callback)
}
@@ -62,28 +62,38 @@ private fun updateUserSensitiveForUidsInternal(
val pm = userContext.packageManager
for ((uid, uidState) in uidsUserSensitivity) {
- for (pkg in uidState.packages) {
- for (perm in pkg.requestedPermissions) {
- var flags = uidState.permStates[perm] ?: continue
+ for (pkg in uidState.packages) {
+ for (perm in pkg.requestedPermissions) {
+ var flags = uidState.permStates[perm] ?: continue
- try {
- val oldFlags = pm.getPermissionFlags(perm, pkg.packageName, user) and
+ try {
+ val oldFlags =
+ pm.getPermissionFlags(perm, pkg.packageName, user) and
FLAGS_ALWAYS_USER_SENSITIVE
- if (flags != oldFlags) {
- pm.updatePermissionFlags(perm, pkg.packageName,
- FLAGS_ALWAYS_USER_SENSITIVE, flags, user)
- }
- } catch (e: IllegalArgumentException) {
- if (e.message?.startsWith("Unknown permission: ") == false) {
- Log.e(LOG_TAG, "Unexpected exception while updating flags for " +
- "${pkg.packageName} (uid $uid) permission $perm", e)
- } else {
- // Unknown permission - ignore
- }
+ if (flags != oldFlags) {
+ pm.updatePermissionFlags(
+ perm,
+ pkg.packageName,
+ FLAGS_ALWAYS_USER_SENSITIVE,
+ flags,
+ user
+ )
+ }
+ } catch (e: IllegalArgumentException) {
+ if (e.message?.startsWith("Unknown permission: ") == false) {
+ Log.e(
+ LOG_TAG,
+ "Unexpected exception while updating flags for " +
+ "${pkg.packageName} (uid $uid) permission $perm",
+ e
+ )
+ } else {
+ // Unknown permission - ignore
}
}
}
}
+ }
callback?.run()
}
@@ -98,8 +108,11 @@ fun updateUserSensitiveForUid(uid: Int, callback: Runnable? = null) {
GlobalScope.launch(IPC) {
val uidSensitivityState = UserSensitivityLiveData[uid].getInitializedValue()
if (uidSensitivityState != null) {
- updateUserSensitiveForUidsInternal(uidSensitivityState,
- UserHandle.getUserHandleForUid(uid), callback)
+ updateUserSensitiveForUidsInternal(
+ uidSensitivityState,
+ UserHandle.getUserHandleForUid(uid),
+ callback
+ )
} else {
Log.e(LOG_TAG, "No packages associated with uid $uid, not updating flags")
callback?.run()
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/utils/v34/SafetyLabelUtils.kt b/PermissionController/src/com/android/permissioncontroller/permission/utils/v34/SafetyLabelUtils.kt
index 5dbe203f9..9fd8ab916 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/utils/v34/SafetyLabelUtils.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/utils/v34/SafetyLabelUtils.kt
@@ -32,8 +32,8 @@ object SafetyLabelUtils {
groupName: String
): Set<Int> {
val purposeSet = mutableSetOf<Int>()
- val categoriesForPermission = PermissionMapping
- .getDataCategoriesForPermissionGroup(groupName)
+ val categoriesForPermission =
+ PermissionMapping.getDataCategoriesForPermissionGroup(groupName)
categoriesForPermission.forEach categoryLoop@{ category ->
val dataCategory: DataCategory? = safetyLabel.dataLabel.dataShared[category]
if (dataCategory == null) {