Use DeviceIdVector for outputs in Audio Policy

Use DeviceIdVector for output in Audio Policy.

Bug: 367816690
Test: atest audiopolicy_tests
Test: adb shell /data/fuzz/arm64/audiopolicy_fuzzer/audiopolicy_fuzzer
Flag: android.media.audio.routed_device_ids
Change-Id: If2144348ff69e75fd4e6c339848d7d161ef5611d
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index 54ef5d5..083b81b 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -1262,7 +1262,7 @@
         uid_t uid,
         audio_config_t *config,
         audio_output_flags_t *flags,
-        audio_port_handle_t *selectedDeviceId,
+        DeviceIdVector *selectedDeviceIds,
         bool *isRequestedDeviceForExclusiveUse,
         std::vector<sp<AudioPolicyMix>> *secondaryMixes,
         output_type_t *outputType,
@@ -1270,7 +1270,8 @@
         bool *isBitPerfect)
 {
     DeviceVector outputDevices;
-    const audio_port_handle_t requestedPortId = *selectedDeviceId;
+    audio_port_handle_t requestedPortId = getFirstDeviceId(*selectedDeviceIds);
+    selectedDeviceIds->clear();
     DeviceVector msdDevices = getMsdAudioOutDevices();
     const sp<DeviceDescriptor> requestedDevice =
         mAvailableOutputDevices.getDeviceFromId(requestedPortId);
@@ -1347,8 +1348,9 @@
         if (policyDesc != nullptr) {
             policyDesc->mPolicyMix = primaryMix;
             *output = policyDesc->mIoHandle;
-            *selectedDeviceId = policyMixDevice != nullptr ? policyMixDevice->getId()
-                                                           : AUDIO_PORT_HANDLE_NONE;
+            if (policyMixDevice != nullptr) {
+                selectedDeviceIds->push_back(policyMixDevice->getId());
+            }
             if ((policyDesc->mFlags & AUDIO_OUTPUT_FLAG_DIRECT) != AUDIO_OUTPUT_FLAG_DIRECT) {
                 // Remove direct flag as it is not on a direct output.
                 *flags = (audio_output_flags_t) (*flags & ~AUDIO_OUTPUT_FLAG_DIRECT);
@@ -1485,11 +1487,13 @@
         return INVALID_OPERATION;
     }
 
-    *selectedDeviceId = getFirstDeviceId(outputDevices);
     for (auto &outputDevice : outputDevices) {
-        if (outputDevice->getId() == mConfig->getDefaultOutputDevice()->getId()) {
-            *selectedDeviceId = outputDevice->getId();
-            break;
+        if (std::find(selectedDeviceIds->begin(), selectedDeviceIds->end(),
+                      outputDevice->getId()) == selectedDeviceIds->end()) {
+            selectedDeviceIds->push_back(outputDevice->getId());
+            if (outputDevice->getId() == mConfig->getDefaultOutputDevice()->getId()) {
+                std::swap(selectedDeviceIds->front(), selectedDeviceIds->back());
+            }
         }
     }
 
@@ -1499,7 +1503,8 @@
         *outputType = API_OUTPUT_LEGACY;
     }
 
-    ALOGV("%s returns output %d selectedDeviceId %d", __func__, *output, *selectedDeviceId);
+    ALOGV("%s returns output %d selectedDeviceIds %s", __func__, *output,
+            toString(*selectedDeviceIds).c_str());
 
     return NO_ERROR;
 }
@@ -1511,7 +1516,7 @@
                                               const AttributionSourceState& attributionSource,
                                               audio_config_t *config,
                                               audio_output_flags_t *flags,
-                                              audio_port_handle_t *selectedDeviceId,
+                                              DeviceIdVector *selectedDeviceIds,
                                               audio_port_handle_t *portId,
                                               std::vector<audio_io_handle_t> *secondaryOutputs,
                                               output_type_t *outputType,
@@ -1526,20 +1531,22 @@
     }
     const uid_t uid = VALUE_OR_RETURN_STATUS(
         aidl2legacy_int32_t_uid_t(attributionSource.uid));
-    const audio_port_handle_t requestedPortId = *selectedDeviceId;
     audio_attributes_t resultAttr;
     bool isRequestedDeviceForExclusiveUse = false;
     std::vector<sp<AudioPolicyMix>> secondaryMixes;
-    const sp<DeviceDescriptor> requestedDevice =
-      mAvailableOutputDevices.getDeviceFromId(requestedPortId);
+    DeviceIdVector requestedDeviceIds = *selectedDeviceIds;
 
     // Prevent from storing invalid requested device id in clients
