Note appOps with featureIds from native code

Test: atest CtsAppOpsTestCases
Bug: 136595429
Change-Id: I31cc35134035d19aa7b98567fd998ff7f406b271
diff --git a/libs/binder/AppOpsManager.cpp b/libs/binder/AppOpsManager.cpp
index 9da9c13..60f047f 100644
--- a/libs/binder/AppOpsManager.cpp
+++ b/libs/binder/AppOpsManager.cpp
@@ -115,18 +115,23 @@
 }
 
 int32_t AppOpsManager::noteOp(int32_t op, int32_t uid, const String16& callingPackage) {
-    return noteOp(op, uid, callingPackage, String16("noteOp from native code"));
+    return noteOp(op, uid, callingPackage, String16(), String16());
 }
 
 int32_t AppOpsManager::noteOp(int32_t op, int32_t uid, const String16& callingPackage,
-        const String16& message) {
+        const String16& featureId, const String16& message) {
     sp<IAppOpsService> service = getService();
     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);
+        if (message.size() == 0) {
+            markAppOpNoted(uid, callingPackage, op, featureId,
+                    String16("noteOp from native code"));
+        } else {
+            markAppOpNoted(uid, callingPackage, op, featureId, message);
+        }
     }
 
     return mode;
@@ -134,19 +139,23 @@
 
 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"));
+    return startOpNoThrow(op, uid, callingPackage, startIfModeDefault, String16(), String16());
 }
 
 int32_t AppOpsManager::startOpNoThrow(int32_t op, int32_t uid, const String16& callingPackage,
-        bool startIfModeDefault, const String16& message) {
+        bool startIfModeDefault, const String16& featureId, const String16& message) {
     sp<IAppOpsService> service = getService();
     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);
+        if (message.size() == 0) {
+            markAppOpNoted(uid, callingPackage, op, featureId,
+                    String16("startOp from native code"));
+        } else {
+            markAppOpNoted(uid, callingPackage, op, featureId, message);
+        }
     }
 
     return mode;
@@ -198,7 +207,7 @@
 }
 
 void AppOpsManager::markAppOpNoted(int32_t uid, const String16& packageName, int32_t opCode,
-         const String16& message) {
+         const String16& featureId, const String16& message) {
     // check it the appops needs to be collected and cache result
     if (appOpsToNote[opCode] == 0) {
         if (shouldCollectNotes(opCode)) {
@@ -212,14 +221,16 @@
         return;
     }
 
-    noteAsyncOp(String16(), uid, packageName, opCode, message);
+    noteAsyncOp(String16(), uid, packageName, opCode, featureId, message);
 }
 
 void AppOpsManager::noteAsyncOp(const String16& callingPackageName, int32_t uid,
-         const String16& packageName, int32_t opCode, const String16& message) {
+         const String16& packageName, int32_t opCode, const String16& featureId,
+         const String16& message) {
     sp<IAppOpsService> service = getService();
     if (service != nullptr) {
-        return service->noteAsyncOp(callingPackageName, uid, packageName, opCode, message);
+        return service->noteAsyncOp(callingPackageName, uid, packageName, opCode, featureId,
+                message);
     }
 }
 
diff --git a/libs/binder/IAppOpsService.cpp b/libs/binder/IAppOpsService.cpp
index 6c16c2d..9760e13 100644
--- a/libs/binder/IAppOpsService.cpp
+++ b/libs/binder/IAppOpsService.cpp
@@ -145,7 +145,8 @@
     }
 
     virtual void noteAsyncOp(const String16& callingPackageName, int32_t uid,
-            const String16& packageName, int32_t opCode, const String16& message) {
+            const String16& packageName, int32_t opCode, const String16& featureId,
+            const String16& message) {
         Parcel data, reply;
         data.writeInterfaceToken(IAppOpsService::getInterfaceDescriptor());
 
@@ -166,6 +167,14 @@
         }
 
         data.writeInt32(opCode);
+
+        // Convert empty featureId into null string
+        if (featureId.size() != 0) {
+            data.writeString16(featureId);
+        } else {
+            data.writeString16(nullptr, 0);
+        }
+
         data.writeString16(message);
         remote()->transact(NOTE_ASYNC_OP_TRANSACTION, data, &reply);
     }
@@ -291,8 +300,9 @@
             int32_t uid = data.readInt32();
             String16 packageName = data.readString16();
             int32_t opCode = data.readInt32();
+            String16 featureId = data.readString16();
             String16 message = data.readString16();
-            noteAsyncOp(callingPackageName, uid, packageName, opCode, message);
+            noteAsyncOp(callingPackageName, uid, packageName, opCode, featureId, message);
             reply->writeNoException();
             return NO_ERROR;
         } break;
diff --git a/libs/binder/include/binder/AppOpsManager.h b/libs/binder/include/binder/AppOpsManager.h
index 0ab40b8..2744ce1 100644
--- a/libs/binder/include/binder/AppOpsManager.h
+++ b/libs/binder/include/binder/AppOpsManager.h
@@ -130,16 +130,17 @@
     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
+    // @Deprecated, use noteOp(int32_t, int32_t uid, const String16&, 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
+            const String16& featureId, const String16& message);
+    // @Deprecated, use startOpNoThrow(int32_t, int32_t, const String16&, bool, const String16&,
+    //              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);
+            bool startIfModeDefault, const String16& featureId, 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);
@@ -147,7 +148,7 @@
     int32_t permissionToOpCode(const String16& permission);
     void setCameraAudioRestriction(int32_t mode);
     void noteAsyncOp(const String16& callingPackageName, int32_t uid, const String16& packageName,
-            int32_t opCode, const String16& message);
+            int32_t opCode, const String16& featureId, const String16& message);
 
 private:
     Mutex mLock;
@@ -155,7 +156,7 @@
 
     sp<IAppOpsService> getService();
     void markAppOpNoted(int32_t uid, const String16& packageName, int32_t opCode,
-            const String16& message);
+            const String16& featureId, const String16& message);
     bool shouldCollectNotes(int32_t opCode);
 };
 
diff --git a/libs/binder/include/binder/IAppOpsService.h b/libs/binder/include/binder/IAppOpsService.h
index 8b8a3c2..ad34bc5 100644
--- a/libs/binder/include/binder/IAppOpsService.h
+++ b/libs/binder/include/binder/IAppOpsService.h
@@ -49,7 +49,8 @@
             const String16& packageName) = 0;
     virtual void setCameraAudioRestriction(int32_t mode) = 0;
     virtual void noteAsyncOp(const String16& callingPackageName, int32_t uid,
-            const String16& packageName, int32_t opCode, const String16& message) = 0;
+            const String16& packageName, int32_t opCode, const String16& featureId,
+            const String16& message) = 0;
     virtual bool shouldCollectNotes(int32_t opCode) = 0;
 
     enum {