APM: support querying of audio playback routing

  Add support for querying the audio devices used for playback
routing for the given audio attributes.
  Take into account registered dynamic policies but disregard
secondary output descriptors as they are used for playback
capture.

Bug: 144440677
Test: atest AudioServiceHostTest
Change-Id: I102c57b432b044dc6b0ead49e0a30d8e9094411d
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index d4d59d6..23cd5c3 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -971,19 +971,21 @@
     if (usePrimaryOutputFromPolicyMixes) {
         *output = policyDesc->mIoHandle;
         sp<AudioPolicyMix> mix = policyDesc->mPolicyMix.promote();
-        sp<DeviceDescriptor> deviceDesc =
-                mAvailableOutputDevices.getDevice(mix->mDeviceType,
-                                                  mix->mDeviceAddress,
-                                                  AUDIO_FORMAT_DEFAULT);
-        *selectedDeviceId = deviceDesc != 0 ? deviceDesc->getId() : AUDIO_PORT_HANDLE_NONE;
+        if (mix != nullptr) {
+            sp<DeviceDescriptor> deviceDesc =
+                    mAvailableOutputDevices.getDevice(mix->mDeviceType,
+                                                      mix->mDeviceAddress,
+                                                      AUDIO_FORMAT_DEFAULT);
+            *selectedDeviceId = deviceDesc != 0 ? deviceDesc->getId() : AUDIO_PORT_HANDLE_NONE;
 
-        ALOGV("getOutputForAttr() returns output %d", *output);
-        if (resultAttr->usage == AUDIO_USAGE_VIRTUAL_SOURCE) {
-            *outputType = API_OUT_MIX_PLAYBACK;
-        } else {
-            *outputType = API_OUTPUT_LEGACY;
+            ALOGV("getOutputForAttr() returns output %d", *output);
+            if (resultAttr->usage == AUDIO_USAGE_VIRTUAL_SOURCE) {
+                *outputType = API_OUT_MIX_PLAYBACK;
+            } else {
+                *outputType = API_OUTPUT_LEGACY;
+            }
+            return NO_ERROR;
         }
-        return NO_ERROR;
     }
     // Virtual sources must always be dynamicaly or explicitly routed
     if (resultAttr->usage == AUDIO_USAGE_VIRTUAL_SOURCE) {
@@ -1638,7 +1640,7 @@
     DeviceVector devices;
     sp<AudioPolicyMix> policyMix = outputDesc->mPolicyMix.promote();
     const char *address = NULL;
-    if (policyMix != NULL) {
+    if (policyMix != nullptr) {
         audio_devices_t newDeviceType;
         address = policyMix->mDeviceAddress.string();
         if ((policyMix->mRouteFlags & MIX_ROUTE_FLAG_LOOP_BACK) == MIX_ROUTE_FLAG_LOOP_BACK) {
@@ -1820,7 +1822,7 @@
             sp<AudioPolicyMix> policyMix = outputDesc->mPolicyMix.promote();
             if (isSingleDeviceType(
                     outputDesc->devices().types(), &audio_is_remote_submix_device) &&
-                policyMix != NULL &&
+                policyMix != nullptr &&
                 policyMix->mMixType == MIX_TYPE_RECORDERS) {
                 setDeviceConnectionStateInt(AUDIO_DEVICE_IN_REMOTE_SUBMIX,
                                             AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE,
@@ -2267,7 +2269,7 @@
     if (status == NO_ERROR && inputDesc->activeCount() == 1) {
         sp<AudioPolicyMix> policyMix = inputDesc->mPolicyMix.promote();
         // if input maps to a dynamic policy with an activity listener, notify of state change
-        if ((policyMix != NULL)
+        if ((policyMix != nullptr)
                 && ((policyMix->mCbFlags & AudioMix::kCbFlagNotifyActivity) != 0)) {
             mpClientInterface->onDynamicPolicyMixStateUpdate(policyMix->mDeviceAddress,
                     MIX_STATE_MIXING);
@@ -2284,7 +2286,7 @@
         // For remote submix (a virtual device), we open only one input per capture request.
         if (audio_is_remote_submix_device(inputDesc->getDeviceType())) {
             String8 address = String8("");
-            if (policyMix == NULL) {
+            if (policyMix == nullptr) {
                 address = String8("0");
             } else if (policyMix->mMixType == MIX_TYPE_PLAYERS) {
                 address = policyMix->mDeviceAddress;
@@ -2331,7 +2333,7 @@
     } else {
         sp<AudioPolicyMix> policyMix = inputDesc->mPolicyMix.promote();
         // if input maps to a dynamic policy with an activity listener, notify of state change
-        if ((policyMix != NULL)
+        if ((policyMix != nullptr)
                 && ((policyMix->mCbFlags & AudioMix::kCbFlagNotifyActivity) != 0)) {
             mpClientInterface->onDynamicPolicyMixStateUpdate(policyMix->mDeviceAddress,
                     MIX_STATE_IDLE);
@@ -2341,7 +2343,7 @@
         // used by a policy mix of type MIX_TYPE_RECORDERS
         if (audio_is_remote_submix_device(inputDesc->getDeviceType())) {
             String8 address = String8("");
-            if (policyMix == NULL) {
+            if (policyMix == nullptr) {
                 address = String8("0");
             } else if (policyMix->mMixType == MIX_TYPE_PLAYERS) {
                 address = policyMix->mDeviceAddress;
@@ -5426,6 +5428,35 @@
     return deviceTypesToBitMask(devices.types());
 }
 
+status_t AudioPolicyManager::getDevicesForAttributes(
+        const audio_attributes_t &attr, AudioDeviceTypeAddrVector *devices) {
+    if (devices == nullptr) {
+        return BAD_VALUE;
+    }
+    // check dynamic policies but only for primary descriptors (secondary not used for audible
+    // audio routing, only used for duplication for playback capture)
+    sp<SwAudioOutputDescriptor> policyDesc;
+    status_t status = mPolicyMixes.getOutputForAttr(attr, 0 /*uid unknown here*/,
+            AUDIO_OUTPUT_FLAG_NONE, policyDesc, nullptr);
+    if (status != OK) {
+        return status;
+    }
+    if (policyDesc != nullptr) {
+        sp<AudioPolicyMix> mix = policyDesc->mPolicyMix.promote();
+        if (mix != nullptr) {
+            AudioDeviceTypeAddr device(mix->mDeviceType, mix->mDeviceAddress.c_str());
+            devices->push_back(device);
+            return NO_ERROR;
+        }
+    }
+
+    DeviceVector curDevices = mEngine->getOutputDevicesForAttributes(attr, nullptr, false);
+    for (const auto& device : curDevices) {
+        devices->push_back(device->getDeviceTypeAddr());
+    }
+    return NO_ERROR;
+}
+
 void AudioPolicyManager::handleNotificationRoutingForStream(audio_stream_type_t stream) {
     switch(stream) {
     case AUDIO_STREAM_MUSIC: