Collect AsyncNotedAppOp in same call as noteOp
This reduces the overhead of collecting noted app-ops to the same amount
of binder calls as if we would not have the feature
Before (conceptionally):
---------------------------------
mode = service.noteOp()
if (mode == allowed && shouldCollectAsyncOp) {
fixup(message)
service.noteAsyncOp()
}
----------------------------------
After (conceptionally):
----------------------------------
if (shouldCollectAsyncOp) {
fixup(message)
}
mode = service.noteOp(shouldCollectAsyncOp, message)
----------------------------------
Bug: 136505050
Test: atest CtsAppOpsTestCases
Change-Id: If1b535a7c4b0f431f251c5d06cdf496c34920e23
This commit is contained in:
@@ -2046,7 +2046,7 @@ public class AppOpsManager {
|
||||
* transaction. Not set if this thread is currently not executing a two way binder transaction.
|
||||
*
|
||||
* @see #startNotedAppOpsCollection
|
||||
* @see #markAppOpNoted
|
||||
* @see #getNotedOpCollectionMode
|
||||
*/
|
||||
private static final ThreadLocal<Integer> sBinderThreadCallingUid = new ThreadLocal<>();
|
||||
|
||||
@@ -2054,7 +2054,8 @@ public class AppOpsManager {
|
||||
* If a thread is currently executing a two-way binder transaction, this stores the op-codes of
|
||||
* the app-ops that were noted during this transaction.
|
||||
*
|
||||
* @see #markAppOpNoted
|
||||
* @see #getNotedOpCollectionMode
|
||||
* @see #collectNotedOpSync
|
||||
*/
|
||||
private static final ThreadLocal<ArrayMap<String, long[]>> sAppOpsNotedInThisBinderTransaction =
|
||||
new ThreadLocal<>();
|
||||
@@ -6322,9 +6323,23 @@ public class AppOpsManager {
|
||||
public int noteOpNoThrow(int op, int uid, @Nullable String packageName,
|
||||
@Nullable String featureId, @Nullable String message) {
|
||||
try {
|
||||
int mode = mService.noteOperation(op, uid, packageName, featureId);
|
||||
int collectionMode = getNotedOpCollectionMode(uid, packageName, op);
|
||||
if (collectionMode == COLLECT_ASYNC) {
|
||||
if (message == null) {
|
||||
// Set stack trace as default message
|
||||
message = getFormattedStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
int mode = mService.noteOperation(op, uid, packageName, featureId,
|
||||
collectionMode == COLLECT_ASYNC, message);
|
||||
|
||||
if (mode == MODE_ALLOWED) {
|
||||
markAppOpNoted(uid, packageName, op, featureId, message);
|
||||
if (collectionMode == COLLECT_SELF) {
|
||||
collectNotedOpForSelf(op, featureId);
|
||||
} else if (collectionMode == COLLECT_SYNC) {
|
||||
collectNotedOpSync(op, featureId);
|
||||
}
|
||||
}
|
||||
|
||||
return mode;
|
||||
@@ -6468,14 +6483,27 @@ public class AppOpsManager {
|
||||
int myUid = Process.myUid();
|
||||
|
||||
try {
|
||||
int collectionMode = getNotedOpCollectionMode(proxiedUid, proxiedPackageName, op);
|
||||
if (collectionMode == COLLECT_ASYNC) {
|
||||
if (message == null) {
|
||||
// Set stack trace as default message
|
||||
message = getFormattedStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
int mode = mService.noteProxyOperation(op, proxiedUid, proxiedPackageName,
|
||||
proxiedFeatureId, myUid, mContext.getOpPackageName(),
|
||||
mContext.getFeatureId());
|
||||
if (mode == MODE_ALLOWED
|
||||
// Only collect app-ops when the proxy is trusted
|
||||
&& mContext.checkPermission(Manifest.permission.UPDATE_APP_OPS_STATS, -1, myUid)
|
||||
== PackageManager.PERMISSION_GRANTED) {
|
||||
markAppOpNoted(proxiedUid, proxiedPackageName, op, proxiedFeatureId, message);
|
||||
mContext.getFeatureId(), collectionMode == COLLECT_ASYNC, message);
|
||||
|
||||
if (mode == MODE_ALLOWED) {
|
||||
if (collectionMode == COLLECT_SELF) {
|
||||
collectNotedOpForSelf(op, proxiedFeatureId);
|
||||
} else if (collectionMode == COLLECT_SYNC
|
||||
// Only collect app-ops when the proxy is trusted
|
||||
&& mContext.checkPermission(Manifest.permission.UPDATE_APP_OPS_STATS, -1,
|
||||
myUid) == PackageManager.PERMISSION_GRANTED) {
|
||||
collectNotedOpSync(op, proxiedFeatureId);
|
||||
}
|
||||
}
|
||||
|
||||
return mode;
|
||||
@@ -6765,10 +6793,23 @@ public class AppOpsManager {
|
||||
public int startOpNoThrow(int op, int uid, @NonNull String packageName,
|
||||
boolean startIfModeDefault, @Nullable String featureId, @Nullable String message) {
|
||||
try {
|
||||
int collectionMode = getNotedOpCollectionMode(uid, packageName, op);
|
||||
if (collectionMode == COLLECT_ASYNC) {
|
||||
if (message == null) {
|
||||
// Set stack trace as default message
|
||||
message = getFormattedStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
int mode = mService.startOperation(getClientId(), op, uid, packageName,
|
||||
featureId, startIfModeDefault);
|
||||
featureId, startIfModeDefault, collectionMode == COLLECT_ASYNC, message);
|
||||
|
||||
if (mode == MODE_ALLOWED) {
|
||||
markAppOpNoted(uid, packageName, op, featureId, message);
|
||||
if (collectionMode == COLLECT_SELF) {
|
||||
collectNotedOpForSelf(op, featureId);
|
||||
} else if (collectionMode == COLLECT_SYNC) {
|
||||
collectNotedOpSync(op, featureId);
|
||||
}
|
||||
}
|
||||
|
||||
return mode;
|
||||
@@ -6932,85 +6973,106 @@ public class AppOpsManager {
|
||||
}
|
||||
|
||||
/**
|
||||
* Mark an app-op as noted
|
||||
* Collect a noted op for the current process.
|
||||
*
|
||||
* @param op The noted op
|
||||
* @param featureId The feature the op is noted for
|
||||
*/
|
||||
private void markAppOpNoted(int uid, @Nullable String packageName, int code,
|
||||
@Nullable String featureId, @Nullable String message) {
|
||||
private void collectNotedOpForSelf(int op, @Nullable String featureId) {
|
||||
synchronized (sLock) {
|
||||
if (sNotedAppOpsCollector != null) {
|
||||
sNotedAppOpsCollector.onSelfNoted(new SyncNotedAppOp(op, featureId));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Collect a noted op when inside of a two-way binder call.
|
||||
*
|
||||
* <p> Delivered to caller via {@link #prefixParcelWithAppOpsIfNeeded}
|
||||
*
|
||||
* @param op The noted op
|
||||
* @param featureId The feature the op is noted for
|
||||
*/
|
||||
private void collectNotedOpSync(int op, @Nullable String featureId) {
|
||||
// If this is inside of a two-way binder call:
|
||||
// We are inside of a two-way binder call. Delivered to caller via
|
||||
// {@link #prefixParcelWithAppOpsIfNeeded}
|
||||
ArrayMap<String, long[]> appOpsNoted = sAppOpsNotedInThisBinderTransaction.get();
|
||||
if (appOpsNoted == null) {
|
||||
appOpsNoted = new ArrayMap<>(1);
|
||||
sAppOpsNotedInThisBinderTransaction.set(appOpsNoted);
|
||||
}
|
||||
|
||||
long[] appOpsNotedForFeature = appOpsNoted.get(featureId);
|
||||
if (appOpsNotedForFeature == null) {
|
||||
appOpsNotedForFeature = new long[2];
|
||||
appOpsNoted.put(featureId, appOpsNotedForFeature);
|
||||
}
|
||||
|
||||
if (op < 64) {
|
||||
appOpsNotedForFeature[0] |= 1L << op;
|
||||
} else {
|
||||
appOpsNotedForFeature[1] |= 1L << (op - 64);
|
||||
}
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
@IntDef(value = {
|
||||
DONT_COLLECT,
|
||||
COLLECT_SELF,
|
||||
COLLECT_SYNC,
|
||||
COLLECT_ASYNC
|
||||
})
|
||||
private @interface NotedOpCollectionMode {}
|
||||
private static final int DONT_COLLECT = 0;
|
||||
private static final int COLLECT_SELF = 1;
|
||||
private static final int COLLECT_SYNC = 2;
|
||||
private static final int COLLECT_ASYNC = 3;
|
||||
|
||||
/**
|
||||
* Mark an app-op as noted.
|
||||
*/
|
||||
private @NotedOpCollectionMode int getNotedOpCollectionMode(int uid,
|
||||
@Nullable String packageName, int op) {
|
||||
if (packageName == null) {
|
||||
packageName = "android";
|
||||
}
|
||||
|
||||
// check it the appops needs to be collected and cache result
|
||||
if (sAppOpsToNote[code] == SHOULD_COLLECT_NOTE_OP_NOT_INITIALIZED) {
|
||||
if (sAppOpsToNote[op] == SHOULD_COLLECT_NOTE_OP_NOT_INITIALIZED) {
|
||||
boolean shouldCollectNotes;
|
||||
try {
|
||||
shouldCollectNotes = mService.shouldCollectNotes(code);
|
||||
shouldCollectNotes = mService.shouldCollectNotes(op);
|
||||
} catch (RemoteException e) {
|
||||
return;
|
||||
return DONT_COLLECT;
|
||||
}
|
||||
|
||||
if (shouldCollectNotes) {
|
||||
sAppOpsToNote[code] = SHOULD_COLLECT_NOTE_OP;
|
||||
sAppOpsToNote[op] = SHOULD_COLLECT_NOTE_OP;
|
||||
} else {
|
||||
sAppOpsToNote[code] = SHOULD_NOT_COLLECT_NOTE_OP;
|
||||
sAppOpsToNote[op] = SHOULD_NOT_COLLECT_NOTE_OP;
|
||||
}
|
||||
}
|
||||
|
||||
if (sAppOpsToNote[code] != SHOULD_COLLECT_NOTE_OP) {
|
||||
return;
|
||||
if (sAppOpsToNote[op] != SHOULD_COLLECT_NOTE_OP) {
|
||||
return DONT_COLLECT;
|
||||
}
|
||||
|
||||
synchronized (sLock) {
|
||||
if (uid == Process.myUid()
|
||||
&& packageName.equals(ActivityThread.currentOpPackageName())) {
|
||||
return COLLECT_SELF;
|
||||
}
|
||||
}
|
||||
|
||||
Integer binderUid = sBinderThreadCallingUid.get();
|
||||
|
||||
synchronized (sLock) {
|
||||
if (sNotedAppOpsCollector != null && uid == Process.myUid() && packageName.equals(
|
||||
ActivityThread.currentOpPackageName())) {
|
||||
// This app is noting an app-op for itself. Deliver immediately.
|
||||
sNotedAppOpsCollector.onSelfNoted(new SyncNotedAppOp(code, featureId));
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (binderUid != null && binderUid == uid) {
|
||||
// If this is inside of a two-way binder call: Delivered to caller via
|
||||
// {@link #prefixParcelWithAppOpsIfNeeded}
|
||||
// We are inside of a two-way binder call. Delivered to caller via
|
||||
// {@link #prefixParcelWithAppOpsIfNeeded}
|
||||
ArrayMap<String, long[]> appOpsNoted = sAppOpsNotedInThisBinderTransaction.get();
|
||||
if (appOpsNoted == null) {
|
||||
appOpsNoted = new ArrayMap<>(1);
|
||||
sAppOpsNotedInThisBinderTransaction.set(appOpsNoted);
|
||||
}
|
||||
|
||||
long[] appOpsNotedForFeature = appOpsNoted.get(featureId);
|
||||
if (appOpsNotedForFeature == null) {
|
||||
appOpsNotedForFeature = new long[2];
|
||||
appOpsNoted.put(featureId, appOpsNotedForFeature);
|
||||
}
|
||||
|
||||
if (code < 64) {
|
||||
appOpsNotedForFeature[0] |= 1L << code;
|
||||
} else {
|
||||
appOpsNotedForFeature[1] |= 1L << (code - 64);
|
||||
}
|
||||
return COLLECT_SYNC;
|
||||
} else {
|
||||
// Cannot deliver the note synchronous: Hence send it to the system server to
|
||||
// notify the noted process.
|
||||
if (message == null) {
|
||||
// Default message is a stack trace
|
||||
message = getFormattedStackTrace();
|
||||
}
|
||||
|
||||
long token = Binder.clearCallingIdentity();
|
||||
try {
|
||||
mService.noteAsyncOp(mContext.getOpPackageName(), uid, packageName, code,
|
||||
featureId, message);
|
||||
} catch (RemoteException e) {
|
||||
e.rethrowFromSystemServer();
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(token);
|
||||
}
|
||||
return COLLECT_ASYNC;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@ import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.util.SparseIntArray;
|
||||
|
||||
import com.android.internal.util.function.HexFunction;
|
||||
import com.android.internal.util.function.QuadFunction;
|
||||
|
||||
/**
|
||||
@@ -63,12 +64,16 @@ public abstract class AppOpsManagerInternal {
|
||||
* @param uid The UID for which to note.
|
||||
* @param packageName The package for which to note. {@code null} for system package.
|
||||
* @param featureId Id of the feature in the package
|
||||
* @param shouldCollectAsyncNotedOp If an {@link AsyncNotedAppOp} should be collected
|
||||
* @param message The message in the async noted op
|
||||
* @param superImpl The super implementation.
|
||||
* @return The app op note result.
|
||||
*/
|
||||
int noteOperation(int code, int uid, @Nullable String packageName,
|
||||
@Nullable String featureId,
|
||||
@NonNull QuadFunction<Integer, Integer, String, String, Integer> superImpl);
|
||||
@Nullable String featureId, boolean shouldCollectAsyncNotedOp,
|
||||
@Nullable String message,
|
||||
@NonNull HexFunction<Integer, Integer, String, String, Boolean, String, Integer>
|
||||
superImpl);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -45,12 +45,6 @@ public final class AsyncNotedAppOp implements Parcelable {
|
||||
/** Uid that noted the op */
|
||||
private final @IntRange(from = 0) int mNotingUid;
|
||||
|
||||
/**
|
||||
* Package that noted the op. {@code null} if the package name that noted the op could be not
|
||||
* be determined (e.g. when the op is noted from native code).
|
||||
*/
|
||||
private final @Nullable String mNotingPackageName;
|
||||
|
||||
/** {@link android.content.Context#createFeatureContext Feature} in the app */
|
||||
private final @Nullable String mFeatureId;
|
||||
|
||||
@@ -69,7 +63,7 @@ public final class AsyncNotedAppOp implements Parcelable {
|
||||
|
||||
|
||||
|
||||
// Code below generated by codegen v1.0.9.
|
||||
// Code below generated by codegen v1.0.14.
|
||||
//
|
||||
// DO NOT MODIFY!
|
||||
// CHECKSTYLE:OFF Generated code
|
||||
@@ -89,9 +83,6 @@ public final class AsyncNotedAppOp implements Parcelable {
|
||||
* Op that was noted
|
||||
* @param notingUid
|
||||
* Uid that noted the op
|
||||
* @param notingPackageName
|
||||
* Package that noted the op. {@code null} if the package name that noted the op could be not
|
||||
* be determined (e.g. when the op is noted from native code).
|
||||
* @param featureId
|
||||
* {@link android.content.Context#createFeatureContext Feature} in the app
|
||||
* @param message
|
||||
@@ -104,7 +95,6 @@ public final class AsyncNotedAppOp implements Parcelable {
|
||||
public AsyncNotedAppOp(
|
||||
@IntRange(from = 0, to = AppOpsManager._NUM_OP - 1) int opCode,
|
||||
@IntRange(from = 0) int notingUid,
|
||||
@Nullable String notingPackageName,
|
||||
@Nullable String featureId,
|
||||
@NonNull String message,
|
||||
@IntRange(from = 0) long time) {
|
||||
@@ -117,7 +107,6 @@ public final class AsyncNotedAppOp implements Parcelable {
|
||||
com.android.internal.util.AnnotationValidations.validate(
|
||||
IntRange.class, null, mNotingUid,
|
||||
"from", 0);
|
||||
this.mNotingPackageName = notingPackageName;
|
||||
this.mFeatureId = featureId;
|
||||
this.mMessage = message;
|
||||
com.android.internal.util.AnnotationValidations.validate(
|
||||
@@ -138,15 +127,6 @@ public final class AsyncNotedAppOp implements Parcelable {
|
||||
return mNotingUid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Package that noted the op. {@code null} if the package name that noted the op could be not
|
||||
* be determined (e.g. when the op is noted from native code).
|
||||
*/
|
||||
@DataClass.Generated.Member
|
||||
public @Nullable String getNotingPackageName() {
|
||||
return mNotingPackageName;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link android.content.Context#createFeatureContext Feature} in the app
|
||||
*/
|
||||
@@ -186,7 +166,6 @@ public final class AsyncNotedAppOp implements Parcelable {
|
||||
return true
|
||||
&& mOpCode == that.mOpCode
|
||||
&& mNotingUid == that.mNotingUid
|
||||
&& java.util.Objects.equals(mNotingPackageName, that.mNotingPackageName)
|
||||
&& java.util.Objects.equals(mFeatureId, that.mFeatureId)
|
||||
&& java.util.Objects.equals(mMessage, that.mMessage)
|
||||
&& mTime == that.mTime;
|
||||
@@ -201,7 +180,6 @@ public final class AsyncNotedAppOp implements Parcelable {
|
||||
int _hash = 1;
|
||||
_hash = 31 * _hash + mOpCode;
|
||||
_hash = 31 * _hash + mNotingUid;
|
||||
_hash = 31 * _hash + java.util.Objects.hashCode(mNotingPackageName);
|
||||
_hash = 31 * _hash + java.util.Objects.hashCode(mFeatureId);
|
||||
_hash = 31 * _hash + java.util.Objects.hashCode(mMessage);
|
||||
_hash = 31 * _hash + Long.hashCode(mTime);
|
||||
@@ -215,12 +193,10 @@ public final class AsyncNotedAppOp implements Parcelable {
|
||||
// void parcelFieldName(Parcel dest, int flags) { ... }
|
||||
|
||||
byte flg = 0;
|
||||
if (mNotingPackageName != null) flg |= 0x4;
|
||||
if (mFeatureId != null) flg |= 0x8;
|
||||
if (mFeatureId != null) flg |= 0x4;
|
||||
dest.writeByte(flg);
|
||||
dest.writeInt(mOpCode);
|
||||
dest.writeInt(mNotingUid);
|
||||
if (mNotingPackageName != null) dest.writeString(mNotingPackageName);
|
||||
if (mFeatureId != null) dest.writeString(mFeatureId);
|
||||
dest.writeString(mMessage);
|
||||
dest.writeLong(mTime);
|
||||
@@ -240,8 +216,7 @@ public final class AsyncNotedAppOp implements Parcelable {
|
||||
byte flg = in.readByte();
|
||||
int opCode = in.readInt();
|
||||
int notingUid = in.readInt();
|
||||
String notingPackageName = (flg & 0x4) == 0 ? null : in.readString();
|
||||
String featureId = (flg & 0x8) == 0 ? null : in.readString();
|
||||
String featureId = (flg & 0x4) == 0 ? null : in.readString();
|
||||
String message = in.readString();
|
||||
long time = in.readLong();
|
||||
|
||||
@@ -254,7 +229,6 @@ public final class AsyncNotedAppOp implements Parcelable {
|
||||
com.android.internal.util.AnnotationValidations.validate(
|
||||
IntRange.class, null, mNotingUid,
|
||||
"from", 0);
|
||||
this.mNotingPackageName = notingPackageName;
|
||||
this.mFeatureId = featureId;
|
||||
this.mMessage = message;
|
||||
com.android.internal.util.AnnotationValidations.validate(
|
||||
@@ -282,11 +256,15 @@ public final class AsyncNotedAppOp implements Parcelable {
|
||||
};
|
||||
|
||||
@DataClass.Generated(
|
||||
time = 1571327470155L,
|
||||
codegenVersion = "1.0.9",
|
||||
time = 1576864422226L,
|
||||
codegenVersion = "1.0.14",
|
||||
sourceFile = "frameworks/base/core/java/android/app/AsyncNotedAppOp.java",
|
||||
inputSignatures = "private final @android.annotation.IntRange(from=0L, to=92L) int mOpCode\nprivate final @android.annotation.IntRange(from=0L) int mNotingUid\nprivate final @android.annotation.Nullable java.lang.String mNotingPackageName\nprivate final @android.annotation.Nullable java.lang.String mFeatureId\nprivate final @android.annotation.NonNull java.lang.String mMessage\nprivate final @android.annotation.IntRange(from=0L) long mTime\npublic @android.annotation.NonNull java.lang.String getOp()\nclass AsyncNotedAppOp extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genEqualsHashCode=true, genAidl=true, genHiddenConstructor=true)")
|
||||
inputSignatures = "private final @android.annotation.IntRange(from=0L, to=92L) int mOpCode\nprivate final @android.annotation.IntRange(from=0L) int mNotingUid\nprivate final @android.annotation.Nullable java.lang.String mFeatureId\nprivate final @android.annotation.NonNull java.lang.String mMessage\nprivate final @android.annotation.IntRange(from=0L) long mTime\npublic @android.annotation.NonNull java.lang.String getOp()\nclass AsyncNotedAppOp extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genEqualsHashCode=true, genAidl=true, genHiddenConstructor=true)")
|
||||
@Deprecated
|
||||
private void __metadata() {}
|
||||
|
||||
|
||||
//@formatter:on
|
||||
// End of generated code
|
||||
|
||||
}
|
||||
|
||||
@@ -31,9 +31,11 @@ interface IAppOpsService {
|
||||
// be kept in sync with frameworks/native/libs/binder/include/binder/IAppOpsService.h
|
||||
// and not be reordered
|
||||
int checkOperation(int code, int uid, String packageName);
|
||||
int noteOperation(int code, int uid, String packageName, @nullable String featureId);
|
||||
int noteOperation(int code, int uid, String packageName, @nullable String featureId,
|
||||
boolean shouldCollectAsyncNotedOp, String message);
|
||||
int startOperation(IBinder clientId, int code, int uid, String packageName,
|
||||
@nullable String featureId, boolean startIfModeDefault);
|
||||
@nullable String featureId, boolean startIfModeDefault,
|
||||
boolean shouldCollectAsyncNotedOp, String message);
|
||||
@UnsupportedAppUsage
|
||||
void finishOperation(IBinder clientId, int code, int uid, String packageName,
|
||||
@nullable String featureId);
|
||||
@@ -41,8 +43,6 @@ interface IAppOpsService {
|
||||
void stopWatchingMode(IAppOpsCallback callback);
|
||||
int permissionToOpCode(String permission);
|
||||
int checkAudioOperation(int code, int usage, int uid, String packageName);
|
||||
void noteAsyncOp(@nullable String callingPackageName, int uid, @nullable String packageName,
|
||||
int opCode, @nullable String featureId, String message);
|
||||
boolean shouldCollectNotes(int opCode);
|
||||
void setCameraAudioRestriction(int mode);
|
||||
// End of methods also called by native code.
|
||||
@@ -50,7 +50,7 @@ interface IAppOpsService {
|
||||
|
||||
int noteProxyOperation(int code, int proxiedUid, String proxiedPackageName,
|
||||
String proxiedFeatureId, int proxyUid, String proxyPackageName,
|
||||
String proxyFeatureId);
|
||||
String proxyFeatureId, boolean shouldCollectAsyncNotedOp, String message);
|
||||
|
||||
// Remaining methods are only used in Java.
|
||||
int checkPackage(int uid, String packageName);
|
||||
|
||||
Reference in New Issue
Block a user