Attribute SOURCE_HOTWORD to OP_RECORD_AUDIO_HOTWORD.

Whenever we startRecording / finishRecording with a source
of SOURCE_HOTWORD, attribute them to OP_RECORD_AUDIO_HOTWORD
instead of OP_RECORD_AUDIO. In either case, OP_RECORD_AUDIO
is checked before the recording commences. Note that we also
check that all recordings with SOURCE_HOTWORD are initiated
by a uid that holds the privileged CAPTURE_AUDIO_HOTWORD
permission.

Note that this change will be superseded in the future once
we have stronger guarantees around hotword handling.

Bug: 162547999
Test: manual with dumpsys appops on AGSA

(cherry picked from commit d127644025c5820e39a2908a249691284b4447d6)

Merged-In: I70e0b652c357597770a18a5a385d62668a69059a
Change-Id: I5ba43828efb0654ec2c1f04fb9737d48a8c4f0bf
diff --git a/media/utils/ServiceUtilities.cpp b/media/utils/ServiceUtilities.cpp
index 143a4e1..491823e 100644
--- a/media/utils/ServiceUtilities.cpp
+++ b/media/utils/ServiceUtilities.cpp
@@ -62,7 +62,7 @@
 }
 
 static bool checkRecordingInternal(const String16& opPackageName, pid_t pid,
-        uid_t uid, bool start) {
+        uid_t uid, bool start, bool isHotwordSource) {
     // Okay to not track in app ops as audio server or media server is us and if
     // device is rooted security model is considered compromised.
     // system_server loses its RECORD_AUDIO permission when a secondary
@@ -87,8 +87,11 @@
     }
 
     AppOpsManager appOps;
-    const int32_t op = appOps.permissionToOpCode(sAndroidPermissionRecordAudio);
+    const int32_t opRecordAudio = appOps.permissionToOpCode(sAndroidPermissionRecordAudio);
+
     if (start) {
+        const int32_t op = isHotwordSource ?
+                AppOpsManager::OP_RECORD_AUDIO_HOTWORD : opRecordAudio;
         if (int32_t mode = appOps.startOpNoThrow(
                         op, uid, resolvedOpPackageName, /*startIfModeDefault*/ false);
                 mode != AppOpsManager::MODE_ALLOWED) {
@@ -97,10 +100,11 @@
             return false;
         }
     } else {
-        if (int32_t mode = appOps.checkOp(op, uid, resolvedOpPackageName);
+        // Always use OP_RECORD_AUDIO for checks at creation time.
+        if (int32_t mode = appOps.checkOp(opRecordAudio, uid, resolvedOpPackageName);
                 mode != AppOpsManager::MODE_ALLOWED) {
             ALOGE("Request check for \"%s\" (uid %d) denied by app op: %d, mode: %d",
-                    String8(resolvedOpPackageName).c_str(), uid, op, mode);
+                    String8(resolvedOpPackageName).c_str(), uid, opRecordAudio, mode);
             return false;
         }
     }
@@ -109,14 +113,15 @@
 }
 
 bool recordingAllowed(const String16& opPackageName, pid_t pid, uid_t uid) {
-    return checkRecordingInternal(opPackageName, pid, uid, /*start*/ false);
+    return checkRecordingInternal(opPackageName, pid, uid, /*start*/ false,
+            /*is_hotword_source*/ false);
 }
 
