Audio policy: use new concurrent record bypass permission

Use either CAPTURE_AUDIO_OUTPUT or
BYPASS_CONCURRENT_RECORD_AUDIO_RESTRICTION permission to allow
concurrent capture during calls. Use of CAPTURE_AUDIO_OUTPUT will be
removed once all system apps are updated.

Bug: 374751406
Test: make
Flag: android.media.audio.concurrent_audio_record_bypass_permission
Change-Id: I1adc9e6fa6b013cfd40e3c3f5559abd6802716ac
diff --git a/aidl/com/android/media/permission/PermissionEnum.aidl b/aidl/com/android/media/permission/PermissionEnum.aidl
index b08db44..7badb87 100644
--- a/aidl/com/android/media/permission/PermissionEnum.aidl
+++ b/aidl/com/android/media/permission/PermissionEnum.aidl
@@ -37,5 +37,6 @@
     CAPTURE_TUNER_AUDIO_INPUT = 11,
     CAPTURE_VOICE_COMMUNICATION_OUTPUT = 12,
     BLUETOOTH_CONNECT = 13,
-    ENUM_SIZE = 14, // Not for actual usage, used by Java
+    BYPASS_CONCURRENT_RECORD_AUDIO_RESTRICTION = 14,
+    ENUM_SIZE = 15, // Not for actual usage, used by Java
 }
diff --git a/media/utils/ServiceUtilities.cpp b/media/utils/ServiceUtilities.cpp
index ddb93fe..ee0f2bc 100644
--- a/media/utils/ServiceUtilities.cpp
+++ b/media/utils/ServiceUtilities.cpp
@@ -291,6 +291,21 @@
     return ok;
 }
 
+bool bypassConcurrentPolicyAllowed(const AttributionSourceState& attributionSource) {
+    uid_t uid = VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(attributionSource.uid));
+    uid_t pid = VALUE_OR_FATAL(aidl2legacy_int32_t_pid_t(attributionSource.pid));
+    if (isAudioServerOrRootUid(uid)) return true;
+    static const String16 sBypassConcurrentPolicy(
+            "android.permission.BYPASS_CONCURRENT_RECORD_AUDIO_RESTRICTION ");
+    // Use PermissionChecker, which includes some logic for allowing the isolated
+    // HotwordDetectionService to hold certain permissions.
+    bool ok = PermissionCache::checkPermission(sBypassConcurrentPolicy, pid, uid);
+    if (!ok) {
+        ALOGV("Request requires android.permission.BYPASS_CONCURRENT_RECORD_AUDIO_RESTRICTION");
+    }
+    return ok;
+}
+
 bool accessUltrasoundAllowed(const AttributionSourceState& attributionSource) {
     uid_t uid = VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(attributionSource.uid));
     uid_t pid = VALUE_OR_FATAL(aidl2legacy_int32_t_pid_t(attributionSource.pid));
diff --git a/media/utils/include/mediautils/ServiceUtilities.h b/media/utils/include/mediautils/ServiceUtilities.h
index 9abdbf1..573cc14 100644
--- a/media/utils/include/mediautils/ServiceUtilities.h
+++ b/media/utils/include/mediautils/ServiceUtilities.h
@@ -102,6 +102,7 @@
 bool captureMediaOutputAllowed(const AttributionSourceState& attributionSource);
 bool captureTunerAudioInputAllowed(const AttributionSourceState& attributionSource);
 bool captureVoiceCommunicationOutputAllowed(const AttributionSourceState& attributionSource);
+bool bypassConcurrentPolicyAllowed(const AttributionSourceState& attributionSource) ;
 bool accessUltrasoundAllowed(const AttributionSourceState& attributionSource);
 bool captureHotwordAllowed(const AttributionSourceState& attributionSource);
 bool settingsAllowed();
