Merge "Revert sync app op chain changes" into sc-dev

This commit is contained in:
Nate Myren
2021-08-03 15:16:35 +00:00
committed by Android (Google) Code Review
4 changed files with 111 additions and 102 deletions

View File

@@ -2849,14 +2849,14 @@ public class AppOpsManager {
private static final ThreadLocal<Integer> sBinderThreadCallingUid = new ThreadLocal<>(); private static final ThreadLocal<Integer> sBinderThreadCallingUid = new ThreadLocal<>();
/** /**
* If a thread is currently executing a two-way binder transaction, this stores the * If a thread is currently executing a two-way binder transaction, this stores the op-codes of
* ops that were noted blaming any app (the caller, the caller of the caller, etc). * the app-ops that were noted during this transaction.
* *
* @see #getNotedOpCollectionMode * @see #getNotedOpCollectionMode
* @see #collectNotedOpSync * @see #collectNotedOpSync
*/ */
private static final ThreadLocal<ArrayMap<String, ArrayMap<String, long[]>>> private static final ThreadLocal<ArrayMap<String, long[]>> sAppOpsNotedInThisBinderTransaction =
sAppOpsNotedInThisBinderTransaction = new ThreadLocal<>(); new ThreadLocal<>();
/** Whether noting for an appop should be collected */ /** Whether noting for an appop should be collected */
private static final @ShouldCollectNoteOp byte[] sAppOpsToNote = new byte[_NUM_OP]; private static final @ShouldCollectNoteOp byte[] sAppOpsToNote = new byte[_NUM_OP];
@@ -9051,6 +9051,66 @@ public class AppOpsManager {
sBinderThreadCallingUid.set(callingUid); sBinderThreadCallingUid.set(callingUid);
} }
/**
* State of a temporarily paused noted app-ops collection.
*
* @see #pauseNotedAppOpsCollection()
*
* @hide
*/
public static class PausedNotedAppOpsCollection {
final int mUid;
final @Nullable ArrayMap<String, long[]> mCollectedNotedAppOps;
PausedNotedAppOpsCollection(int uid, @Nullable ArrayMap<String,
long[]> collectedNotedAppOps) {
mUid = uid;
mCollectedNotedAppOps = collectedNotedAppOps;
}
}
/**
* Temporarily suspend collection of noted app-ops when binder-thread calls into the other
* process. During such a call there might be call-backs coming back on the same thread which
* should not be accounted to the current collection.
*
* @return a state needed to resume the collection
*
* @hide
*/
public static @Nullable PausedNotedAppOpsCollection pauseNotedAppOpsCollection() {
Integer previousUid = sBinderThreadCallingUid.get();
if (previousUid != null) {
ArrayMap<String, long[]> previousCollectedNotedAppOps =
sAppOpsNotedInThisBinderTransaction.get();
sBinderThreadCallingUid.remove();
sAppOpsNotedInThisBinderTransaction.remove();
return new PausedNotedAppOpsCollection(previousUid, previousCollectedNotedAppOps);
}
return null;
}
/**
* Resume a collection paused via {@link #pauseNotedAppOpsCollection}.
*
* @param prevCollection The state of the previous collection
*
* @hide
*/
public static void resumeNotedAppOpsCollection(
@Nullable PausedNotedAppOpsCollection prevCollection) {
if (prevCollection != null) {
sBinderThreadCallingUid.set(prevCollection.mUid);
if (prevCollection.mCollectedNotedAppOps != null) {
sAppOpsNotedInThisBinderTransaction.set(prevCollection.mCollectedNotedAppOps);
}
}
}
/** /**
* Finish collection of noted appops on this thread. * Finish collection of noted appops on this thread.
* *
@@ -9091,47 +9151,26 @@ public class AppOpsManager {
*/ */
@TestApi @TestApi
public static void collectNotedOpSync(@NonNull SyncNotedAppOp syncOp) { public static void collectNotedOpSync(@NonNull SyncNotedAppOp syncOp) {
collectNotedOpSync(sOpStrToOp.get(syncOp.getOp()), syncOp.getAttributionTag(),
syncOp.getPackageName());
}
/**
* Collect a noted op when inside of a two-way binder call.
*
* <p> Delivered to caller via {@link #prefixParcelWithAppOpsIfNeeded}
*
* @param code the op code to note for
* @param attributionTag the attribution tag to note for
* @param packageName the package to note for
*/
private static void collectNotedOpSync(int code, @Nullable String attributionTag,
@NonNull String packageName) {
// If this is inside of a two-way binder call: // If this is inside of a two-way binder call:
// We are inside of a two-way binder call. Delivered to caller via // We are inside of a two-way binder call. Delivered to caller via
// {@link #prefixParcelWithAppOpsIfNeeded} // {@link #prefixParcelWithAppOpsIfNeeded}
ArrayMap<String, ArrayMap<String, long[]>> appOpsNoted = int op = sOpStrToOp.get(syncOp.getOp());
sAppOpsNotedInThisBinderTransaction.get(); ArrayMap<String, long[]> appOpsNoted = sAppOpsNotedInThisBinderTransaction.get();
if (appOpsNoted == null) { if (appOpsNoted == null) {
appOpsNoted = new ArrayMap<>(1); appOpsNoted = new ArrayMap<>(1);
sAppOpsNotedInThisBinderTransaction.set(appOpsNoted); sAppOpsNotedInThisBinderTransaction.set(appOpsNoted);
} }
ArrayMap<String, long[]> packageAppOpsNotedForAttribution = appOpsNoted.get(packageName); long[] appOpsNotedForAttribution = appOpsNoted.get(syncOp.getAttributionTag());
if (packageAppOpsNotedForAttribution == null) {
packageAppOpsNotedForAttribution = new ArrayMap<>(1);
appOpsNoted.put(packageName, packageAppOpsNotedForAttribution);
}
long[] appOpsNotedForAttribution = packageAppOpsNotedForAttribution.get(attributionTag);
if (appOpsNotedForAttribution == null) { if (appOpsNotedForAttribution == null) {
appOpsNotedForAttribution = new long[2]; appOpsNotedForAttribution = new long[2];
packageAppOpsNotedForAttribution.put(attributionTag, appOpsNotedForAttribution); appOpsNoted.put(syncOp.getAttributionTag(), appOpsNotedForAttribution);
} }
if (code < 64) { if (op < 64) {
appOpsNotedForAttribution[0] |= 1L << code; appOpsNotedForAttribution[0] |= 1L << op;
} else { } else {
appOpsNotedForAttribution[1] |= 1L << (code - 64); appOpsNotedForAttribution[1] |= 1L << (op - 64);
} }
} }
@@ -9185,7 +9224,9 @@ public class AppOpsManager {
} }
} }
if (isListeningForOpNotedInBinderTransaction()) { Integer binderUid = sBinderThreadCallingUid.get();
if (binderUid != null && binderUid == uid) {
return COLLECT_SYNC; return COLLECT_SYNC;
} else { } else {
return COLLECT_ASYNC; return COLLECT_ASYNC;
@@ -9204,32 +9245,20 @@ public class AppOpsManager {
*/ */
// TODO (b/186872903) Refactor how sync noted ops are propagated. // TODO (b/186872903) Refactor how sync noted ops are propagated.
public static void prefixParcelWithAppOpsIfNeeded(@NonNull Parcel p) { public static void prefixParcelWithAppOpsIfNeeded(@NonNull Parcel p) {
if (!isListeningForOpNotedInBinderTransaction()) { ArrayMap<String, long[]> notedAppOps = sAppOpsNotedInThisBinderTransaction.get();
return;
}
final ArrayMap<String, ArrayMap<String, long[]>> notedAppOps =
sAppOpsNotedInThisBinderTransaction.get();
if (notedAppOps == null) { if (notedAppOps == null) {
return; return;
} }
p.writeInt(Parcel.EX_HAS_NOTED_APPOPS_REPLY_HEADER); p.writeInt(Parcel.EX_HAS_NOTED_APPOPS_REPLY_HEADER);
final int packageCount = notedAppOps.size(); int numAttributionWithNotesAppOps = notedAppOps.size();
p.writeInt(packageCount); p.writeInt(numAttributionWithNotesAppOps);
for (int i = 0; i < packageCount; i++) { for (int i = 0; i < numAttributionWithNotesAppOps; i++) {
p.writeString(notedAppOps.keyAt(i)); p.writeString(notedAppOps.keyAt(i));
p.writeLong(notedAppOps.valueAt(i)[0]);
final ArrayMap<String, long[]> notedTagAppOps = notedAppOps.valueAt(i); p.writeLong(notedAppOps.valueAt(i)[1]);
final int tagCount = notedTagAppOps.size();
p.writeInt(tagCount);
for (int j = 0; j < tagCount; j++) {
p.writeString(notedTagAppOps.keyAt(j));
p.writeLong(notedTagAppOps.valueAt(j)[0]);
p.writeLong(notedTagAppOps.valueAt(j)[1]);
}
} }
} }
@@ -9244,55 +9273,37 @@ public class AppOpsManager {
* @hide * @hide
*/ */
public static void readAndLogNotedAppops(@NonNull Parcel p) { public static void readAndLogNotedAppops(@NonNull Parcel p) {
final int packageCount = p.readInt(); int numAttributionsWithNotedAppOps = p.readInt();
if (packageCount <= 0) {
return;
}
final String myPackageName = ActivityThread.currentPackageName(); for (int i = 0; i < numAttributionsWithNotedAppOps; i++) {
String attributionTag = p.readString();
long[] rawNotedAppOps = new long[2];
rawNotedAppOps[0] = p.readLong();
rawNotedAppOps[1] = p.readLong();
synchronized (sLock) { if (rawNotedAppOps[0] != 0 || rawNotedAppOps[1] != 0) {
for (int i = 0; i < packageCount; i++) { BitSet notedAppOps = BitSet.valueOf(rawNotedAppOps);
final String packageName = p.readString();
final int tagCount = p.readInt(); synchronized (sLock) {
for (int j = 0; j < tagCount; j++) {
final String attributionTag = p.readString();
final long[] rawNotedAppOps = new long[2];
rawNotedAppOps[0] = p.readLong();
rawNotedAppOps[1] = p.readLong();
if (rawNotedAppOps[0] == 0 && rawNotedAppOps[1] == 0) {
continue;
}
final BitSet notedAppOps = BitSet.valueOf(rawNotedAppOps);
for (int code = notedAppOps.nextSetBit(0); code != -1; for (int code = notedAppOps.nextSetBit(0); code != -1;
code = notedAppOps.nextSetBit(code + 1)) { code = notedAppOps.nextSetBit(code + 1)) {
if (Objects.equals(myPackageName, packageName)) { if (sOnOpNotedCallback != null) {
if (sOnOpNotedCallback != null) { sOnOpNotedCallback.onNoted(new SyncNotedAppOp(code, attributionTag));
sOnOpNotedCallback.onNoted(new SyncNotedAppOp(code, } else {
attributionTag, packageName)); String message = getFormattedStackTrace();
} else { sUnforwardedOps.add(
String message = getFormattedStackTrace(); new AsyncNotedAppOp(code, Process.myUid(), attributionTag,
sUnforwardedOps.add(new AsyncNotedAppOp(code, Process.myUid(), message, System.currentTimeMillis()));
attributionTag, message, System.currentTimeMillis())); if (sUnforwardedOps.size() > MAX_UNFORWARDED_OPS) {
if (sUnforwardedOps.size() > MAX_UNFORWARDED_OPS) { sUnforwardedOps.remove(0);
sUnforwardedOps.remove(0);
}
} }
} else if (isListeningForOpNotedInBinderTransaction()) {
collectNotedOpSync(code, attributionTag, packageName);
}
}
for (int code = notedAppOps.nextSetBit(0); code != -1;
code = notedAppOps.nextSetBit(code + 1)) {
if (Objects.equals(myPackageName, packageName)) {
sMessageCollector.onNoted(new SyncNotedAppOp(code,
attributionTag, packageName));
} }
} }
} }
for (int code = notedAppOps.nextSetBit(0); code != -1;
code = notedAppOps.nextSetBit(code + 1)) {
sMessageCollector.onNoted(new SyncNotedAppOp(code, attributionTag));
}
} }
} }
} }
@@ -9398,15 +9409,7 @@ public class AppOpsManager {
* @hide * @hide
*/ */
public static boolean isListeningForOpNoted() { public static boolean isListeningForOpNoted() {
return sOnOpNotedCallback != null || isListeningForOpNotedInBinderTransaction() return sOnOpNotedCallback != null || isCollectingStackTraces();
|| isCollectingStackTraces();
}
/**
* @return whether we are in a binder transaction and collecting appops.
*/
private static boolean isListeningForOpNotedInBinderTransaction() {
return sBinderThreadCallingUid.get() != null;
} }
/** /**

View File

@@ -21,7 +21,6 @@ import android.annotation.NonNull;
import android.annotation.Nullable; import android.annotation.Nullable;
import android.annotation.TestApi; import android.annotation.TestApi;
import android.os.Parcelable; import android.os.Parcelable;
import android.os.Process;
import com.android.internal.annotations.Immutable; import com.android.internal.annotations.Immutable;
import com.android.internal.util.DataClass; import com.android.internal.util.DataClass;
@@ -29,6 +28,8 @@ import com.android.internal.util.DataClass;
/** /**
* Description of an app-op that was noted for the current process. * Description of an app-op that was noted for the current process.
* *
* Note: package name is currently unused in the system.
*
* <p>This is either delivered after a * <p>This is either delivered after a
* {@link AppOpsManager.OnOpNotedCallback#onNoted(SyncNotedAppOp) two way binder call} or * {@link AppOpsManager.OnOpNotedCallback#onNoted(SyncNotedAppOp) two way binder call} or
* when the app * when the app

View File

@@ -560,6 +560,9 @@ public final class BinderProxy implements IBinder {
} }
} }
final AppOpsManager.PausedNotedAppOpsCollection prevCollection =
AppOpsManager.pauseNotedAppOpsCollection();
if ((flags & FLAG_ONEWAY) == 0 && AppOpsManager.isListeningForOpNoted()) { if ((flags & FLAG_ONEWAY) == 0 && AppOpsManager.isListeningForOpNoted()) {
flags |= FLAG_COLLECT_NOTED_APP_OPS; flags |= FLAG_COLLECT_NOTED_APP_OPS;
} }
@@ -567,6 +570,8 @@ public final class BinderProxy implements IBinder {
try { try {
return transactNative(code, data, reply, flags); return transactNative(code, data, reply, flags);
} finally { } finally {
AppOpsManager.resumeNotedAppOpsCollection(prevCollection);
if (transactListener != null) { if (transactListener != null) {
transactListener.onTransactEnded(session); transactListener.onTransactEnded(session);
} }

View File

@@ -3438,7 +3438,7 @@ public class AppOpsService extends IAppOpsService.Stub {
+ " package " + packageName + "flags: " + + " package " + packageName + "flags: " +
AppOpsManager.flagsToString(flags)); AppOpsManager.flagsToString(flags));
return new SyncNotedAppOp(AppOpsManager.MODE_ERRORED, code, attributionTag, return new SyncNotedAppOp(AppOpsManager.MODE_ERRORED, code, attributionTag,
packageName + " flags: " + AppOpsManager.flagsToString(flags)); packageName);
} }
final Op op = getOpLocked(ops, code, uid, true); final Op op = getOpLocked(ops, code, uid, true);
final AttributedOp attributedOp = op.getOrCreateAttribution(op, attributionTag); final AttributedOp attributedOp = op.getOrCreateAttribution(op, attributionTag);