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