diff --git a/services/audiopolicy/service/Android.bp b/services/audiopolicy/service/Android.bp
index e157808..619c924 100644
--- a/services/audiopolicy/service/Android.bp
+++ b/services/audiopolicy/service/Android.bp
@@ -16,6 +16,7 @@
     ],
 
     shared_libs: [
+        "android.media.audio-aconfig-cc",
         "android.media.audiopolicy-aconfig-cc",
         "audio-permission-aidl-cpp",
         "audioclient-types-aidl-cpp",
diff --git a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
index 3589de1..df7077c 100644
--- a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
+++ b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
@@ -23,6 +23,7 @@
 
 #include <android/content/AttributionSourceState.h>
 #include <android_media_audiopolicy.h>
+#include <android_media_audio.h>
 #include <com_android_media_audio.h>
 #include <cutils/properties.h>
 #include <error/expected_utils.h>
@@ -56,6 +57,7 @@
 namespace audiopolicy_flags = android::media::audiopolicy;
 using binder::Status;
 using aidl_utils::binderStatusFromStatusT;
+using android::media::audio::concurrent_audio_record_bypass_permission;
 using com::android::media::audio::audioserver_permissions;
 using com::android::media::permission::NativePermissionController;
 using com::android::media::permission::PermissionEnum::ACCESS_ULTRASOUND;
@@ -71,6 +73,7 @@
 using com::android::media::permission::PermissionEnum::MODIFY_PHONE_STATE;
 using com::android::media::permission::PermissionEnum::RECORD_AUDIO;
 using com::android::media::permission::PermissionEnum::WRITE_SECURE_SETTINGS;
+using com::android::media::permission::PermissionEnum::BYPASS_CONCURRENT_RECORD_AUDIO_RESTRICTION;
 using content::AttributionSourceState;
 using media::audio::common::AudioConfig;
 using media::audio::common::AudioConfigBase;
@@ -734,6 +737,17 @@
     bool canCaptureOutput = audioserver_permissions() ?
                         CHECK_PERM(CAPTURE_AUDIO_OUTPUT, attributionSource.uid)
                         : captureAudioOutputAllowed(attributionSource);
+
+    //TODO(b/374751406): remove forcing canBypassConcurrentPolicy to canCaptureOutput
+    // once all system apps using CAPTURE_AUDIO_OUTPUT to capture during calls
+    // are updated to use the new CONCURRENT_AUDIO_RECORD_BYPASS permission.
+    bool canBypassConcurrentPolicy = canCaptureOutput;
+    if (concurrent_audio_record_bypass_permission()) {
+        canBypassConcurrentPolicy = audioserver_permissions() ?
+                            CHECK_PERM(BYPASS_CONCURRENT_RECORD_AUDIO_RESTRICTION,
+                                       attributionSource.uid)
+                            : bypassConcurrentPolicyAllowed(attributionSource);
+    }
     bool canInterceptCallAudio = audioserver_permissions() ?
                         CHECK_PERM(CALL_AUDIO_INTERCEPTION, attributionSource.uid)
                         : callAudioInterceptionAllowed(attributionSource);
@@ -874,7 +888,8 @@
         sp<AudioRecordClient> client = new AudioRecordClient(attr, input, session, portId,
                                                              selectedDeviceIds, attributionSource,
                                                              virtualDeviceId,
-                                                             canCaptureOutput, canCaptureHotword,
+                                                             canBypassConcurrentPolicy,
+                                                             canCaptureHotword,
                                                              mOutputCommandThread);
         mAudioRecordClients.add(portId, client);
     }
diff --git a/services/audiopolicy/service/AudioPolicyService.cpp b/services/audiopolicy/service/AudioPolicyService.cpp
index 80ee34e..4c506e8 100644
--- a/services/audiopolicy/service/AudioPolicyService.cpp
+++ b/services/audiopolicy/service/AudioPolicyService.cpp
@@ -853,13 +853,13 @@
 //               AND an accessibility service is TOP
 //                  AND source is either VOICE_RECOGNITION OR HOTWORD
 //               OR there is no active privacy sensitive capture or call
-//                          OR client has CAPTURE_AUDIO_OUTPUT privileged permission
+//                          OR client can capture calls
 //                  AND source is VOICE_RECOGNITION OR HOTWORD
 //    The client is an assistant AND active assistant is not being used
 //        AND an accessibility service is on TOP or a RTT call is active
 //                AND the source is VOICE_RECOGNITION or HOTWORD
 //        OR there is no active privacy sensitive capture or call
-//                OR client has CAPTURE_AUDIO_OUTPUT privileged permission
+//                OR client can capture calls
 //            AND is TOP most recent assistant and uses VOICE_RECOGNITION or HOTWORD
 //                OR there is no top recent assistant and source is HOTWORD
 //    OR The client is an accessibility service
@@ -867,7 +867,7 @@
 //                AND the source is VOICE_RECOGNITION or HOTWORD
 //            OR The assistant is not on TOP
 //                AND there is no active privacy sensitive capture or call
