Merge "Allow appops command to modify uid ops." into oc-dev

This commit is contained in:
Dianne Hackborn
2017-04-12 21:37:47 +00:00
committed by Android (Google) Code Review
2 changed files with 116 additions and 14 deletions

View File

@@ -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);

View File

@@ -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;