Merge "Support noted appops collection in native code"
diff --git a/libs/binder/Android.bp b/libs/binder/Android.bp
index 027418a..0b71d1f 100644
--- a/libs/binder/Android.bp
+++ b/libs/binder/Android.bp
@@ -86,10 +86,8 @@
vendor: {
exclude_srcs: [
"ActivityManager.cpp",
- "AppOpsManager.cpp",
"IActivityManager.cpp",
"IAppOpsCallback.cpp",
- "IAppOpsService.cpp",
"IBatteryStats.cpp",
"IMediaResourceMonitor.cpp",
"IPermissionController.cpp",
diff --git a/libs/binder/AppOpsManager.cpp b/libs/binder/AppOpsManager.cpp
index 525685c..48b218e 100644
--- a/libs/binder/AppOpsManager.cpp
+++ b/libs/binder/AppOpsManager.cpp
@@ -21,10 +21,18 @@
#include <utils/SystemClock.h>
+#include <sys/types.h>
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#endif
+#define LOG_TAG "AppOpsManager"
+
namespace android {
namespace {
+#ifndef __ANDROID_VNDK__
#if defined(__BRILLO__)
// Because Brillo has no application model, security policy is managed
// statically (at build time) with SELinux controls.
@@ -33,13 +41,17 @@
#else
const int APP_OPS_MANAGER_UNAVAILABLE_MODE = AppOpsManager::MODE_IGNORED;
#endif // defined(__BRILLO__)
+#endif // __ANDROID_VNDK__
} // namespace
static String16 _appops("appops");
+#ifndef __ANDROID_VNDK__
static pthread_mutex_t gTokenMutex = PTHREAD_MUTEX_INITIALIZER;
+#endif // __ANDROID_VNDK__
static sp<IBinder> gToken;
+#ifndef __ANDROID_VNDK__
static const sp<IBinder>& getToken(const sp<IAppOpsService>& service) {
pthread_mutex_lock(&gTokenMutex);
if (gToken == nullptr || gToken->pingBinder() != NO_ERROR) {
@@ -48,6 +60,17 @@
pthread_mutex_unlock(&gTokenMutex);
return gToken;
}
+#endif // __ANDROID_VNDK__
+
+thread_local uint64_t notedAppOpsInThisBinderTransaction[2];
+thread_local int32_t uidOfThisBinderTransaction = -1;
+
+// Whether an appop should be collected: 0 == not initialized, 1 == don't note, 2 == note
+#ifndef __ANDROID_VNDK__
+uint8_t appOpsToNote[AppOpsManager::_NUM_OP] = {0};
+#else
+uint8_t appOpsToNote[128] = {0};
+#endif // __ANDROID_VNDK__
AppOpsManager::AppOpsManager()
{
@@ -85,6 +108,7 @@
}
#endif // defined(__BRILLO__)
+#ifndef __ANDROID_VNDK__
int32_t AppOpsManager::checkOp(int32_t op, int32_t uid, const String16& callingPackage)
{
sp<IAppOpsService> service = getService();
@@ -102,18 +126,41 @@
}
int32_t AppOpsManager::noteOp(int32_t op, int32_t uid, const String16& callingPackage) {
+ return noteOp(op, uid, callingPackage, String16("noteOp from native code"));
+}
+
+int32_t AppOpsManager::noteOp(int32_t op, int32_t uid, const String16& callingPackage,
+ const String16& message) {
sp<IAppOpsService> service = getService();
- return service != nullptr
+ int32_t mode = service != nullptr
? service->noteOperation(op, uid, callingPackage)
: APP_OPS_MANAGER_UNAVAILABLE_MODE;
+
+ if (mode == AppOpsManager::MODE_ALLOWED) {
+ markAppOpNoted(uid, callingPackage, op, message);
+ }
+
+ return mode;
}
int32_t AppOpsManager::startOpNoThrow(int32_t op, int32_t uid, const String16& callingPackage,
bool startIfModeDefault) {
+ return startOpNoThrow(op, uid, callingPackage, startIfModeDefault,
+ String16("startOpNoThrow from native code"));
+}
+
+int32_t AppOpsManager::startOpNoThrow(int32_t op, int32_t uid, const String16& callingPackage,
+ bool startIfModeDefault, const String16& message) {
sp<IAppOpsService> service = getService();
- return service != nullptr
+ int32_t mode = service != nullptr
? service->startOperation(getToken(service), op, uid, callingPackage,
startIfModeDefault) : APP_OPS_MANAGER_UNAVAILABLE_MODE;
+
+ if (mode == AppOpsManager::MODE_ALLOWED) {
+ markAppOpNoted(uid, callingPackage, op, message);
+ }
+
+ return mode;
}
void AppOpsManager::finishOp(int32_t op, int32_t uid, const String16& callingPackage) {
@@ -146,5 +193,40 @@
return -1;
}
+#endif // __ANDROID_VNDK__
+
+bool AppOpsManager::shouldCollectNotes(int32_t opcode) {
+ sp<IAppOpsService> service = getService();
+ if (service != nullptr) {
+ return service->shouldCollectNotes(opcode);
+ }
+ return false;
+}
+
+void AppOpsManager::markAppOpNoted(int32_t uid, const String16& packageName, int32_t opCode,
+ const String16& message) {
+ // check it the appops needs to be collected and cache result
+ if (appOpsToNote[opCode] == 0) {
+ if (shouldCollectNotes(opCode)) {
+ appOpsToNote[opCode] = 2;
+ } else {
+ appOpsToNote[opCode] = 1;
+ }
+ }
+
+ if (appOpsToNote[opCode] != 2) {
+ return;
+ }
+
+ noteAsyncOp(String16(), uid, packageName, opCode, message);
+}
+
+void AppOpsManager::noteAsyncOp(const String16& callingPackageName, int32_t uid,
+ const String16& packageName, int32_t opCode, const String16& message) {
+ sp<IAppOpsService> service = getService();
+ if (service != nullptr) {
+ return service->noteAsyncOp(callingPackageName, uid, packageName, opCode, message);
+ }
+}
}; // namespace android
diff --git a/libs/binder/IAppOpsService.cpp b/libs/binder/IAppOpsService.cpp
index c426f3a..8840990 100644
--- a/libs/binder/IAppOpsService.cpp
+++ b/libs/binder/IAppOpsService.cpp
@@ -34,6 +34,7 @@
{
}
+#ifndef __ANDROID_VNDK__
virtual int32_t checkOperation(int32_t code, int32_t uid, const String16& packageName) {
Parcel data, reply;
data.writeInterfaceToken(IAppOpsService::getInterfaceDescriptor());
@@ -111,7 +112,6 @@
return reply.readStrongBinder();
}
-
virtual int32_t permissionToOpCode(const String16& permission) {
Parcel data, reply;
data.writeInterfaceToken(IAppOpsService::getInterfaceDescriptor());
@@ -137,6 +137,45 @@
}
return reply.readInt32();
}
+
+#endif
+ virtual void noteAsyncOp(const String16& callingPackageName, int32_t uid,
+ const String16& packageName, int32_t opCode, const String16& message) {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAppOpsService::getInterfaceDescriptor());
+
+ // Convert empty callingPackage into null string
+ if (callingPackageName.size() != 0) {
+ data.writeString16(callingPackageName);
+ } else {
+ data.writeString16(nullptr, 0);
+ }
+
+ data.writeInt32(uid);
+
+ // Convert empty packageName into null string
+ if (packageName.size() != 0) {
+ data.writeString16(packageName);
+ } else {
+ data.writeString16(nullptr, 0);
+ }
+
+ data.writeInt32(opCode);
+ data.writeString16(message);
+ remote()->transact(NOTE_ASYNC_OP_TRANSACTION, data, &reply);
+ }
+
+ virtual bool shouldCollectNotes(int32_t opCode) {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAppOpsService::getInterfaceDescriptor());
+ data.writeInt32(opCode);
+ remote()->transact(SHOULD_COLLECT_NOTES_TRANSACTION, data, &reply);
+ // fail on exception
+ if (reply.readExceptionCode() != 0) {
+ return false;
+ }
+ return reply.readBool();
+ }
};
IMPLEMENT_META_INTERFACE(AppOpsService, "com.android.internal.app.IAppOpsService");
@@ -149,6 +188,7 @@
{
//printf("AppOpsService received: "); data.print();
switch(code) {
+#ifndef __ANDROID_VNDK__
case CHECK_OPERATION_TRANSACTION: {
CHECK_INTERFACE(IAppOpsService, data, reply);
int32_t code = data.readInt32();
@@ -234,6 +274,26 @@
reply->writeInt32(res);
return NO_ERROR;
} break;
+#endif // __ANDROID_VNDK__
+ case NOTE_ASYNC_OP_TRANSACTION: {
+ CHECK_INTERFACE(IAppOpsService, data, reply);
+ String16 callingPackageName = data.readString16();
+ int32_t uid = data.readInt32();
+ String16 packageName = data.readString16();
+ int32_t opCode = data.readInt32();
+ String16 message = data.readString16();
+ noteAsyncOp(callingPackageName, uid, packageName, opCode, message);
+ reply->writeNoException();
+ return NO_ERROR;
+ } break;
+ case SHOULD_COLLECT_NOTES_TRANSACTION: {
+ CHECK_INTERFACE(IAppOpsService, data, reply);
+ int32_t opCode = data.readInt32();
+ bool shouldCollect = shouldCollectNotes(opCode);
+ reply->writeNoException();
+ reply->writeBool(shouldCollect);
+ return NO_ERROR;
+ } break;
default:
return BBinder::onTransact(code, data, reply, flags);
}
diff --git a/libs/binder/include/binder/AppOpsManager.h b/libs/binder/include/binder/AppOpsManager.h
index 17493b4..7a99396 100644
--- a/libs/binder/include/binder/AppOpsManager.h
+++ b/libs/binder/include/binder/AppOpsManager.h
@@ -17,8 +17,6 @@
#ifndef ANDROID_APP_OPS_MANAGER_H
#define ANDROID_APP_OPS_MANAGER_H
-#ifndef __ANDROID_VNDK__
-
#include <binder/IAppOpsService.h>
#include <utils/threads.h>
@@ -35,6 +33,7 @@
MODE_ERRORED = IAppOpsService::MODE_ERRORED
};
+#ifndef __ANDROID_VNDK__
enum {
OP_NONE = -1,
OP_COARSE_LOCATION = 0,
@@ -109,34 +108,58 @@
OP_START_FOREGROUND = 76,
OP_BLUETOOTH_SCAN = 77,
OP_USE_BIOMETRIC = 78,
+ OP_ACTIVITY_RECOGNITION = 79,
+ OP_SMS_FINANCIAL_TRANSACTIONS = 80,
+ OP_READ_MEDIA_AUDIO = 81,
+ OP_WRITE_MEDIA_AUDIO = 82,
+ OP_READ_MEDIA_VIDEO = 83,
+ OP_WRITE_MEDIA_VIDEO = 84,
+ OP_READ_MEDIA_IMAGES = 85,
+ OP_WRITE_MEDIA_IMAGES = 86,
+ OP_LEGACY_STORAGE = 87,
+ OP_ACCESS_ACCESSIBILITY = 88,
+ OP_READ_DEVICE_IDENTIFIERS = 89,
+ _NUM_OP = 90
};
+#endif // __ANDROID_VNDK__
AppOpsManager();
+#ifndef __ANDROID_VNDK__
int32_t checkOp(int32_t op, int32_t uid, const String16& callingPackage);
int32_t checkAudioOpNoThrow(int32_t op, int32_t usage, int32_t uid,
const String16& callingPackage);
+ // @Deprecated, use noteOp(int32_t, int32_t uid, const String16&, const String16&) instead
int32_t noteOp(int32_t op, int32_t uid, const String16& callingPackage);
+ int32_t noteOp(int32_t op, int32_t uid, const String16& callingPackage,
+ const String16& message);
+ // @Deprecated, use startOpNoThrow(int32_t, int32_t, const String16&, bool, const String16&)
+ // instead
int32_t startOpNoThrow(int32_t op, int32_t uid, const String16& callingPackage,
bool startIfModeDefault);
+ int32_t startOpNoThrow(int32_t op, int32_t uid, const String16& callingPackage,
+ bool startIfModeDefault, const String16& message);
void finishOp(int32_t op, int32_t uid, const String16& callingPackage);
void startWatchingMode(int32_t op, const String16& packageName,
const sp<IAppOpsCallback>& callback);
void stopWatchingMode(const sp<IAppOpsCallback>& callback);
int32_t permissionToOpCode(const String16& permission);
-
+#endif // __ANDROID_VNDK__
+ void noteAsyncOp(const String16& callingPackageName, int32_t uid, const String16& packageName,
+ int32_t opCode, const String16& message);
private:
Mutex mLock;
sp<IAppOpsService> mService;
sp<IAppOpsService> getService();
+ void markAppOpNoted(int32_t uid, const String16& packageName, int32_t opCode,
+ const String16& message);
+ bool shouldCollectNotes(int32_t opCode);
};
}; // namespace android
+
// ---------------------------------------------------------------------------
-#else // __ANDROID_VNDK__
-#error "This header is not visible to vendors"
-#endif // __ANDROID_VNDK__
#endif // ANDROID_APP_OPS_MANAGER_H
diff --git a/libs/binder/include/binder/IAppOpsService.h b/libs/binder/include/binder/IAppOpsService.h
index 3dbd0d9..9d02370 100644
--- a/libs/binder/include/binder/IAppOpsService.h
+++ b/libs/binder/include/binder/IAppOpsService.h
@@ -19,8 +19,8 @@
#define ANDROID_IAPP_OPS_SERVICE_H
#ifndef __ANDROID_VNDK__
-
#include <binder/IAppOpsCallback.h>
+#endif
#include <binder/IInterface.h>
namespace android {
@@ -32,6 +32,7 @@
public:
DECLARE_META_INTERFACE(AppOpsService)
+#ifndef __ANDROID_VNDK__
virtual int32_t checkOperation(int32_t code, int32_t uid, const String16& packageName) = 0;
virtual int32_t noteOperation(int32_t code, int32_t uid, const String16& packageName) = 0;
virtual int32_t startOperation(const sp<IBinder>& token, int32_t code, int32_t uid,
@@ -45,8 +46,13 @@
virtual int32_t permissionToOpCode(const String16& permission) = 0;
virtual int32_t checkAudioOperation(int32_t code, int32_t usage,int32_t uid,
const String16& packageName) = 0;
+#endif // __ANDROID_VNDK__
+ virtual void noteAsyncOp(const String16& callingPackageName, int32_t uid,
+ const String16& packageName, int32_t opCode, const String16& message) = 0;
+ virtual bool shouldCollectNotes(int32_t opCode) = 0;
enum {
+#ifndef __ANDROID_VNDK__
CHECK_OPERATION_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION,
NOTE_OPERATION_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION+1,
START_OPERATION_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION+2,
@@ -56,6 +62,9 @@
GET_TOKEN_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION+6,
PERMISSION_TO_OP_CODE_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION+7,
CHECK_AUDIO_OPERATION_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION+8,
+#endif // __ANDROID_VNDK__
+ NOTE_ASYNC_OP_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION+9,
+ SHOULD_COLLECT_NOTES_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION+10,
};
enum {
@@ -81,8 +90,4 @@
}; // namespace android
-#else // __ANDROID_VNDK__
-#error "This header is not visible to vendors"
-#endif // __ANDROID_VNDK__
-
#endif // ANDROID_IAPP_OPS_SERVICE_H