Merge "Appops refcount fixup" into main
diff --git a/media/utils/ServiceUtilities.cpp b/media/utils/ServiceUtilities.cpp
index 679b111..ddb93fe 100644
--- a/media/utils/ServiceUtilities.cpp
+++ b/media/utils/ServiceUtilities.cpp
@@ -45,6 +45,7 @@
 namespace android {
 
 namespace {
+constexpr auto PERMISSION_GRANTED = permission::PermissionChecker::PERMISSION_GRANTED;
 constexpr auto PERMISSION_HARD_DENIED = permission::PermissionChecker::PERMISSION_HARD_DENIED;
 }
 
@@ -78,19 +79,32 @@
 
 int32_t getOpForSource(audio_source_t source) {
   switch (source) {
-    case AUDIO_SOURCE_HOTWORD:
-      return AppOpsManager::OP_RECORD_AUDIO_HOTWORD;
+    case AUDIO_SOURCE_FM_TUNER:
+        return AppOpsManager::OP_NONE;
     case AUDIO_SOURCE_ECHO_REFERENCE: // fallthrough
     case AUDIO_SOURCE_REMOTE_SUBMIX:
       return AppOpsManager::OP_RECORD_AUDIO_OUTPUT;
     case AUDIO_SOURCE_VOICE_DOWNLINK:
       return AppOpsManager::OP_RECORD_INCOMING_PHONE_AUDIO;
+    case AUDIO_SOURCE_HOTWORD:
+      return AppOpsManager::OP_RECORD_AUDIO_HOTWORD;
     case AUDIO_SOURCE_DEFAULT:
     default:
       return AppOpsManager::OP_RECORD_AUDIO;
   }
 }
 
+bool isRecordOpRequired(audio_source_t source) {
+  switch (source) {
+    case AUDIO_SOURCE_FM_TUNER:
+    case AUDIO_SOURCE_ECHO_REFERENCE: // fallthrough
+    case AUDIO_SOURCE_REMOTE_SUBMIX:
+        return false;
+    default:
+      return true;
+  }
+}
+
 std::optional<AttributionSourceState> resolveAttributionSource(
         const AttributionSourceState& callerAttributionSource, const uint32_t virtualDeviceId) {
     AttributionSourceState nextAttributionSource = callerAttributionSource;
@@ -122,7 +136,8 @@
     return std::optional<AttributionSourceState>{myAttributionSource};
 }
 
-    static int checkRecordingInternal(const AttributionSourceState &attributionSource,
+
+static int checkRecordingInternal(const AttributionSourceState &attributionSource,
                                        const uint32_t virtualDeviceId,
                                        const String16 &msg, bool start, audio_source_t source) {
     // Okay to not track in app ops as audio server or media server is us and if
@@ -131,32 +146,47 @@
     // user is active, but it is a core system service so let it through.
     // TODO(b/141210120): UserManager.DISALLOW_RECORD_AUDIO should not affect system user 0
     uid_t uid = VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(attributionSource.uid));
-    if (isAudioServerOrMediaServerOrSystemServerOrRootUid(uid)) return true;
-
-    // We specify a pid and uid here as mediaserver (aka MediaRecorder or StageFrightRecorder)
-    // may open a record track on behalf of a client. Note that pid may be a tid.
-    // IMPORTANT: DON'T USE PermissionCache - RUNTIME PERMISSIONS CHANGE.
-    std::optional<AttributionSourceState> resolvedAttributionSource =
-            resolveAttributionSource(attributionSource, virtualDeviceId);
-    if (!resolvedAttributionSource.has_value()) {
-        return false;
-    }
+    if (isAudioServerOrMediaServerOrSystemServerOrRootUid(uid)) return PERMISSION_GRANTED;
 
     const int32_t attributedOpCode = getOpForSource(source);
+    if (isRecordOpRequired(source)) {
+        // We specify a pid and uid here as mediaserver (aka MediaRecorder or StageFrightRecorder)
+        // may open a record track on behalf of a client. Note that pid may be a tid.
+        // IMPORTANT: DON'T USE PermissionCache - RUNTIME PERMISSIONS CHANGE.
+        std::optional<AttributionSourceState> resolvedAttributionSource =
+                resolveAttributionSource(attributionSource, virtualDeviceId);
+        if (!resolvedAttributionSource.has_value()) {
+            return PERMISSION_HARD_DENIED;
+        }
 
-    permission::PermissionChecker permissionChecker;
-    int permitted;
-    if (start) {
-        permitted = permissionChecker.checkPermissionForStartDataDeliveryFromDatasource(
-                sAndroidPermissionRecordAudio, resolvedAttributionSource.value(), msg,
-                attributedOpCode);
+        permission::PermissionChecker permissionChecker;
+        int permitted;
+        if (start) {
+            permitted = permissionChecker.checkPermissionForStartDataDeliveryFromDatasource(
+                    sAndroidPermissionRecordAudio, resolvedAttributionSource.value(), msg,
+                    attributedOpCode);
+        } else {
+            permitted = permissionChecker.checkPermissionForPreflightFromDatasource(
+                    sAndroidPermissionRecordAudio, resolvedAttributionSource.value(), msg,
+                    attributedOpCode);
+        }
+
+        return permitted;
     } else {
-        permitted = permissionChecker.checkPermissionForPreflightFromDatasource(
-                sAndroidPermissionRecordAudio, resolvedAttributionSource.value(), msg,
-                attributedOpCode);
+        if (attributedOpCode == AppOpsManager::OP_NONE) return PERMISSION_GRANTED;  // nothing to do
+        AppOpsManager ap{};
+        PermissionController pc{};
+        return ap.startOpNoThrow(
+                attributedOpCode, attributionSource.uid,
+                resolveCallingPackage(pc,
+                                      String16{attributionSource.packageName.value_or("").c_str()},
+                                      attributionSource.uid),
+                false,
+                attributionSource.attributionTag.has_value()
+                        ? String16{attributionSource.attributionTag.value().c_str()}
+                        : String16{},
+                msg);
     }
-
-    return permitted;
 }
 
 static constexpr int DEVICE_ID_DEFAULT = 0;
@@ -188,19 +218,32 @@
     uid_t uid = VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(attributionSource.uid));
     if (isAudioServerOrMediaServerOrSystemServerOrRootUid(uid)) return;
 
-    // We specify a pid and uid here as mediaserver (aka MediaRecorder or StageFrightRecorder)
-    // may open a record track on behalf of a client. Note that pid may be a tid.
-    // IMPORTANT: DON'T USE PermissionCache - RUNTIME PERMISSIONS CHANGE.
-    const std::optional<AttributionSourceState> resolvedAttributionSource =
-            resolveAttributionSource(attributionSource, virtualDeviceId);
-    if (!resolvedAttributionSource.has_value()) {
-        return;
-    }
-
     const int32_t attributedOpCode = getOpForSource(source);
-    permission::PermissionChecker permissionChecker;
-    permissionChecker.finishDataDeliveryFromDatasource(attributedOpCode,
-            resolvedAttributionSource.value());
+    if (isRecordOpRequired(source)) {
+        // We specify a pid and uid here as mediaserver (aka MediaRecorder or StageFrightRecorder)
+        // may open a record track on behalf of a client. Note that pid may be a tid.
+        // IMPORTANT: DON'T USE PermissionCache - RUNTIME PERMISSIONS CHANGE.
+        const std::optional<AttributionSourceState> resolvedAttributionSource =
+                resolveAttributionSource(attributionSource, virtualDeviceId);
+        if (!resolvedAttributionSource.has_value()) {
+            return;
+        }
+
+        permission::PermissionChecker permissionChecker;
+        permissionChecker.finishDataDeliveryFromDatasource(attributedOpCode,
+                resolvedAttributionSource.value());
+    } else {
+        if (attributedOpCode == AppOpsManager::OP_NONE) return;  // nothing to do
+        AppOpsManager ap{};
+        PermissionController pc{};
+        ap.finishOp(attributedOpCode, attributionSource.uid,
+                    resolveCallingPackage(
+                            pc, String16{attributionSource.packageName.value_or("").c_str()},
+                            attributionSource.uid),
+                    attributionSource.attributionTag.has_value()
+                            ? String16{attributionSource.attributionTag.value().c_str()}
+                            : String16{});
+    }
 }
 
 bool captureAudioOutputAllowed(const AttributionSourceState& attributionSource) {
diff --git a/media/utils/include/mediautils/ServiceUtilities.h b/media/utils/include/mediautils/ServiceUtilities.h
index 461e190..9abdbf1 100644
--- a/media/utils/include/mediautils/ServiceUtilities.h
+++ b/media/utils/include/mediautils/ServiceUtilities.h
@@ -118,6 +118,7 @@
         const AttributionSourceState& attributionSource, const String16& caller);
 void anonymizeBluetoothAddress(char *address);
 
