Merge "Revert "Access app op modes in UID state indirectly.""

This commit is contained in:
TreeHugger Robot
2019-09-30 22:07:12 +00:00
committed by Android (Google) Code Review
2 changed files with 128 additions and 150 deletions

View File

@@ -65,6 +65,7 @@ import android.content.pm.PermissionInfo;
import android.content.pm.UserInfo;
import android.database.ContentObserver;
import android.hardware.camera2.CameraDevice.CAMERA_AUDIO_RESTRICTION;
import android.media.AudioAttributes;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Binder;
@@ -360,7 +361,7 @@ public class AppOpsService extends IAppOpsService.Stub {
public int startNesting;
public ArrayMap<String, Ops> pkgOps;
private SparseIntArray opModes;
public SparseIntArray opModes;
// true indicates there is an interested observer, false there isn't but it has such an op
public SparseBooleanArray foregroundOps;
@@ -382,64 +383,6 @@ public class AppOpsService extends IAppOpsService.Stub {
&& (pendingState == UID_STATE_CACHED));
}
public int getOpModeCount() {
return opModes != null ? opModes.size() : 0;
}
public int getOpCodeAt(int index) {
return opModes.keyAt(index);
}
public boolean hasOpMode(int code) {
return opModes != null && opModes.indexOfKey(code) >= 0;
}
public int getOpMode(int code) {
return opModes.get(code);
}
public boolean putOpMode(int code, int mode) {
if (mode == AppOpsManager.opToDefaultMode(code)) {
return removeOpMode(code);
}
if (opModes == null) {
opModes = new SparseIntArray();
}
int index = opModes.indexOfKey(code);
if (index < 0) {
opModes.put(code, mode);
return true;
}
if (opModes.valueAt(index) == mode) {
return false;
}
opModes.setValueAt(index, mode);
return true;
}
public boolean removeOpMode(int code) {
if (opModes == null) {
return false;
}
int index = opModes.indexOfKey(code);
if (index < 0) {
return false;
}
opModes.removeAt(index);
if (opModes.size() == 0) {
opModes = null;
}
return true;
}
@Nullable
public SparseIntArray cloneOpModes() {
if (opModes == null) {
return null;
}
return opModes.clone();
}
int evalMode(int op, int mode) {
if (mode == AppOpsManager.MODE_FOREGROUND) {
return state <= AppOpsManager.resolveFirstUnrestrictedUidState(op)
@@ -467,13 +410,14 @@ public class AppOpsService extends IAppOpsService.Stub {
public void evalForegroundOps(SparseArray<ArraySet<ModeCallback>> watchers) {
SparseBooleanArray which = null;
hasForegroundWatchers = false;
for (int i = getOpModeCount() - 1; i >= 0; i--) {
int code = getOpCodeAt(i);
if (getOpMode(code) == AppOpsManager.MODE_FOREGROUND) {
if (which == null) {
which = new SparseBooleanArray();
if (opModes != null) {
for (int i = opModes.size() - 1; i >= 0; i--) {
if (opModes.valueAt(i) == AppOpsManager.MODE_FOREGROUND) {
if (which == null) {
which = new SparseBooleanArray();
}
evalForegroundWatchers(opModes.keyAt(i), watchers, which);
}
evalForegroundWatchers(code, watchers, which);
}
}
if (pkgOps != null) {
@@ -1121,28 +1065,24 @@ public class AppOpsService extends IAppOpsService.Stub {
return resOps;
}
@Nullable
private ArrayList<AppOpsManager.OpEntry> collectOps(@NonNull UidState uidState,
@Nullable int[] ops) {
int opModeCount = uidState.getOpModeCount();
if (opModeCount == 0) {
private ArrayList<AppOpsManager.OpEntry> collectOps(SparseIntArray uidOps, int[] ops) {
if (uidOps == null) {
return null;
}
ArrayList<AppOpsManager.OpEntry> resOps = null;
if (ops == null) {
resOps = new ArrayList<>();
for (int i = 0; i < opModeCount; i++) {
int code = uidState.getOpCodeAt(i);
resOps.add(new OpEntry(code, uidState.getOpMode(code)));
for (int j=0; j<uidOps.size(); j++) {
resOps.add(new OpEntry(uidOps.keyAt(j), uidOps.valueAt(j)));
}
} else {
for (int i = 0; i < ops.length; i++) {
int code = ops[i];
if (uidState.hasOpMode(code)) {
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 OpEntry(code, uidState.getOpMode(code)));
resOps.add(new OpEntry(uidOps.keyAt(j), uidOps.valueAt(j)));
}
}
}
@@ -1288,11 +1228,11 @@ public class AppOpsService extends IAppOpsService.Stub {
if (uidState == null) {
return null;
}
ArrayList<AppOpsManager.OpEntry> resOps = collectOps(uidState, ops);
ArrayList<AppOpsManager.OpEntry> resOps = collectOps(uidState.opModes, ops);
if (resOps == null) {
return null;
}
ArrayList<AppOpsManager.PackageOps> res = new ArrayList<>();
ArrayList<AppOpsManager.PackageOps> res = new ArrayList<AppOpsManager.PackageOps>();
AppOpsManager.PackageOps resPackage = new AppOpsManager.PackageOps(
null, uidState.uid, resOps);
res.add(resPackage);
@@ -1360,14 +1300,29 @@ public class AppOpsService extends IAppOpsService.Stub {
return;
}
uidState = new UidState(uid);
uidState.putOpMode(code, mode);
uidState.opModes = new SparseIntArray();
uidState.opModes.put(code, mode);
mUidStates.put(uid, uidState);
scheduleWriteLocked();
} else {
boolean changed = uidState.putOpMode(code, mode);
if (changed) {
} else if (uidState.opModes == null) {
if (mode != defaultMode) {
uidState.opModes = new SparseIntArray();
uidState.opModes.put(code, mode);
scheduleWriteLocked();
}
} else {
if (uidState.opModes.indexOfKey(code) >= 0 && uidState.opModes.get(code) == mode) {
return;
}
if (mode == defaultMode) {
uidState.opModes.delete(code);
if (uidState.opModes.size() <= 0) {
uidState.opModes = null;
}
} else {
uidState.opModes.put(code, mode);
}
scheduleWriteLocked();
}
uidState.evalForegroundOps(mOpModeWatchers);
}
@@ -1606,13 +1561,16 @@ public class AppOpsService extends IAppOpsService.Stub {
for (int i = mUidStates.size() - 1; i >= 0; i--) {
UidState uidState = mUidStates.valueAt(i);
if (uidState.uid == reqUid || reqUid == -1) {
for (int opModeIndex = uidState.getOpModeCount() - 1; opModeIndex >= 0;
opModeIndex--) {
final int code = uidState.getOpCodeAt(opModeIndex);
SparseIntArray opModes = uidState.opModes;
if (opModes != null && (uidState.uid == reqUid || reqUid == -1)) {
final int uidOpCount = opModes.size();
for (int j = uidOpCount - 1; j >= 0; j--) {
final int code = opModes.keyAt(j);
if (AppOpsManager.opAllowsReset(code)) {
uidState.removeOpMode(code);
opModes.removeAt(j);
if (opModes.size() <= 0) {
uidState.opModes = null;
}
for (String packageName : getPackagesForUid(uidState.uid)) {
callbacks = addCallbacks(callbacks, code, uidState.uid, packageName,
mOpModeWatchers.get(code));
@@ -1862,8 +1820,9 @@ public class AppOpsService extends IAppOpsService.Stub {
}
code = AppOpsManager.opToSwitch(code);
UidState uidState = getUidStateLocked(uid, false);
if (uidState != null && uidState.hasOpMode(code)) {
final int rawMode = uidState.getOpMode(code);
if (uidState != null && uidState.opModes != null
&& uidState.opModes.indexOfKey(code) >= 0) {
final int rawMode = uidState.opModes.get(code);
return raw ? rawMode : uidState.evalMode(code, rawMode);
}
Op op = getOpLocked(code, uid, packageName, false, false);
@@ -2032,8 +1991,8 @@ public class AppOpsService extends IAppOpsService.Stub {
final int switchCode = AppOpsManager.opToSwitch(code);
// If there is a non-default per UID policy (we set UID op mode only if
// non-default) it takes over, otherwise use the per package policy.
if (uidState.hasOpMode(switchCode)) {
final int uidMode = uidState.evalMode(code, uidState.getOpMode(switchCode));
if (uidState.opModes != null && uidState.opModes.indexOfKey(switchCode) >= 0) {
final int uidMode = uidState.evalMode(code, uidState.opModes.get(switchCode));
if (uidMode != AppOpsManager.MODE_ALLOWED) {
if (DEBUG) Slog.d(TAG, "noteOperation: uid reject #" + uidMode + " for code "
+ switchCode + " (" + code + ") uid " + uid + " package "
@@ -2334,8 +2293,8 @@ public class AppOpsService extends IAppOpsService.Stub {
// If there is a non-default per UID policy (we set UID op mode only if
// non-default) it takes over, otherwise use the per package policy.
final int opCode = op.op;
if (uidState.hasOpMode(switchCode)) {
final int uidMode = uidState.evalMode(code, uidState.getOpMode(switchCode));
if (uidState.opModes != null && uidState.opModes.indexOfKey(switchCode) >= 0) {
final int uidMode = uidState.evalMode(code, uidState.opModes.get(switchCode));
if (uidMode != AppOpsManager.MODE_ALLOWED
&& (!startIfModeDefault || uidMode != AppOpsManager.MODE_DEFAULT)) {
if (DEBUG) Slog.d(TAG, "noteOperation: uid reject #" + uidMode + " for code "
@@ -2654,8 +2613,9 @@ public class AppOpsService extends IAppOpsService.Stub {
|| !callback.isWatchingUid(uidState.uid)) {
continue;
}
boolean doAllPackages = uidState.hasOpMode(code)
&& uidState.getOpMode(code) == AppOpsManager.MODE_FOREGROUND;
boolean doAllPackages = uidState.opModes != null
&& uidState.opModes.indexOfKey(code) >= 0
&& uidState.opModes.get(code) == AppOpsManager.MODE_FOREGROUND;
if (uidState.pkgOps != null) {
for (int pkgi = uidState.pkgOps.size() - 1; pkgi >= 0; pkgi--) {
final Op op = uidState.pkgOps.valueAt(pkgi).get(code);
@@ -2978,9 +2938,12 @@ public class AppOpsService extends IAppOpsService.Stub {
if (uidState == null) {
continue;
}
if (uidState.hasOpMode(AppOpsManager.OP_RUN_IN_BACKGROUND)) {
uidState.putOpMode(AppOpsManager.OP_RUN_ANY_IN_BACKGROUND, uidState.getOpMode(
AppOpsManager.OP_RUN_IN_BACKGROUND));
if (uidState.opModes != null) {
final int idx = uidState.opModes.indexOfKey(AppOpsManager.OP_RUN_IN_BACKGROUND);
if (idx >= 0) {
uidState.opModes.put(AppOpsManager.OP_RUN_ANY_IN_BACKGROUND,
uidState.opModes.valueAt(idx));
}
}
if (uidState.pkgOps == null) {
continue;
@@ -3036,7 +2999,10 @@ public class AppOpsService extends IAppOpsService.Stub {
final int code = Integer.parseInt(parser.getAttributeValue(null, "n"));
final int mode = Integer.parseInt(parser.getAttributeValue(null, "m"));
UidState uidState = getUidStateLocked(uid, true);
uidState.putOpMode(code, mode);
if (uidState.opModes == null) {
uidState.opModes = new SparseIntArray();
}
uidState.opModes.put(code, mode);
} else {
Slog.w(TAG, "Unknown element under <uid-ops>: "
+ parser.getName());
@@ -3188,38 +3154,47 @@ public class AppOpsService extends IAppOpsService.Stub {
out.startTag(null, "app-ops");
out.attribute(null, "v", String.valueOf(CURRENT_VERSION));
final SparseArray<SparseIntArray> uidOpModes = new SparseArray<>();
SparseArray<SparseIntArray> uidStatesClone;
synchronized (this) {
final int uidStatesSize = mUidStates.size();
for (int i = 0; i < uidStatesSize; i++) {
final SparseIntArray opModes = mUidStates.valueAt(i).cloneOpModes();
if (opModes != null) {
final int uid = mUidStates.keyAt(i);
uidOpModes.put(uid, opModes);
uidStatesClone = new SparseArray<>(mUidStates.size());
final int uidStateCount = mUidStates.size();
for (int uidStateNum = 0; uidStateNum < uidStateCount; uidStateNum++) {
UidState uidState = mUidStates.valueAt(uidStateNum);
int uid = mUidStates.keyAt(uidStateNum);
SparseIntArray opModes = uidState.opModes;
if (opModes != null && opModes.size() > 0) {
uidStatesClone.put(uid, new SparseIntArray(opModes.size()));
final int opCount = opModes.size();
for (int opCountNum = 0; opCountNum < opCount; opCountNum++) {
uidStatesClone.get(uid).put(
opModes.keyAt(opCountNum),
opModes.valueAt(opCountNum));
}
}
}
}
final int uidOpModesSize = uidOpModes.size();
for (int uidOpModesIndex = 0; uidOpModesIndex < uidOpModesSize; uidOpModesIndex++) {
final int uid = uidOpModes.keyAt(uidOpModesIndex);
final SparseIntArray opModes = uidOpModes.valueAt(uidOpModesIndex);
out.startTag(null, "uid");
out.attribute(null, "n", Integer.toString(uid));
final int opModesSize = opModes.size();
for (int opModesIndex = 0; opModesIndex < opModesSize; opModesIndex++) {
final int code = opModes.keyAt(opModesIndex);
final int mode = opModes.valueAt(opModesIndex);
out.startTag(null, "op");
out.attribute(null, "n", Integer.toString(code));
out.attribute(null, "m", Integer.toString(mode));
out.endTag(null, "op");
final int uidStateCount = uidStatesClone.size();
for (int uidStateNum = 0; uidStateNum < uidStateCount; uidStateNum++) {
SparseIntArray opModes = uidStatesClone.valueAt(uidStateNum);
if (opModes != null && opModes.size() > 0) {
out.startTag(null, "uid");
out.attribute(null, "n",
Integer.toString(uidStatesClone.keyAt(uidStateNum)));
final int opCount = opModes.size();
for (int opCountNum = 0; opCountNum < opCount; opCountNum++) {
final int op = opModes.keyAt(opCountNum);
final int mode = opModes.valueAt(opCountNum);
out.startTag(null, "op");
out.attribute(null, "n", Integer.toString(op));
out.attribute(null, "m", Integer.toString(mode));
out.endTag(null, "op");
}
out.endTag(null, "uid");
}
out.endTag(null, "uid");
}
if (allOps != null) {
@@ -4164,22 +4139,21 @@ public class AppOpsService extends IAppOpsService.Stub {
}
for (int i=0; i<mUidStates.size(); i++) {
UidState uidState = mUidStates.valueAt(i);
final SparseIntArray opModes = uidState.opModes;
final ArrayMap<String, Ops> pkgOps = uidState.pkgOps;
if (dumpWatchers || dumpHistory) {
continue;
}
if (dumpOp >= 0 || dumpPackage != null || dumpMode >= 0) {
boolean hasOp = dumpOp < 0 || uidState.hasOpMode(dumpOp);
boolean hasOp = dumpOp < 0 || (uidState.opModes != null
&& uidState.opModes.indexOfKey(dumpOp) >= 0);
boolean hasPackage = dumpPackage == null;
boolean hasMode = dumpMode < 0;
if (!hasMode) {
int opModeCount = uidState.getOpModeCount();
for (int opModeIndex = 0; opModeIndex < opModeCount; opModeIndex++) {
int code = uidState.getOpCodeAt(opModeIndex);
if (uidState.getOpMode(code) == dumpMode) {
if (!hasMode && opModes != null) {
for (int opi = 0; !hasMode && opi < opModes.size(); opi++) {
if (opModes.valueAt(opi) == dumpMode) {
hasMode = true;
break;
}
}
}
@@ -4246,18 +4220,20 @@ public class AppOpsService extends IAppOpsService.Stub {
}
needSep = true;
final int opModeCount = uidState.getOpModeCount();
for (int opModeIndex = 0; opModeIndex < opModeCount; opModeIndex++) {
final int code = uidState.getOpCodeAt(opModeIndex);
final int mode = uidState.getOpMode(code);
if (dumpOp >= 0 && dumpOp != code) {
continue;
if (opModes != null) {
final int opModeCount = opModes.size();
for (int j = 0; j < opModeCount; j++) {
final int code = opModes.keyAt(j);
final int mode = opModes.valueAt(j);
if (dumpOp >= 0 && dumpOp != code) {
continue;
}
if (dumpMode >= 0 && dumpMode != mode) {
continue;
}
pw.print(" "); pw.print(AppOpsManager.opToName(code));
pw.print(": mode="); pw.println(AppOpsManager.modeToName(mode));
}
if (dumpMode >= 0 && dumpMode != mode) {
continue;
}
pw.print(" "); pw.print(AppOpsManager.opToName(code));
pw.print(": mode="); pw.println(AppOpsManager.modeToName(mode));
}
if (pkgOps == null) {

View File

@@ -89,11 +89,13 @@ public class AppOpsUpgradeTest {
final int defaultModeOp2 = AppOpsManager.opToDefaultMode(op2);
for(int i = 0; i < uidStates.size(); i++) {
final AppOpsService.UidState uidState = uidStates.valueAt(i);
final int uidMode1 = uidState.hasOpMode(op1) ? uidState.getOpMode(op1) : defaultModeOp1;
final int uidMode2 = uidState.hasOpMode(op2) ? uidState.getOpMode(op2) : defaultModeOp2;
assertEquals(uidMode1, uidMode2);
if (uidMode1 != defaultModeOp1) {
numberOfNonDefaultOps++;
if (uidState.opModes != null) {
final int uidMode1 = uidState.opModes.get(op1, defaultModeOp1);
final int uidMode2 = uidState.opModes.get(op2, defaultModeOp2);
assertEquals(uidMode1, uidMode2);
if (uidMode1 != defaultModeOp1) {
numberOfNonDefaultOps++;
}
}
if (uidState.pkgOps == null) {
continue;