Add permission check for audio attributes tags.

Audio attributes tags are system APIs in NDK that can be used to affect
routing, volume control, etc. In that case, apply
MODIFY_AUDIO_SETTINGS_PRIVILEGED permission check to protect it.

Bug: 378909923
Test: atest test_attributes
Flag: EXEMPT NDK
Change-Id: Id2a4063b72587e9495bd1221ef82122725f28b5a
diff --git a/aidl/com/android/media/permission/PermissionEnum.aidl b/aidl/com/android/media/permission/PermissionEnum.aidl
index 7badb87..8eeae10 100644
--- a/aidl/com/android/media/permission/PermissionEnum.aidl
+++ b/aidl/com/android/media/permission/PermissionEnum.aidl
@@ -38,5 +38,6 @@
     CAPTURE_VOICE_COMMUNICATION_OUTPUT = 12,
     BLUETOOTH_CONNECT = 13,
     BYPASS_CONCURRENT_RECORD_AUDIO_RESTRICTION = 14,
-    ENUM_SIZE = 15, // Not for actual usage, used by Java
+    MODIFY_AUDIO_SETTINGS_PRIVILEGED = 15,
+    ENUM_SIZE = 16, // Not for actual usage, used by Java
 }
diff --git a/media/utils/ServiceUtilities.cpp b/media/utils/ServiceUtilities.cpp
index 39a172f..8ceff96 100644
--- a/media/utils/ServiceUtilities.cpp
+++ b/media/utils/ServiceUtilities.cpp
@@ -55,6 +55,8 @@
 static const String16 sModifyPhoneState("android.permission.MODIFY_PHONE_STATE");
 static const String16 sModifyAudioRouting("android.permission.MODIFY_AUDIO_ROUTING");
 static const String16 sCallAudioInterception("android.permission.CALL_AUDIO_INTERCEPTION");
+static const String16 sModifyAudioSettingsPrivileged(
+        "android.permission.MODIFY_AUDIO_SETTINGS_PRIVILEGED");
 
 static String16 resolveCallingPackage(PermissionController& permissionController,
         const std::optional<String16> opPackageName, uid_t uid) {
@@ -387,6 +389,17 @@
     return ok;
 }
 
+bool modifyAudioSettingsPrivilegedAllowed(const AttributionSourceState& attributionSource) {
+    uid_t uid = VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(attributionSource.uid));
+    pid_t pid = VALUE_OR_FATAL(aidl2legacy_int32_t_pid_t(attributionSource.pid));
+    if (isAudioServerUid(uid)) return true;
+    // IMPORTANT: Use PermissionCache - not a runtime permission and may not change.
+    bool ok = PermissionCache::checkPermission(sModifyAudioSettingsPrivileged, pid, uid);
+    if (!ok) ALOGE("%s(): android.permission.MODIFY_AUDIO_SETTINGS_PRIVILEGED denied for uid %d",
+                   __func__, uid);
+    return ok;
+}
+
 bool dumpAllowed() {
     static const String16 sDump("android.permission.DUMP");
     // IMPORTANT: Use PermissionCache - not a runtime permission and may not change.
diff --git a/media/utils/include/mediautils/ServiceUtilities.h b/media/utils/include/mediautils/ServiceUtilities.h
index 573cc14..42789d5 100644
--- a/media/utils/include/mediautils/ServiceUtilities.h
+++ b/media/utils/include/mediautils/ServiceUtilities.h
@@ -110,6 +110,7 @@
 bool modifyAudioRoutingAllowed(const AttributionSourceState& attributionSource);
 bool modifyDefaultAudioEffectsAllowed();
 bool modifyDefaultAudioEffectsAllowed(const AttributionSourceState& attributionSource);
+bool modifyAudioSettingsPrivilegedAllowed(const AttributionSourceState& attributionSource);
 bool dumpAllowed();
 bool modifyPhoneStateAllowed(const AttributionSourceState& attributionSource);
 bool bypassInterruptionPolicyAllowed(const AttributionSourceState& attributionSource);
diff --git a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
index 12320b7..802ebeb 100644
--- a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
+++ b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
@@ -73,6 +73,7 @@
 using com::android::media::permission::PermissionEnum::CAPTURE_TUNER_AUDIO_INPUT;
 using com::android::media::permission::PermissionEnum::MODIFY_AUDIO_ROUTING;
 using com::android::media::permission::PermissionEnum::MODIFY_AUDIO_SETTINGS;
+using com::android::media::permission::PermissionEnum::MODIFY_AUDIO_SETTINGS_PRIVILEGED;
 using com::android::media::permission::PermissionEnum::MODIFY_DEFAULT_AUDIO_EFFECTS;
 using com::android::media::permission::PermissionEnum::MODIFY_PHONE_STATE;
 using com::android::media::permission::PermissionEnum::RECORD_AUDIO;
@@ -443,6 +444,16 @@
         }
     }
 
+    if (strlen(attr.tags) != 0) {
+        if (!(audioserver_permissions() ?
+              CHECK_PERM(MODIFY_AUDIO_SETTINGS_PRIVILEGED, attributionSource.uid)
+              : modifyAudioSettingsPrivilegedAllowed(attributionSource))) {
+            ALOGE("%s: permission denied: audio attributes tags not allowed for uid %d pid %d",
+                  __func__, attributionSource.uid, attributionSource.pid);
+            return binderStatusFromStatusT(PERMISSION_DENIED);
+        }
+    }
+
     AutoCallerClear acc;
     AudioPolicyInterface::output_type_t outputType;
     bool isSpatialized = false;