+bool isRecordOpRequired(audio_source_t source);
 int32_t getOpForSource(audio_source_t source);
 
 AttributionSourceState getCallingAttributionSource();
diff --git a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
index 1ffa176..f298541 100644
--- a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
+++ b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
@@ -909,13 +909,12 @@
 
     std::stringstream msg;
     msg << "Audio recording on session " << client->session;
+
     const auto permitted = startRecording(client->attributionSource, client->virtualDeviceId,
             String16(msg.str().c_str()), client->attributes.source);
 
     // check calling permissions
-    if (permitted == PERMISSION_HARD_DENIED && client->attributes.source != AUDIO_SOURCE_FM_TUNER
-            && client->attributes.source != AUDIO_SOURCE_REMOTE_SUBMIX
-            && client->attributes.source != AUDIO_SOURCE_ECHO_REFERENCE) {
+    if (permitted == PERMISSION_HARD_DENIED) {
         ALOGE("%s permission denied: recording not allowed for attribution source %s",
                 __func__, client->attributionSource.toString().c_str());
         return binderStatusFromStatusT(PERMISSION_DENIED);
diff --git a/services/audiopolicy/service/AudioRecordClient.cpp b/services/audiopolicy/service/AudioRecordClient.cpp
index 733f0d6..fd344d9 100644
--- a/services/audiopolicy/service/AudioRecordClient.cpp
+++ b/services/audiopolicy/service/AudioRecordClient.cpp
@@ -19,6 +19,7 @@
 #include "AudioRecordClient.h"
 #include "AudioPolicyService.h"
 #include "binder/AppOpsManager.h"
+#include "mediautils/ServiceUtilities.h"
 #include <android_media_audiopolicy.h>
 
 #include <algorithm>
@@ -118,16 +119,20 @@
     }
 
     return new OpRecordAudioMonitor(attributionSource, virtualDeviceId, attr,
-                                    getOpForSource(attr.source), commandThread);
+                                    getOpForSource(attr.source),
+                                    isRecordOpRequired(attr.source),
+                                    commandThread);
 }
 
 OpRecordAudioMonitor::OpRecordAudioMonitor(
         const AttributionSourceState &attributionSource,
         const uint32_t virtualDeviceId, const audio_attributes_t &attr,
         int32_t appOp,
+        bool shouldMonitorRecord,
         wp<AudioPolicyService::AudioCommandThread> commandThread) :
         mHasOp(true), mAttributionSource(attributionSource),
         mVirtualDeviceId(virtualDeviceId), mAttr(attr), mAppOp(appOp),