-bool startRecording(const String16& opPackageName, pid_t pid, uid_t uid) {
-     return checkRecordingInternal(opPackageName, pid, uid, /*start*/ true);
+bool startRecording(const String16& opPackageName, pid_t pid, uid_t uid, bool isHotwordSource) {
+     return checkRecordingInternal(opPackageName, pid, uid, /*start*/ true, isHotwordSource);
 }
 
-void finishRecording(const String16& opPackageName, uid_t uid) {
+void finishRecording(const String16& opPackageName, uid_t uid, bool isHotwordSource) {
     // Okay to not track in app ops as audio server is us and if
     // device is rooted security model is considered compromised.
     if (isAudioServerOrRootUid(uid)) return;
@@ -129,7 +134,8 @@
     }
 
     AppOpsManager appOps;
-    const int32_t op = appOps.permissionToOpCode(sAndroidPermissionRecordAudio);
+    const int32_t op = isHotwordSource ? AppOpsManager::OP_RECORD_AUDIO_HOTWORD
+            : appOps.permissionToOpCode(sAndroidPermissionRecordAudio);
     appOps.finishOp(op, uid, resolvedOpPackageName);
 }
 
diff --git a/media/utils/fuzzers/ServiceUtilitiesFuzz.cpp b/media/utils/fuzzers/ServiceUtilitiesFuzz.cpp
index 3d141b5..183155c 100644
--- a/media/utils/fuzzers/ServiceUtilitiesFuzz.cpp
+++ b/media/utils/fuzzers/ServiceUtilitiesFuzz.cpp
@@ -44,6 +44,7 @@
     FuzzedDataProvider data_provider(data, size);
     uid_t uid = data_provider.ConsumeIntegral<uid_t>();
     pid_t pid = data_provider.ConsumeIntegral<pid_t>();
+    bool isHotword = data_provider.ConsumeBool();
 
     // There is not state here, and order is not significant,
     // so we can simply call all of the target functions
@@ -54,8 +55,8 @@
     std::string packageNameStr = data_provider.ConsumeRandomLengthString(kMaxStringLen);
     android::String16 opPackageName(packageNameStr.c_str());
     android::recordingAllowed(opPackageName, pid, uid);
-    android::startRecording(opPackageName, pid, uid);
-    android::finishRecording(opPackageName, uid);
+    android::startRecording(opPackageName, pid, uid, isHotword);
+    android::finishRecording(opPackageName, uid, isHotword);
     android::captureAudioOutputAllowed(pid, uid);
     android::captureMediaOutputAllowed(pid, uid);
     android::captureHotwordAllowed(opPackageName, pid, uid);
diff --git a/media/utils/include/mediautils/ServiceUtilities.h b/media/utils/include/mediautils/ServiceUtilities.h
index 212599a..431dd7a 100644
--- a/media/utils/include/mediautils/ServiceUtilities.h
+++ b/media/utils/include/mediautils/ServiceUtilities.h
@@ -79,8 +79,8 @@
 }
 
 bool recordingAllowed(const String16& opPackageName, pid_t pid, uid_t uid);
-bool startRecording(const String16& opPackageName, pid_t pid, uid_t uid);
-void finishRecording(const String16& opPackageName, uid_t uid);
+bool startRecording(const String16& opPackageName, pid_t pid, uid_t uid, bool isHotwordSource);
+void finishRecording(const String16& opPackageName, uid_t uid, bool isHotwordSource);
 bool captureAudioOutputAllowed(pid_t pid, uid_t uid);
 bool captureMediaOutputAllowed(pid_t pid, uid_t uid);
 bool captureVoiceCommunicationOutputAllowed(pid_t pid, uid_t uid);
diff --git a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
index df8e4c5..dcd30f6 100644
--- a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
+++ b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
@@ -573,7 +573,8 @@
     }
 
     // check calling permissions
-    if (!(startRecording(client->opPackageName, client->pid, client->uid)
+    if (!(startRecording(client->opPackageName, client->pid, client->uid,
+            client->attributes.source == AUDIO_SOURCE_HOTWORD)
             || client->attributes.source == AUDIO_SOURCE_FM_TUNER)) {
         ALOGE("%s permission denied: recording not allowed for uid %d pid %d",
                 __func__, client->uid, client->pid);
@@ -661,7 +662,8 @@
         client->active = false;
         client->startTimeNs = 0;
         updateUidStates_l();
-        finishRecording(client->opPackageName, client->uid);
+        finishRecording(client->opPackageName, client->uid,
+                        client->attributes.source == AUDIO_SOURCE_HOTWORD);
     }
 
     return status;
@@ -687,7 +689,8 @@
     updateUidStates_l();
 
     // finish the recording app op
-    finishRecording(client->opPackageName, client->uid);
+    finishRecording(client->opPackageName, client->uid,
+                    client->attributes.source == AUDIO_SOURCE_HOTWORD);
     AutoCallerClear acc;
     return mAudioPolicyManager->stopInput(portId);
 }