-    const audio_port_handle_t sanitizedRequestedPortId =
-      requestedDevice != nullptr ? requestedPortId : AUDIO_PORT_HANDLE_NONE;
-    *selectedDeviceId = sanitizedRequestedPortId;
+    DeviceIdVector sanitizedRequestedPortIds;
+    for (auto deviceId : *selectedDeviceIds) {
+        if (mAvailableOutputDevices.getDeviceFromId(deviceId) != nullptr) {
+            sanitizedRequestedPortIds.push_back(deviceId);
+        }
+    }
+    *selectedDeviceIds = sanitizedRequestedPortIds;
 
     status_t status = getOutputForAttrInt(&resultAttr, output, session, attr, stream, uid,
-            config, flags, selectedDeviceId, &isRequestedDeviceForExclusiveUse,
+            config, flags, selectedDeviceIds, &isRequestedDeviceForExclusiveUse,
             secondaryOutputs != nullptr ? &secondaryMixes : nullptr, outputType, isSpatialized,
             isBitPerfect);
     if (status != NO_ERROR) {
@@ -1564,9 +1571,10 @@
     *portId = PolicyAudioPort::getNextUniqueId();
 
     sp<SwAudioOutputDescriptor> outputDesc = mOutputs.valueFor(*output);
+    // TODO(b/367816690): Add device id sets to TrackClientDescriptor
     sp<TrackClientDescriptor> clientDesc =
         new TrackClientDescriptor(*portId, uid, session, resultAttr, clientConfig,
-                                  sanitizedRequestedPortId, *stream,
+                                  getFirstDeviceId(sanitizedRequestedPortIds), *stream,
                                   mEngine->getProductStrategyForAttributes(resultAttr),
                                   toVolumeSource(resultAttr),
                                   *flags, isRequestedDeviceForExclusiveUse,
@@ -1577,8 +1585,9 @@
     *volume = Volume::DbToAmpl(outputDesc->getCurVolume(toVolumeSource(resultAttr)));
     *muted = outputDesc->isMutedByGroup(toVolumeSource(resultAttr));
 
-    ALOGV("%s() returns output %d requestedPortId %d selectedDeviceId %d for port ID %d", __func__,
-          *output, requestedPortId, *selectedDeviceId, *portId);
+    ALOGV("%s() returns output %d requestedPortIds %s selectedDeviceIds %s for port ID %d",
+          __func__, *output, toString(requestedDeviceIds).c_str(),
+          toString(*selectedDeviceIds).c_str(), *portId);
 
     return NO_ERROR;
 }
@@ -5596,14 +5605,14 @@
                                     : audio_channel_mask_in_to_out(sourceMask);
                     config.format = sourceDesc->config().format;
                     audio_output_flags_t flags = AUDIO_OUTPUT_FLAG_NONE;
-                    audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE;
+                    DeviceIdVector selectedDeviceIds;
                     bool isRequestedDeviceForExclusiveUse = false;
                     output_type_t outputType;
                     bool isSpatialized;
                     bool isBitPerfect;
                     getOutputForAttrInt(&resultAttr, &output, AUDIO_SESSION_NONE, &attributes,
                                         &stream, sourceDesc->uid(), &config, &flags,
-                                        &selectedDeviceId, &isRequestedDeviceForExclusiveUse,
+                                        &selectedDeviceIds, &isRequestedDeviceForExclusiveUse,
                                         nullptr, &outputType, &isSpatialized, &isBitPerfect);
                     if (output == AUDIO_IO_HANDLE_NONE) {
                         ALOGV("%s no output for device %s",
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.h b/services/audiopolicy/managerdefault/AudioPolicyManager.h
index 1ca0c32..e0cafd4 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.h
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.h
@@ -123,7 +123,7 @@
                                   const AttributionSourceState& attributionSource,
                                   audio_config_t *config,
                                   audio_output_flags_t *flags,
-                                  audio_port_handle_t *selectedDeviceId,
+                                  DeviceIdVector *selectedDeviceIds,
                                   audio_port_handle_t *portId,
                                   std::vector<audio_io_handle_t> *secondaryOutputs,
                                   output_type_t *outputType,
@@ -893,15 +893,7 @@
             return mAvailableInputDevices.getDevicesFromHwModule(
                     mPrimaryOutput->getModuleHandle());
         }
-        /**
-         * @brief getFirstDeviceId of the Device Vector
-         * @return if the collection is not empty, it returns the first device Id,
-         *         otherwise AUDIO_PORT_HANDLE_NONE
-         */
-        audio_port_handle_t getFirstDeviceId(const DeviceVector &devices) const
-        {
-            return (devices.size() > 0) ? devices.itemAt(0)->getId() : AUDIO_PORT_HANDLE_NONE;
-        }
+
         String8 getFirstDeviceAddress(const DeviceVector &devices) const
         {
             return (devices.size() > 0) ?
@@ -1142,7 +1134,7 @@
                 uid_t uid,
                 audio_config_t *config,
                 audio_output_flags_t *flags,
-                audio_port_handle_t *selectedDeviceId,
+                DeviceIdVector *selectedDeviceIds,
                 bool *isRequestedDeviceForExclusiveUse,
                 std::vector<sp<AudioPolicyMix>> *secondaryMixes,
                 output_type_t *outputType,