-//                    OR client has CAPTURE_AUDIO_OUTPUT privileged permission
+//                    OR client can capture calls
 //        AND is on TOP
 //        AND the source is VOICE_RECOGNITION or HOTWORD
 //    OR the client source is virtual (remote submix, call audio TX or RX...)
@@ -875,7 +875,7 @@
 //        AND is on TOP
 //            OR all active clients are using HOTWORD source
 //        AND no call is active
-//            OR client has CAPTURE_AUDIO_OUTPUT privileged permission
+//            OR client can capture calls
 //    OR the client is the current InputMethodService
 //        AND a RTT call is active AND the source is VOICE_RECOGNITION
 //    OR The client is an active communication owner
@@ -884,7 +884,11 @@
 //        AND The assistant is not on TOP
 //        AND is on TOP or latest started
 //        AND there is no active privacy sensitive capture or call
-//            OR client has CAPTURE_AUDIO_OUTPUT privileged permission
+//            OR client can capture calls
+//    NOTE: a client can capture calls if it either:
+//       has CAPTURE_AUDIO_OUTPUT privileged permission (temporarily until
+//            all system apps are updated)
+//       or has CONCURRENT_AUDIO_RECORD_BYPASS privileged permission
 
 
     sp<AudioRecordClient> topActive;
@@ -1024,7 +1028,7 @@
     //  else
     //    favor the privacy sensitive case
     if (topActive != nullptr && topSensitiveActive != nullptr
-            && !topActive->canCaptureOutput) {
+            && !topActive->canBypassConcurrentPolicy) {
         topActive = nullptr;
     }
 
@@ -1055,8 +1059,8 @@
                                                                mMutex) {
             uid_t recordUid = VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(
                 recordClient->attributionSource.uid));
-            bool canCaptureCall = recordClient->canCaptureOutput;
-            bool canCaptureCommunication = recordClient->canCaptureOutput
+            bool canCaptureCall = recordClient->canBypassConcurrentPolicy;
+            bool canCaptureCommunication = recordClient->canBypassConcurrentPolicy
                 || !isPhoneStateOwnerActive
                 || recordUid == mPhoneStateOwnerUid;
             return !(isInCall && !canCaptureCall)
@@ -1072,7 +1076,7 @@
         //         AND is ongoing communication owner
         //         AND is on TOP or latest started
         const bool allowSensitiveCapture =
-            !isSensitiveActive || isTopOrLatestSensitive || current->canCaptureOutput;
+            !isSensitiveActive || isTopOrLatestSensitive || current->canBypassConcurrentPolicy;
         bool allowCapture = false;
         if (!isAssistantOnTop || isActiveAssistant) {
             allowCapture = (isTopOrLatestActive || isTopOrLatestSensitive) &&
diff --git a/services/audiopolicy/service/AudioRecordClient.h b/services/audiopolicy/service/AudioRecordClient.h
index 76bc17a..2135575 100644
--- a/services/audiopolicy/service/AudioRecordClient.h
+++ b/services/audiopolicy/service/AudioRecordClient.h
@@ -90,12 +90,12 @@
                       const DeviceIdVector deviceIds,
                       const AttributionSourceState& attributionSource,
                       const uint32_t virtualDeviceId,
-                      bool canCaptureOutput, bool canCaptureHotword,
+                      bool canBypassConcurrentPolicy, bool canCaptureHotword,
                       wp<AudioPolicyService::AudioCommandThread> commandThread) :
                 AudioClient(attributes, io, attributionSource,
                     session, portId, deviceIds), attributionSource(attributionSource),
                     virtualDeviceId(virtualDeviceId),
-                    startTimeNs(0), canCaptureOutput(canCaptureOutput),
+                    startTimeNs(0), canBypassConcurrentPolicy(canBypassConcurrentPolicy),
                     canCaptureHotword(canCaptureHotword), silenced(false),
                     mOpRecordAudioMonitor(
                             OpRecordAudioMonitor::createIfNeeded(attributionSource,
@@ -112,7 +112,7 @@
     const AttributionSourceState attributionSource; // attribution source of client
     const uint32_t virtualDeviceId; // id of the virtual device associated with the audio device
     nsecs_t startTimeNs;
-    const bool canCaptureOutput;
+    const bool canBypassConcurrentPolicy;
     const bool canCaptureHotword;
     bool silenced;