Merge "Respect role granted app op permissions when resetting all op modes." into udc-dev
This commit is contained in:
@@ -2217,8 +2217,7 @@ public class AppOpsManager {
|
||||
/** Whether noting for an appop should be collected */
|
||||
private static final @ShouldCollectNoteOp byte[] sAppOpsToNote = new byte[_NUM_OP];
|
||||
|
||||
private static final int[] RUNTIME_AND_APPOP_PERMISSIONS_OPS = {
|
||||
// RUNTIME PERMISSIONS
|
||||
private static final int[] RUNTIME_PERMISSION_OPS = {
|
||||
// Contacts
|
||||
OP_READ_CONTACTS,
|
||||
OP_WRITE_CONTACTS,
|
||||
@@ -2275,8 +2274,13 @@ public class AppOpsManager {
|
||||
OP_NEARBY_WIFI_DEVICES,
|
||||
// Notifications
|
||||
OP_POST_NOTIFICATION,
|
||||
};
|
||||
|
||||
// APPOP PERMISSIONS
|
||||
/**
|
||||
* Ops for app op permissions that are setting the per-package mode for certain reasons. Most
|
||||
* app op permissions should set the per-UID mode instead.
|
||||
*/
|
||||
private static final int[] APP_OP_PERMISSION_PACKAGE_OPS = {
|
||||
OP_ACCESS_NOTIFICATIONS,
|
||||
OP_SYSTEM_ALERT_WINDOW,
|
||||
OP_WRITE_SETTINGS,
|
||||
@@ -2285,9 +2289,16 @@ public class AppOpsManager {
|
||||
OP_SMS_FINANCIAL_TRANSACTIONS,
|
||||
OP_MANAGE_IPSEC_TUNNELS,
|
||||
OP_INSTANT_APP_START_FOREGROUND,
|
||||
OP_LOADER_USAGE_STATS
|
||||
};
|
||||
|
||||
/**
|
||||
* Ops for app op permissions that are setting the per-UID mode for certain reasons. This should
|
||||
* be preferred over the per-package mode for new app op permissions.
|
||||
*/
|
||||
private static final int[] APP_OP_PERMISSION_UID_OPS = {
|
||||
OP_MANAGE_EXTERNAL_STORAGE,
|
||||
OP_INTERACT_ACROSS_PROFILES,
|
||||
OP_LOADER_USAGE_STATS,
|
||||
OP_MANAGE_ONGOING_CALLS,
|
||||
OP_USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER,
|
||||
OP_SCHEDULE_EXACT_ALARM,
|
||||
@@ -2777,7 +2788,17 @@ public class AppOpsManager {
|
||||
sOpStrToOp.put(sAppOpInfos[i].name, i);
|
||||
}
|
||||
}
|
||||
for (int op : RUNTIME_AND_APPOP_PERMISSIONS_OPS) {
|
||||
for (int op : RUNTIME_PERMISSION_OPS) {
|
||||
if (sAppOpInfos[op].permission != null) {
|
||||
sPermToOp.put(sAppOpInfos[op].permission, op);
|
||||
}
|
||||
}
|
||||
for (int op : APP_OP_PERMISSION_PACKAGE_OPS) {
|
||||
if (sAppOpInfos[op].permission != null) {
|
||||
sPermToOp.put(sAppOpInfos[op].permission, op);
|
||||
}
|
||||
}
|
||||
for (int op : APP_OP_PERMISSION_UID_OPS) {
|
||||
if (sAppOpInfos[op].permission != null) {
|
||||
sPermToOp.put(sAppOpInfos[op].permission, op);
|
||||
}
|
||||
@@ -2946,6 +2967,22 @@ public class AppOpsManager {
|
||||
return !sAppOpInfos[op].disableReset;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve whether the op is a per-package op for an app op permission.
|
||||
* @hide
|
||||
*/
|
||||
public static boolean opIsPackageAppOpPermission(int op) {
|
||||
return ArrayUtils.contains(APP_OP_PERMISSION_PACKAGE_OPS, op);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve whether the op is a per-package op for an app op permission.
|
||||
* @hide
|
||||
*/
|
||||
public static boolean opIsUidAppOpPermission(int op) {
|
||||
return ArrayUtils.contains(APP_OP_PERMISSION_UID_OPS, op);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a listenerId suitable for use with {@link #noteOp(int, int, String, String, String)}.
|
||||
*
|
||||
|
||||
@@ -2096,7 +2096,9 @@ public class AppOpsService extends IAppOpsService.Stub {
|
||||
final int code = opModes.keyAt(j);
|
||||
if (AppOpsManager.opAllowsReset(code)) {
|
||||
int previousMode = opModes.valueAt(j);
|
||||
uidState.setUidMode(code, AppOpsManager.opToDefaultMode(code));
|
||||
int newMode = isUidOpGrantedByRole(uidState.uid, code) ? MODE_ALLOWED :
|
||||
AppOpsManager.opToDefaultMode(code);
|
||||
uidState.setUidMode(code, newMode);
|
||||
for (String packageName : getPackagesForUid(uidState.uid)) {
|
||||
callbacks = addCallbacks(callbacks, code, uidState.uid, packageName,
|
||||
previousMode,
|
||||
@@ -2139,10 +2141,15 @@ public class AppOpsService extends IAppOpsService.Stub {
|
||||
deferResetOpToDpm(curOp.op, reqPackageName, reqUserId);
|
||||
continue;
|
||||
}
|
||||
if (AppOpsManager.opAllowsReset(curOp.op)
|
||||
&& curOp.getMode() != AppOpsManager.opToDefaultMode(curOp.op)) {
|
||||
if (AppOpsManager.opAllowsReset(curOp.op)) {
|
||||
int previousMode = curOp.getMode();
|
||||
curOp.setMode(AppOpsManager.opToDefaultMode(curOp.op));
|
||||
int newMode = isPackageOpGrantedByRole(packageName, uidState.uid,
|
||||
curOp.op) ? MODE_ALLOWED : AppOpsManager.opToDefaultMode(
|
||||
curOp.op);
|
||||
if (previousMode == newMode) {
|
||||
continue;
|
||||
}
|
||||
curOp.setMode(newMode);
|
||||
changed = true;
|
||||
uidChanged = true;
|
||||
final int uid = curOp.uidState.uid;
|
||||
@@ -2198,6 +2205,41 @@ public class AppOpsService extends IAppOpsService.Stub {
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isUidOpGrantedByRole(int uid, int code) {
|
||||
if (!AppOpsManager.opIsUidAppOpPermission(code)) {
|
||||
return false;
|
||||
}
|
||||
PackageManager packageManager = mContext.getPackageManager();
|
||||
long token = Binder.clearCallingIdentity();
|
||||
try {
|
||||
// Permissions are managed by UIDs, but unfortunately a package name is required in API.
|
||||
String packageName = ArrayUtils.firstOrNull(packageManager.getPackagesForUid(uid));
|
||||
if (packageName == null) {
|
||||
return false;
|
||||
}
|
||||
int permissionFlags = packageManager.getPermissionFlags(AppOpsManager.opToPermission(
|
||||
code), packageName, UserHandle.getUserHandleForUid(uid));
|
||||
return (permissionFlags & PackageManager.FLAG_PERMISSION_GRANTED_BY_ROLE) != 0;
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(token);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isPackageOpGrantedByRole(@NonNull String packageName, int uid, int code) {
|
||||
if (!AppOpsManager.opIsPackageAppOpPermission(code)) {
|
||||
return false;
|
||||
}
|
||||
PackageManager packageManager = mContext.getPackageManager();
|
||||
long token = Binder.clearCallingIdentity();
|
||||
try {
|
||||
int permissionFlags = packageManager.getPermissionFlags(AppOpsManager.opToPermission(
|
||||
code), packageName, UserHandle.getUserHandleForUid(uid));
|
||||
return (permissionFlags & PackageManager.FLAG_PERMISSION_GRANTED_BY_ROLE) != 0;
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(token);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean shouldDeferResetOpToDpm(int op) {
|
||||
// TODO(b/174582385): avoid special-casing app-op resets by migrating app-op permission
|
||||
// pre-grants to a role-based mechanism or another general-purpose mechanism.
|
||||
|
||||
Reference in New Issue
Block a user