diff options
| author | 2017-04-11 13:32:47 -0700 | |
|---|---|---|
| committer | 2017-04-11 13:34:14 -0700 | |
| commit | c7214a3ade62db082c89b933a51a0ddd9f57b49d (patch) | |
| tree | edaff6827506f98cf52ea4b6d00f06c4871bcfe2 | |
| parent | 4a306894145340a4fe08b70b569eaa31641b38e6 (diff) | |
Allow appops command to modify uid ops.
The get and set commands can now operate on per-uid
app ops as well as per-package ones.
The to parse a uid string in to a more generic place, but
for now we'll leave it here.
Test: none
Change-Id: I7efbb3966ddb79639dafabbe4bf1df659bed6240
| -rw-r--r-- | core/java/com/android/internal/app/IAppOpsService.aidl | 1 | ||||
| -rw-r--r-- | services/core/java/com/android/server/AppOpsService.java | 129 |
2 files changed, 116 insertions, 14 deletions
diff --git a/core/java/com/android/internal/app/IAppOpsService.aidl b/core/java/com/android/internal/app/IAppOpsService.aidl index 3a31b370a417..35d4ba81bd69 100644 --- a/core/java/com/android/internal/app/IAppOpsService.aidl +++ b/core/java/com/android/internal/app/IAppOpsService.aidl @@ -38,6 +38,7 @@ interface IAppOpsService { int checkPackage(int uid, String packageName); List<AppOpsManager.PackageOps> getPackagesForOps(in int[] ops); List<AppOpsManager.PackageOps> getOpsForPackage(int uid, String packageName, in int[] ops); + List<AppOpsManager.PackageOps> getUidOps(int uid, in int[] ops); void setUidMode(int code, int uid, int mode); void setMode(int code, int uid, String packageName, int mode); void resetAllModes(int reqUserId, String reqPackageName); diff --git a/services/core/java/com/android/server/AppOpsService.java b/services/core/java/com/android/server/AppOpsService.java index dcf6fd718722..1a5ec61a1510 100644 --- a/services/core/java/com/android/server/AppOpsService.java +++ b/services/core/java/com/android/server/AppOpsService.java @@ -416,6 +416,29 @@ public class AppOpsService extends IAppOpsService.Stub { return resOps; } + private ArrayList<AppOpsManager.OpEntry> collectOps(SparseIntArray uidOps, int[] ops) { + ArrayList<AppOpsManager.OpEntry> resOps = null; + if (ops == null) { + resOps = new ArrayList<>(); + for (int j=0; j<uidOps.size(); j++) { + resOps.add(new AppOpsManager.OpEntry(uidOps.keyAt(j), uidOps.valueAt(j), + 0, 0, 0, -1, null)); + } + } else { + for (int j=0; j<ops.length; j++) { + int index = uidOps.indexOfKey(ops[j]); + if (index >= 0) { + if (resOps == null) { + resOps = new ArrayList<>(); + } + resOps.add(new AppOpsManager.OpEntry(uidOps.keyAt(index), uidOps.valueAt(index), + 0, 0, 0, -1, null)); + } + } + } + return resOps; + } + @Override public List<AppOpsManager.PackageOps> getPackagesForOps(int[] ops) { mContext.enforcePermission(android.Manifest.permission.GET_APP_OPS_STATS, @@ -473,6 +496,27 @@ public class AppOpsService extends IAppOpsService.Stub { } } + @Override + public List<AppOpsManager.PackageOps> getUidOps(int uid, int[] ops) { + mContext.enforcePermission(android.Manifest.permission.GET_APP_OPS_STATS, + Binder.getCallingPid(), Binder.getCallingUid(), null); + synchronized (this) { + UidState uidState = getUidStateLocked(uid, false); + if (uidState == null) { + return null; + } + ArrayList<AppOpsManager.OpEntry> resOps = collectOps(uidState.opModes, ops); + if (resOps == null) { + return null; + } + ArrayList<AppOpsManager.PackageOps> res = new ArrayList<AppOpsManager.PackageOps>(); + AppOpsManager.PackageOps resPackage = new AppOpsManager.PackageOps( + null, uidState.uid, resOps); + res.add(resPackage); + return res; + } + } + private void pruneOp(Op op, int uid, String packageName) { if (op.time == 0 && op.rejectTime == 0) { Ops ops = getOpsRawLocked(uid, packageName, false); @@ -1669,6 +1713,7 @@ public class AppOpsService extends IAppOpsService.Stub { int op; int mode; int packageUid; + int nonpackageUid; Shell(IAppOpsService iface, AppOpsService internal) { mInterface = iface; @@ -1790,15 +1835,59 @@ public class AppOpsService extends IAppOpsService.Stub { if (userId == UserHandle.USER_CURRENT) { userId = ActivityManager.getCurrentUser(); } - if ("root".equals(packageName)) { - packageUid = 0; - } else { - packageUid = AppGlobals.getPackageManager().getPackageUid(packageName, - PackageManager.MATCH_UNINSTALLED_PACKAGES, userId); + nonpackageUid = -1; + try { + nonpackageUid = Integer.parseInt(packageName); + } catch (NumberFormatException e) { } - if (packageUid < 0) { - err.println("Error: No UID for " + packageName + " in user " + userId); - return -1; + if (nonpackageUid == -1 && packageName.length() > 1 && packageName.charAt(0) == 'u' + && packageName.indexOf('.') < 0) { + int i = 1; + while (i < packageName.length() && packageName.charAt(i) >= '0' + && packageName.charAt(i) <= '9') { + i++; + } + if (i > 1 && i < packageName.length()) { + String userStr = packageName.substring(1, i); + try { + int user = Integer.parseInt(userStr); + char type = packageName.charAt(i); + i++; + int startTypeVal = i; + while (i < packageName.length() && packageName.charAt(i) >= '0' + && packageName.charAt(i) <= '9') { + i++; + } + if (i > startTypeVal) { + String typeValStr = packageName.substring(startTypeVal, i); + try { + int typeVal = Integer.parseInt(typeValStr); + if (type == 'a') { + nonpackageUid = UserHandle.getUid(user, + typeVal + Process.FIRST_APPLICATION_UID); + } else if (type == 's') { + nonpackageUid = UserHandle.getUid(user, typeVal); + } + } catch (NumberFormatException e) { + } + } + } catch (NumberFormatException e) { + } + } + } + if (nonpackageUid != -1) { + packageName = null; + } else { + if ("root".equals(packageName)) { + packageUid = 0; + } else { + packageUid = AppGlobals.getPackageManager().getPackageUid(packageName, + PackageManager.MATCH_UNINSTALLED_PACKAGES, userId); + } + if (packageUid < 0) { + err.println("Error: No UID for " + packageName + " in user " + userId); + return -1; + } } return 0; } @@ -1814,9 +1903,9 @@ public class AppOpsService extends IAppOpsService.Stub { pw.println("AppOps service (appops) commands:"); pw.println(" help"); pw.println(" Print this help text."); - pw.println(" set [--user <USER_ID>] <PACKAGE> <OP> <MODE>"); + pw.println(" set [--user <USER_ID>] <PACKAGE | UID> <OP> <MODE>"); pw.println(" Set the mode for a particular application and operation."); - pw.println(" get [--user <USER_ID>] <PACKAGE> [<OP>]"); + pw.println(" get [--user <USER_ID>] <PACKAGE | UID> [<OP>]"); pw.println(" Return the mode for a particular application and optional operation."); pw.println(" query-op [--user <USER_ID>] <OP> [<MODE>]"); pw.println(" Print all packages that currently have the given op in the given mode."); @@ -1858,7 +1947,12 @@ public class AppOpsService extends IAppOpsService.Stub { return -1; } - shell.mInterface.setMode(shell.op, shell.packageUid, shell.packageName, mode); + if (shell.packageName != null) { + shell.mInterface.setMode(shell.op, shell.packageUid, shell.packageName, + mode); + } else { + shell.mInterface.setUidMode(shell.op, shell.nonpackageUid, mode); + } return 0; } case "get": { @@ -1867,9 +1961,16 @@ public class AppOpsService extends IAppOpsService.Stub { return res; } - List<AppOpsManager.PackageOps> ops = shell.mInterface.getOpsForPackage( - shell.packageUid, shell.packageName, - shell.op != AppOpsManager.OP_NONE ? new int[] {shell.op} : null); + List<AppOpsManager.PackageOps> ops; + if (shell.packageName != null) { + ops = shell.mInterface.getOpsForPackage( + shell.packageUid, shell.packageName, + shell.op != AppOpsManager.OP_NONE ? new int[]{shell.op} : null); + } else { + ops = shell.mInterface.getUidOps( + shell.nonpackageUid, + shell.op != AppOpsManager.OP_NONE ? new int[]{shell.op} : null); + } if (ops == null || ops.size() <= 0) { pw.println("No operations."); return 0; |