audio policy: add permission check for privileged attributes flags

Add check for privileged permission if attributes
flags BYPASS_INTERRUPTION_POLICY or BYPASS_MUTE are set.

Bug: 131873101
Test: Manual smoke tests for audio playback.
Test: Emergency cell broadcast in
Change-Id: I073cf669f606f0d081ff5c8d19f39b5e12efe297
diff --git a/media/libaudioclient/AudioSystem.cpp b/media/libaudioclient/AudioSystem.cpp
index d359f52..1e7f9fa 100644
--- a/media/libaudioclient/AudioSystem.cpp
+++ b/media/libaudioclient/AudioSystem.cpp
@@ -864,7 +864,7 @@
     return aps->getOutput(stream);
 }
 
-status_t AudioSystem::getOutputForAttr(const audio_attributes_t *attr,
+status_t AudioSystem::getOutputForAttr(audio_attributes_t *attr,
                                         audio_io_handle_t *output,
                                         audio_session_t session,
                                         audio_stream_type_t *stream,
diff --git a/media/libaudioclient/IAudioPolicyService.cpp b/media/libaudioclient/IAudioPolicyService.cpp
index 9b4221c..c548457 100644
--- a/media/libaudioclient/IAudioPolicyService.cpp
+++ b/media/libaudioclient/IAudioPolicyService.cpp
@@ -198,7 +198,7 @@
         return static_cast <audio_io_handle_t> (reply.readInt32());
     }
 
-    status_t getOutputForAttr(const audio_attributes_t *attr,
+    status_t getOutputForAttr(audio_attributes_t *attr,
                               audio_io_handle_t *output,
                               audio_session_t session,
                               audio_stream_type_t *stream,
@@ -212,38 +212,27 @@
         {
             Parcel data, reply;
             data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
-            if (attr == NULL) {
-                if (stream == NULL) {
-                    ALOGE("getOutputForAttr(): NULL audio attributes and stream type");
-                    return BAD_VALUE;
-                }
-                if (*stream == AUDIO_STREAM_DEFAULT) {
-                    ALOGE("getOutputForAttr unspecified stream type");
-                    return BAD_VALUE;
-                }
-            }
-            if (output == NULL) {
-                ALOGE("getOutputForAttr NULL output - shouldn't happen");
+            if (attr == nullptr) {
+                ALOGE("%s NULL audio attributes", __func__);
                 return BAD_VALUE;
             }
-            if (selectedDeviceId == NULL) {
-                ALOGE("getOutputForAttr NULL selectedDeviceId - shouldn't happen");
+            if (output == nullptr) {
+                ALOGE("%s NULL output - shouldn't happen", __func__);
                 return BAD_VALUE;
             }
-            if (portId == NULL) {
-                ALOGE("getOutputForAttr NULL portId - shouldn't happen");
+            if (selectedDeviceId == nullptr) {
+                ALOGE("%s NULL selectedDeviceId - shouldn't happen", __func__);
                 return BAD_VALUE;
             }
-            if (secondaryOutputs == NULL) {
-                ALOGE("getOutputForAttr NULL secondaryOutputs - shouldn't happen");
+            if (portId == nullptr) {
+                ALOGE("%s NULL portId - shouldn't happen", __func__);
                 return BAD_VALUE;
             }
-            if (attr == NULL) {
-                data.writeInt32(0);
-            } else {
-                data.writeInt32(1);
-                data.write(attr, sizeof(audio_attributes_t));
+            if (secondaryOutputs == nullptr) {
+                ALOGE("%s NULL secondaryOutputs - shouldn't happen", __func__);
+                return BAD_VALUE;
             }
+            data.write(attr, sizeof(audio_attributes_t));
             data.writeInt32(session);
             if (stream == NULL) {
                 data.writeInt32(0);
@@ -265,6 +254,10 @@
             if (status != NO_ERROR) {
                 return status;
             }
+            status = (status_t)reply.read(&attr, sizeof(audio_attributes_t));
+            if (status != NO_ERROR) {
+                return status;
+            }
             *output = (audio_io_handle_t)reply.readInt32();
             audio_stream_type_t lStream = (audio_stream_type_t)reply.readInt32();
             if (stream != NULL) {
@@ -1449,12 +1442,12 @@
 
         case GET_OUTPUT_FOR_ATTR: {
             CHECK_INTERFACE(IAudioPolicyService, data, reply);
-            audio_attributes_t attr = {};
-            bool hasAttributes = data.readInt32() != 0;
-            if (hasAttributes) {
-                data.read(&attr, sizeof(audio_attributes_t));
-                sanetizeAudioAttributes(&attr);
+            audio_attributes_t attr = AUDIO_ATTRIBUTES_INITIALIZER;
+            status_t status = data.read(&attr, sizeof(audio_attributes_t));
+            if (status != NO_ERROR) {
+                return status;
             }
+            sanetizeAudioAttributes(&attr);
             audio_session_t session = (audio_session_t)data.readInt32();
             audio_stream_type_t stream = AUDIO_STREAM_DEFAULT;
             bool hasStream = data.readInt32() != 0;
@@ -1472,11 +1465,15 @@
             audio_port_handle_t portId = (audio_port_handle_t)data.readInt32();
             audio_io_handle_t output = 0;
             std::vector<audio_io_handle_t> secondaryOutputs;
-            status_t status = getOutputForAttr(hasAttributes ? &attr : NULL,
+            status = getOutputForAttr(&attr,
                     &output, session, &stream, pid, uid,
                     &config,
                     flags, &selectedDeviceId, &portId, &secondaryOutputs);
             reply->writeInt32(status);
+            status = reply->write(&attr, sizeof(audio_attributes_t));
+            if (status != NO_ERROR) {
+                return status;
+            }
             reply->writeInt32(output);
             reply->writeInt32(stream);
             reply->writeInt32(selectedDeviceId);
diff --git a/media/libaudioclient/include/media/AudioSystem.h b/media/libaudioclient/include/media/AudioSystem.h
index f79ec21..56c69f6 100644
--- a/media/libaudioclient/include/media/AudioSystem.h
+++ b/media/libaudioclient/include/media/AudioSystem.h
@@ -223,7 +223,7 @@
     static status_t setForceUse(audio_policy_force_use_t usage, audio_policy_forced_cfg_t config);
     static audio_policy_forced_cfg_t getForceUse(audio_policy_force_use_t usage);
 
-    static status_t getOutputForAttr(const audio_attributes_t *attr,
+    static status_t getOutputForAttr(audio_attributes_t *attr,
                                      audio_io_handle_t *output,
                                      audio_session_t session,
                                      audio_stream_type_t *stream,
diff --git a/media/libaudioclient/include/media/IAudioPolicyService.h b/media/libaudioclient/include/media/IAudioPolicyService.h
index b639044..33ab1f9 100644
--- a/media/libaudioclient/include/media/IAudioPolicyService.h
+++ b/media/libaudioclient/include/media/IAudioPolicyService.h
@@ -57,7 +57,7 @@
                                     audio_policy_forced_cfg_t config) = 0;
     virtual audio_policy_forced_cfg_t getForceUse(audio_policy_force_use_t usage) = 0;
     virtual audio_io_handle_t getOutput(audio_stream_type_t stream) = 0;
-    virtual status_t getOutputForAttr(const audio_attributes_t *attr,
+    virtual status_t getOutputForAttr(audio_attributes_t *attr,
                                       audio_io_handle_t *output,
                                       audio_session_t session,
                                       audio_stream_type_t *stream,
diff --git a/media/utils/ServiceUtilities.cpp b/media/utils/ServiceUtilities.cpp
index 768cd1e..16fdeaf 100644
--- a/media/utils/ServiceUtilities.cpp
+++ b/media/utils/ServiceUtilities.cpp
@@ -35,6 +35,8 @@
 namespace android {
 
 static const String16 sAndroidPermissionRecordAudio("android.permission.RECORD_AUDIO");
+static const String16 sModifyPhoneState("android.permission.MODIFY_PHONE_STATE");
+static const String16 sModifyAudioRouting("android.permission.MODIFY_AUDIO_ROUTING");
 
 static String16 resolveCallingPackage(PermissionController& permissionController,
         const String16& opPackageName, uid_t uid) {
@@ -162,9 +164,8 @@
 }
 
 bool modifyAudioRoutingAllowed() {
-    static const String16 sModifyAudioRoutingAllowed("android.permission.MODIFY_AUDIO_ROUTING");
     // IMPORTANT: Use PermissionCache - not a runtime permission and may not change.
-    bool ok = PermissionCache::checkCallingPermission(sModifyAudioRoutingAllowed);
+    bool ok = PermissionCache::checkCallingPermission(sModifyAudioRouting);
     if (!ok) ALOGE("android.permission.MODIFY_AUDIO_ROUTING");
     return ok;
 }
@@ -200,9 +201,19 @@
 }
 
 bool modifyPhoneStateAllowed(pid_t pid, uid_t uid) {
-    static const String16 sModifyPhoneState("android.permission.MODIFY_PHONE_STATE");
     bool ok = PermissionCache::checkPermission(sModifyPhoneState, pid, uid);
-    if (!ok) ALOGE("Request requires android.permission.MODIFY_PHONE_STATE");
+    ALOGE_IF(!ok, "Request requires %s", String8(sModifyPhoneState).c_str());
+    return ok;
+}
+
+// privileged behavior needed by Dialer, Settings, SetupWizard and CellBroadcastReceiver
+bool bypassInterruptionPolicyAllowed(pid_t pid, uid_t uid) {
+    static const String16 sWriteSecureSettings("android.permission.WRITE_SECURE_SETTINGS");
+    bool ok = PermissionCache::checkPermission(sModifyPhoneState, pid, uid)
+        || PermissionCache::checkPermission(sWriteSecureSettings, pid, uid)
+        || PermissionCache::checkPermission(sModifyAudioRouting, pid, uid);
+    ALOGE_IF(!ok, "Request requires %s or %s",
+             String8(sModifyPhoneState).c_str(), String8(sWriteSecureSettings).c_str());
     return ok;
 }
 
diff --git a/media/utils/include/mediautils/ServiceUtilities.h b/media/utils/include/mediautils/ServiceUtilities.h
index c5fe05f..2a6e609 100644
--- a/media/utils/include/mediautils/ServiceUtilities.h
+++ b/media/utils/include/mediautils/ServiceUtilities.h
@@ -81,6 +81,8 @@
 bool modifyDefaultAudioEffectsAllowed();
 bool dumpAllowed();
 bool modifyPhoneStateAllowed(pid_t pid, uid_t uid);
+bool bypassInterruptionPolicyAllowed(pid_t pid, uid_t uid);
+
 status_t checkIMemory(const sp<IMemory>& iMemory);
 
 class MediaPackageManager {