Apply fg/bg state in default grant policy
The fg/bg state is encoded in the app-op of the foreground permission.
I.e. depending whether the background permission is granted, the
foregrounds app-op state need to be different.
Test: Checked that default browser has both fg and bg location
Change-Id: I1428b65f95b23c921a3a5f69d84efe9124b51cd1
diff --git a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
index 030e148..32b2bf0 100644
--- a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
+++ b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
@@ -22,6 +22,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.ActivityManager;
+import android.app.AppOpsManager;
import android.app.DownloadManager;
import android.app.SearchManager;
import android.app.admin.DevicePolicyManager;
@@ -1027,6 +1028,23 @@
| PackageManager.FLAG_PERMISSION_SYSTEM_FIXED)) != 0;
}
+ /**
+ * Return the background permission for a permission.
+ *
+ * @param permission The name of the foreground permission
+ *
+ * @return The name of the background permission or {@code null} if the permission has no
+ * background permission
+ */
+ private @Nullable String getBackgroundPermission(@NonNull String permission) {
+ try {
+ return mContext.getPackageManager().getPermissionInfo(permission,
+ 0).backgroundPermission;
+ } catch (NameNotFoundException e) {
+ return null;
+ }
+ }
+
private void grantRuntimePermissions(PackageInfo pkg,
Set<String> permissionsWithoutSplits, boolean systemFixed, boolean ignoreSystemPackage,
int userId) {
@@ -1039,9 +1057,15 @@
return;
}
+ PackageManager pm = mContext.getPackageManager();
final ArraySet<String> permissions = new ArraySet<>(permissionsWithoutSplits);
ApplicationInfo applicationInfo = pkg.applicationInfo;
+ int newFlags = PackageManager.FLAG_PERMISSION_GRANTED_BY_DEFAULT;
+ if (systemFixed) {
+ newFlags |= PackageManager.FLAG_PERMISSION_SYSTEM_FIXED;
+ }
+
// Automatically attempt to grant split permissions to older APKs
final List<PermissionManager.SplitPermissionInfo> splitPermissions =
mContext.getSystemService(PermissionManager.class).getSplitPermissions();
@@ -1081,9 +1105,28 @@
}
}
- final int grantablePermissionCount = requestedPermissions.length;
- for (int i = 0; i < grantablePermissionCount; i++) {
+ final int numRequestedPermissions = requestedPermissions.length;
+
+ // Sort requested permissions so that all permissions that are a foreground permission (i.e.
+ // permisions that have background permission) are before their background permissions.
+ final String[] sortedRequestedPermissions = new String[numRequestedPermissions];
+ int numForeground = 0;
+ int numOther = 0;
+ for (int i = 0; i < numRequestedPermissions; i++) {
String permission = requestedPermissions[i];
+ if (getBackgroundPermission(permission) != null) {
+ sortedRequestedPermissions[numForeground] = permission;
+ numForeground++;
+ } else {
+ sortedRequestedPermissions[numRequestedPermissions - 1 - numOther] =
+ permission;
+ numOther++;
+ }
+ }
+
+ for (int requestedPermissionNum = 0; requestedPermissionNum < numRequestedPermissions;
+ requestedPermissionNum++) {
+ String permission = requestedPermissions[requestedPermissionNum];
// If there is a disabled system app it may request a permission the updated
// version ot the data partition doesn't, In this case skip the permission.
@@ -1111,20 +1154,58 @@
continue;
}
+ int uid = UserHandle.getUid(userId,
+ UserHandle.getAppId(pkg.applicationInfo.uid));
+ String op = AppOpsManager.permissionToOp(permission);
+
mContext.getPackageManager()
.grantRuntimePermission(pkg.packageName, permission, user);
+
+ mContext.getPackageManager().updatePermissionFlags(permission, pkg.packageName,
+ newFlags, newFlags, user);
+
+ List<String> fgPerms = mPermissionManager.getBackgroundPermissions()
+ .get(permission);
+ if (fgPerms != null) {
+ int numFgPerms = fgPerms.size();
+ for (int fgPermNum = 0; fgPermNum < numFgPerms; fgPermNum++) {
+ String fgPerm = fgPerms.get(fgPermNum);
+
+ if (pm.checkPermission(fgPerm, pkg.packageName)
+ == PackageManager.PERMISSION_GRANTED) {
+ // Upgrade the app-op state of the fg permission to allow bg access
+ mContext.getSystemService(AppOpsManager.class).setMode(
+ AppOpsManager.permissionToOp(fgPerm), uid,
+ pkg.packageName, AppOpsManager.MODE_ALLOWED);
+
+ break;
+ }
+ }
+ }
+
+ String bgPerm = getBackgroundPermission(permission);
+ if (bgPerm == null) {
+ if (op != null) {
+ mContext.getSystemService(AppOpsManager.class).setMode(op, uid,
+ pkg.packageName, AppOpsManager.MODE_ALLOWED);
+ }
+ } else {
+ int mode;
+ if (pm.checkPermission(bgPerm, pkg.packageName)
+ == PackageManager.PERMISSION_GRANTED) {
+ mode = AppOpsManager.MODE_ALLOWED;
+ } else {
+ mode = AppOpsManager.MODE_FOREGROUND;
+ }
+
+ mContext.getSystemService(AppOpsManager.class).setMode(op, uid,
+ pkg.packageName, mode);
+ }
+
if (DEBUG) {
Log.i(TAG, "Granted " + (systemFixed ? "fixed " : "not fixed ")
+ permission + " to default handler " + pkg);
}
-
- int newFlags = PackageManager.FLAG_PERMISSION_GRANTED_BY_DEFAULT;
- if (systemFixed) {
- newFlags |= PackageManager.FLAG_PERMISSION_SYSTEM_FIXED;
- }
-
- mContext.getPackageManager().updatePermissionFlags(permission, pkg.packageName,
- newFlags, newFlags, user);
}
// If a component gets a permission for being the default handler A