+        mShouldMonitorRecord(shouldMonitorRecord),
         mCommandThread(commandThread) {
 }
 
@@ -160,7 +165,7 @@
                       });
     };
     reg(mAppOp);
-    if (mAppOp != AppOpsManager::OP_RECORD_AUDIO) {
+    if (mAppOp != AppOpsManager::OP_RECORD_AUDIO && mShouldMonitorRecord) {
         reg(AppOpsManager::OP_RECORD_AUDIO);
     }
 }
@@ -186,7 +191,7 @@
                 });
     };
     bool hasIt = check(mAppOp);
-    if (mAppOp != AppOpsManager::OP_RECORD_AUDIO) {
+    if (mAppOp != AppOpsManager::OP_RECORD_AUDIO && mShouldMonitorRecord) {
         hasIt = hasIt && check(AppOpsManager::OP_RECORD_AUDIO);
     }
 
diff --git a/services/audiopolicy/service/AudioRecordClient.h b/services/audiopolicy/service/AudioRecordClient.h
index 76aff41..977d77b 100644
--- a/services/audiopolicy/service/AudioRecordClient.h
+++ b/services/audiopolicy/service/AudioRecordClient.h
@@ -47,6 +47,7 @@
                          uint32_t virtualDeviceId,
                          const audio_attributes_t &attr,
                          int32_t appOp,
+                         bool shouldMonitorRecord,
                          wp<AudioPolicyService::AudioCommandThread> commandThread);
 
     void onFirstRef() override;
@@ -74,6 +75,7 @@
     const uint32_t mVirtualDeviceId;
     const audio_attributes_t mAttr;
     const int32_t mAppOp;
+    const bool mShouldMonitorRecord;
     wp<AudioPolicyService::AudioCommandThread> mCommandThread;
 };