audiopolicy: common: add several helper function on DeviceDesc

-Add another DeviceVector constructor to simplify usage
-report tagname as port name
-migrate API from apm
-search/filter helpers

Test: Audio smoke tests.
Test: CTS tests for AudioRecord, AudioTrack and AudioEffect

Change-Id: Ie37a2d9db2e8a15a37743e7129159fa77a4c6b51
Signed-off-by: François Gaffie <francois.gaffie@renault.com>
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioPort.h b/services/audiopolicy/common/managerdefinitions/include/AudioPort.h
index ebb9352..bb9cad8 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioPort.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioPort.h
@@ -116,6 +116,7 @@
     audio_module_handle_t getModuleHandle() const;
     uint32_t getModuleVersionMajor() const;
     const char *getModuleName() const;
+    sp<HwModule> getModule() const { return mModule; }
 
     bool useInputChannelMask() const
     {
@@ -137,12 +138,12 @@
     void log(const char* indent) const;
 
     AudioGainCollection mGains; // gain controllers
-    sp<HwModule> mModule;                 // audio HW module exposing this I/O stream
 
 private:
     void pickChannelMask(audio_channel_mask_t &channelMask, const ChannelsVector &channelMasks) const;
     void pickSamplingRate(uint32_t &rate,const SampleRateVector &samplingRates) const;
 
+    sp<HwModule> mModule;                 // audio HW module exposing this I/O stream
     String8  mName;
     audio_port_type_t mType;
     audio_port_role_t mRole;
diff --git a/services/audiopolicy/common/managerdefinitions/include/DeviceDescriptor.h b/services/audiopolicy/common/managerdefinitions/include/DeviceDescriptor.h
index 6f99bf3..d02123c 100644
--- a/services/audiopolicy/common/managerdefinitions/include/DeviceDescriptor.h
+++ b/services/audiopolicy/common/managerdefinitions/include/DeviceDescriptor.h
@@ -39,6 +39,8 @@
     virtual const String8 getTagName() const { return mTagName; }
 
     audio_devices_t type() const { return mDeviceType; }
+    String8 address() const { return mAddress; }
+    void setAddress(const String8 &address) { mAddress = address; }
 
     const FormatVector& encodedFormats() const { return mEncodedFormats; }
 
@@ -57,39 +59,113 @@
     audio_port_handle_t getId() const;
     void dump(String8 *dst, int spaces, int index, bool verbose = true) const;
     void log() const;
-
-    String8 mAddress;
+    std::string toString() const;
 
 private:
+    String8 mAddress{""};
     String8 mTagName; // Unique human readable identifier for a device port found in conf file.
     audio_devices_t     mDeviceType;
     FormatVector        mEncodedFormats;
-    audio_port_handle_t mId;
-
-friend class DeviceVector;
+    audio_port_handle_t mId = AUDIO_PORT_HANDLE_NONE;
 };
 
 class DeviceVector : public SortedVector<sp<DeviceDescriptor> >
 {
 public:
     DeviceVector() : SortedVector(), mDeviceTypes(AUDIO_DEVICE_NONE) {}
+    explicit DeviceVector(const sp<DeviceDescriptor>& item) : DeviceVector()
+    {
+        add(item);
+    }
 
     ssize_t add(const sp<DeviceDescriptor>& item);
     void add(const DeviceVector &devices);
     ssize_t remove(const sp<DeviceDescriptor>& item);
+    void remove(const DeviceVector &devices);
     ssize_t indexOf(const sp<DeviceDescriptor>& item) const;
 
     audio_devices_t types() const { return mDeviceTypes; }
 
     // If 'address' is empty, a device with a non-empty address may be returned
     // if there is no device with the specified 'type' and empty address.
-    sp<DeviceDescriptor> getDevice(audio_devices_t type, const String8 &address) const;
+    sp<DeviceDescriptor> getDevice(audio_devices_t type, const String8 &address = {}) const;
     DeviceVector getDevicesFromTypeMask(audio_devices_t types) const;
+
+    /**
+     * @brief getDeviceFromId
+     * @param id of the DeviceDescriptor to seach (aka Port handle).
+     * @return DeviceDescriptor associated to port id if found, nullptr otherwise. If the id is
+     * equal to AUDIO_PORT_HANDLE_NONE, it also returns a nullptr.
+     */
     sp<DeviceDescriptor> getDeviceFromId(audio_port_handle_t id) const;
     sp<DeviceDescriptor> getDeviceFromTagName(const String8 &tagName) const;
     DeviceVector getDevicesFromHwModule(audio_module_handle_t moduleHandle) const;
     audio_devices_t getDeviceTypesFromHwModule(audio_module_handle_t moduleHandle) const;
 
+    bool contains(const sp<DeviceDescriptor>& item) const { return indexOf(item) >= 0; }
+
+    /**
+     * @brief containsAtLeastOne
+     * @param devices vector of devices to check against.
+     * @return true if the DeviceVector contains at list one of the devices from the given vector.
+     */
+    bool containsAtLeastOne(const DeviceVector &devices) const;
+
+    /**
+     * @brief containsAllDevices
+     * @param devices vector of devices to check against.
+     * @return true if the DeviceVector contains all the devices from the given vector
+     */
+    bool containsAllDevices(const DeviceVector &devices) const;
+
+    /**
+     * @brief filter the devices supported by this collection against another collection
+     * @param devices to filter against
+     * @return
+     */
+    DeviceVector filter(const DeviceVector &devices) const;
+
+    /**
+     * @brief merge two vectors. As SortedVector Implementation is buggy (it does not check the size
+     * of the destination vector, only of the source, it provides a safe implementation
+     * @param devices source device vector to merge with
+     * @return size of the merged vector.
+     */
+    ssize_t merge(const DeviceVector &devices)
+    {
+        if (isEmpty()) {
+            add(devices);
+            return size();
+        }
+        return SortedVector::merge(devices);
+    }
+
+    /**
+     * @brief operator == DeviceVector are equals if all the DeviceDescriptor can be found (aka
+     * DeviceDescriptor with same type and address) and the vector has same size.
+     * @param right DeviceVector to compare to.
+     * @return true if right contains the same device and has the same size.
+     */
+    bool operator==(const DeviceVector &right) const
+    {
+        if (size() != right.size()) {
+            return false;
+        }
+        for (const auto &device : *this) {
+            if (right.indexOf(device) < 0) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    bool operator!=(const DeviceVector &right) const
+    {
+        return !operator==(right);
+    }
+
+    std::string toString() const;
+
     void dump(String8 *dst, const String8 &tag, int spaces = 0, bool verbose = true) const;
 
 private:
diff --git a/services/audiopolicy/common/managerdefinitions/include/IOProfile.h b/services/audiopolicy/common/managerdefinitions/include/IOProfile.h
index 8ff8238..ca6ca56 100644
--- a/services/audiopolicy/common/managerdefinitions/include/IOProfile.h
+++ b/services/audiopolicy/common/managerdefinitions/include/IOProfile.h
@@ -88,7 +88,7 @@
 
     bool supportDeviceAddress(const String8 &address) const
     {
-        return mSupportedDevices[0]->mAddress == address;
+        return mSupportedDevices[0]->address() == address;
     }
 
     // chose first device present in mSupportedDevices also part of deviceType
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
index 4ce6b08..97504ab 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
@@ -698,8 +698,8 @@
     sp<SwAudioOutputDescriptor> primaryOutput = getPrimaryOutput();
 
     if ((primaryOutput != NULL) && (primaryOutput->mProfile != NULL)
-        && (primaryOutput->mProfile->mModule != NULL)) {
-        sp<HwModule> primaryHwModule = primaryOutput->mProfile->mModule;
+        && (primaryOutput->mProfile->getModule() != NULL)) {
+        sp<HwModule> primaryHwModule = primaryOutput->mProfile->getModule();
         Vector <sp<IOProfile>> primaryHwModuleOutputProfiles =
                                    primaryHwModule->getOutputProfiles();
         for (size_t i = 0; i < primaryHwModuleOutputProfiles.size(); i++) {
diff --git a/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp
index 9e5f944..04cbcd1 100644
--- a/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp
@@ -35,7 +35,7 @@
     AudioPort(String8(""), AUDIO_PORT_TYPE_DEVICE,
               audio_is_output_device(type) ? AUDIO_PORT_ROLE_SINK :
                                              AUDIO_PORT_ROLE_SOURCE),
-    mAddress(""), mTagName(tagName), mDeviceType(type), mEncodedFormats(encodedFormats), mId(0)
+    mTagName(tagName), mDeviceType(type), mEncodedFormats(encodedFormats)
 {
     if (type == AUDIO_DEVICE_IN_REMOTE_SUBMIX || type == AUDIO_DEVICE_OUT_REMOTE_SUBMIX ) {
         mAddress = String8("0");
@@ -132,6 +132,13 @@
     return ret;
 }
 
+void DeviceVector::remove(const DeviceVector &devices)
+{
+    for (const auto& device : devices) {
+        remove(device);
+    }
+}
+
 DeviceVector DeviceVector::getDevicesFromHwModule(audio_module_handle_t moduleHandle) const
 {
     DeviceVector devices;
@@ -159,9 +166,9 @@
     sp<DeviceDescriptor> device;
     for (size_t i = 0; i < size(); i++) {
         if (itemAt(i)->type() == type) {
-            if (address == "" || itemAt(i)->mAddress == address) {
+            if (address == "" || itemAt(i)->address() == address) {
                 device = itemAt(i);
-                if (itemAt(i)->mAddress == address) {
+                if (itemAt(i)->address() == address) {
                     break;
                 }
             }
@@ -174,9 +181,11 @@
 
 sp<DeviceDescriptor> DeviceVector::getDeviceFromId(audio_port_handle_t id) const
 {
-    for (const auto& device : *this) {
-        if (device->getId() == id) {
-            return device;
+    if (id != AUDIO_PORT_HANDLE_NONE) {
+        for (const auto& device : *this) {
+            if (device->getId() == id) {
+                return device;
+            }
         }
     }
     return nullptr;
@@ -188,8 +197,8 @@
     bool isOutput = audio_is_output_devices(type);
     type &= ~AUDIO_DEVICE_BIT_IN;
     for (size_t i = 0; (i < size()) && (type != AUDIO_DEVICE_NONE); i++) {
-        bool curIsOutput = audio_is_output_devices(itemAt(i)->mDeviceType);
-        audio_devices_t curType = itemAt(i)->mDeviceType & ~AUDIO_DEVICE_BIT_IN;
+        bool curIsOutput = audio_is_output_devices(itemAt(i)->type());
+        audio_devices_t curType = itemAt(i)->type() & ~AUDIO_DEVICE_BIT_IN;
         if ((isOutput == curIsOutput) && ((type & curType) != 0)) {
             devices.add(itemAt(i));
             type &= ~curType;
@@ -251,8 +260,7 @@
     // without the test?
     // This has been demonstrated to NOT be true (at start up)
     // ALOG_ASSERT(mModule != NULL);
-    dstConfig->ext.device.hw_module =
-            mModule != 0 ? mModule->getHandle() : AUDIO_MODULE_HANDLE_NONE;
+    dstConfig->ext.device.hw_module = getModuleHandle();
     (void)audio_utils_strlcpy_zerofill(dstConfig->ext.device.address, mAddress.string());
 }
 
@@ -263,7 +271,7 @@
     port->id = mId;
     toAudioPortConfig(&port->active_config);
     port->ext.device.type = mDeviceType;
-    port->ext.device.hw_module = mModule->getHandle();
+    port->ext.device.hw_module = getModuleHandle();
     (void)audio_utils_strlcpy_zerofill(port->ext.device.address, mAddress.string());
 }
 
@@ -294,6 +302,49 @@
     AudioPort::dump(dst, spaces, verbose);
 }
 
+std::string DeviceDescriptor::toString() const
+{
+    std::stringstream sstream;
+    sstream << "type:0x" << std::hex << type() << ",@:" << mAddress;
+    return sstream.str();
+}
+
+std::string DeviceVector::toString() const
+{
+    if (isEmpty()) {
+        return {"AUDIO_DEVICE_NONE"};
+    }
+    std::string result = {"{"};
+    for (const auto &device : *this) {
+        if (device != *begin()) {
+           result += ";";
+        }
+        result += device->toString();
+    }
+    return result + "}";
+}
+
+DeviceVector DeviceVector::filter(const DeviceVector &devices) const
+{
+    DeviceVector filteredDevices;
+    for (const auto &device : *this) {
+        if (devices.contains(device)) {
+            filteredDevices.add(device);
+        }
+    }
+    return filteredDevices;
+}
+
+bool DeviceVector::containsAtLeastOne(const DeviceVector &devices) const
+{
+    return !filter(devices).isEmpty();
+}
+
+bool DeviceVector::containsAllDevices(const DeviceVector &devices) const
+{
+    return filter(devices).size() == devices.size();
+}
+
 void DeviceDescriptor::log() const
 {
     std::string device;
diff --git a/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp b/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp
index 59ba479..80af88d 100644
--- a/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp
@@ -51,7 +51,7 @@
                                               config->sample_rate));
 
     sp<DeviceDescriptor> devDesc = new DeviceDescriptor(device);
-    devDesc->mAddress = address;
+    devDesc->setAddress(address);
     profile->addSupportedDevice(devDesc);
 
     return addOutputProfile(profile);
@@ -113,7 +113,7 @@
                                               config->sample_rate));
 
     sp<DeviceDescriptor> devDesc = new DeviceDescriptor(device);
-    devDesc->mAddress = address;
+    devDesc->setAddress(address);
     profile->addSupportedDevice(devDesc);
 
     ALOGV("addInputProfile() name %s rate %d mask 0x%08x",
@@ -296,7 +296,7 @@
 
     sp<DeviceDescriptor> devDesc = new DeviceDescriptor(device);
     devDesc->setName(String8(device_name));
-    devDesc->mAddress = address;
+    devDesc->setAddress(address);
     return devDesc;
 }
 
diff --git a/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp b/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp
index 930171f..1154654 100644
--- a/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp
@@ -516,7 +516,7 @@
     std::string address = getXmlAttribute(cur, Attributes::address);
     if (!address.empty()) {
         ALOGV("%s: address=%s for %s", __func__, address.c_str(), name.c_str());
-        deviceDesc->mAddress = String8(address.c_str());
+        deviceDesc->setAddress(String8(address.c_str()));
     }
 
     AudioProfileTraits::Collection profiles;
@@ -535,7 +535,7 @@
         return Status::fromStatusT(status);
     }
     ALOGV("%s: adding device tag %s type %08x address %s", __func__,
-          deviceDesc->getName().string(), type, deviceDesc->mAddress.string());
+          deviceDesc->getName().string(), type, deviceDesc->address().string());
     return deviceDesc;
 }
 
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index ec1b9ea..64a2b8a 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -149,13 +149,13 @@
 
             // Before checking outputs, broadcast connect event to allow HAL to retrieve dynamic
             // parameters on newly connected devices (instead of opening the outputs...)
-            broadcastDeviceConnectionState(device, state, devDesc->mAddress);
+            broadcastDeviceConnectionState(device, state, devDesc->address());
 
-            if (checkOutputsForDevice(devDesc, state, outputs, devDesc->mAddress) != NO_ERROR) {
+            if (checkOutputsForDevice(devDesc, state, outputs, devDesc->address()) != NO_ERROR) {
                 mAvailableOutputDevices.remove(devDesc);
 
                 broadcastDeviceConnectionState(device, AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE,
-                                               devDesc->mAddress);
+                                               devDesc->address());
                 return INVALID_OPERATION;
             }
             // Propagate device availability to Engine
@@ -178,12 +178,12 @@
             ALOGV("setDeviceConnectionState() disconnecting output device %x", device);
 
             // Send Disconnect to HALs
-            broadcastDeviceConnectionState(device, state, devDesc->mAddress);
+            broadcastDeviceConnectionState(device, state, devDesc->address());
 
             // remove device from available output devices
             mAvailableOutputDevices.remove(devDesc);
 
-            checkOutputsForDevice(devDesc, state, outputs, devDesc->mAddress);
+            checkOutputsForDevice(devDesc, state, outputs, devDesc->address());
 
             // Propagate device availability to Engine
             mEngine->setDeviceConnectionState(devDesc, state);
@@ -265,11 +265,11 @@
 
             // Before checking intputs, broadcast connect event to allow HAL to retrieve dynamic
             // parameters on newly connected devices (instead of opening the inputs...)
-            broadcastDeviceConnectionState(device, state, devDesc->mAddress);
+            broadcastDeviceConnectionState(device, state, devDesc->address());
 
-            if (checkInputsForDevice(devDesc, state, inputs, devDesc->mAddress) != NO_ERROR) {
+            if (checkInputsForDevice(devDesc, state, inputs, devDesc->address()) != NO_ERROR) {
                 broadcastDeviceConnectionState(device, AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE,
-                                               devDesc->mAddress);
+                                               devDesc->address());
                 return INVALID_OPERATION;
             }
 
@@ -294,9 +294,9 @@
             ALOGV("setDeviceConnectionState() disconnecting input device %x", device);
 
             // Set Disconnect to HALs
-            broadcastDeviceConnectionState(device, state, devDesc->mAddress);
+            broadcastDeviceConnectionState(device, state, devDesc->address());
 
-            checkInputsForDevice(devDesc, state, inputs, devDesc->mAddress);
+            checkInputsForDevice(devDesc, state, inputs, devDesc->address());
             mAvailableInputDevices.remove(devDesc);
 
             // Propagate device availability to Engine
@@ -910,8 +910,7 @@
     }
 
     outputDevices = mAvailableOutputDevices.getDevicesFromTypeMask(device);
-    *selectedDeviceId = outputDevices.size() > 0 ? outputDevices.itemAt(0)->getId()
-            : AUDIO_PORT_HANDLE_NONE;
+    *selectedDeviceId = getFirstDeviceId(outputDevices);
 
     ALOGV("%s returns output %d selectedDeviceId %d", __func__, *output, *selectedDeviceId);
 
@@ -1053,8 +1052,7 @@
                 new SwAudioOutputDescriptor(profile, mpClientInterface);
 
         DeviceVector outputDevices = mAvailableOutputDevices.getDevicesFromTypeMask(device);
-        String8 address = outputDevices.size() > 0 ? outputDevices.itemAt(0)->mAddress
-                : String8("");
+        String8 address = getFirstDeviceAddress(outputDevices);
 
         // MSD patch may be using the only output stream that can service this request. Release
         // MSD patch to prioritize this request over any active output on MSD.
@@ -1755,10 +1753,7 @@
     }
 
     // Explicit routing?
-    sp<DeviceDescriptor> deviceDesc;
-    if (*selectedDeviceId != AUDIO_PORT_HANDLE_NONE) {
-        deviceDesc = mAvailableInputDevices.getDeviceFromId(*selectedDeviceId);
-    }
+    sp<DeviceDescriptor> deviceDesc = mAvailableInputDevices.getDeviceFromId(*selectedDeviceId);
 
     // special case for mmap capture: if an input IO handle is specified, we reuse this input if
     // possible
@@ -1864,8 +1859,7 @@
 exit:
 
     inputDevices = mAvailableInputDevices.getDevicesFromTypeMask(device);
-    *selectedDeviceId = inputDevices.size() > 0 ? inputDevices.itemAt(0)->getId()
-                                                : AUDIO_PORT_HANDLE_NONE;
+    *selectedDeviceId = getFirstDeviceId(inputDevices);
 
     isSoundTrigger = inputSource == AUDIO_SOURCE_HOTWORD &&
         mSoundTriggerSessions.indexOfKey(session) > 0;
@@ -1996,7 +1990,7 @@
     if (address == "") {
         DeviceVector inputDevices = mAvailableInputDevices.getDevicesFromTypeMask(device);
         // the inputs vector must be of size >= 1, but we don't want to crash here
-        address = inputDevices.size() > 0 ? inputDevices.itemAt(0)->mAddress : String8("");
+        address = getFirstDeviceAddress(inputDevices);
     }
 
     status_t status = inputDesc->open(&lConfig, device, address,
@@ -2963,7 +2957,7 @@
             }
 
             if (!outputDesc->mProfile->isCompatibleProfile(devDesc->type(),
-                                                           devDesc->mAddress,
+                                                           devDesc->address(),
                                                            patch->sources[0].sample_rate,
                                                            NULL,  // updatedSamplingRate
                                                            patch->sources[0].format,
@@ -3020,7 +3014,7 @@
             }
 
             if (!inputDesc->mProfile->isCompatibleProfile(devDesc->type(),
-                                                          devDesc->mAddress,
+                                                          devDesc->address(),
                                                           patch->sinks[0].sample_rate,
                                                           NULL, /*updatedSampleRate*/
                                                           patch->sinks[0].format,
@@ -3085,8 +3079,8 @@
                 // - audio HAL version is < 3.0
                 // - audio HAL version is >= 3.0 but no route has been declared between devices
                 if (!srcDeviceDesc->hasSameHwModuleAs(sinkDeviceDesc) ||
-                        (srcDeviceDesc->mModule->getHalVersionMajor() < 3) ||
-                        !srcDeviceDesc->mModule->supportsPatch(srcDeviceDesc, sinkDeviceDesc)) {
+                        (srcDeviceDesc->getModuleVersionMajor() < 3) ||
+                        !srcDeviceDesc->getModule()->supportsPatch(srcDeviceDesc, sinkDeviceDesc)) {
                     // support only one sink device for now to simplify output selection logic
                     if (patch->num_sinks > 1) {
                         return INVALID_OPERATION;
@@ -3431,8 +3425,8 @@
     audio_patch_handle_t afPatchHandle = AUDIO_PATCH_HANDLE_NONE;
 
     if (srcDeviceDesc->hasSameHwModuleAs(sinkDeviceDesc) &&
-            srcDeviceDesc->getAudioPort()->mModule->getHalVersionMajor() >= 3 &&
-            sinkDeviceDesc->mModule->supportsPatch(srcDeviceDesc, sinkDeviceDesc) &&
+            srcDeviceDesc->getModuleVersionMajor() >= 3 &&
+            sinkDeviceDesc->getModule()->supportsPatch(srcDeviceDesc, sinkDeviceDesc) &&
             srcDeviceDesc->getAudioPort()->mGains.size() > 0) {
         ALOGV("%s Device to Device route supported by >=3.0 HAL", __FUNCTION__);
         // TODO: may explicitly specify whether we should use HW or SW patch
@@ -3666,7 +3660,7 @@
             AUDIO_DEVICE_OUT_HDMI);
     for (size_t i = 0; i < hdmiOutputDevices.size(); i++) {
         // Simulate reconnection to update enabled surround sound formats.
-        String8 address = hdmiOutputDevices[i]->mAddress;
+        String8 address = hdmiOutputDevices[i]->address();
         String8 name = hdmiOutputDevices[i]->getName();
         status_t status = setDeviceConnectionStateInt(AUDIO_DEVICE_OUT_HDMI,
                                                       AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE,
@@ -3686,7 +3680,7 @@
                 AUDIO_DEVICE_IN_HDMI);
     for (size_t i = 0; i < hdmiInputDevices.size(); i++) {
         // Simulate reconnection to update enabled surround sound formats.
-        String8 address = hdmiInputDevices[i]->mAddress;
+        String8 address = hdmiInputDevices[i]->address();
         String8 name = hdmiInputDevices[i]->getName();
         status_t status = setDeviceConnectionStateInt(AUDIO_DEVICE_IN_HDMI,
                                                       AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE,
@@ -3944,8 +3938,7 @@
             const DeviceVector &supportedDevices = outProfile->getSupportedDevices();
             const DeviceVector &devicesForType = supportedDevices.getDevicesFromTypeMask(
                     profileType);
-            String8 address = devicesForType.size() > 0 ? devicesForType.itemAt(0)->mAddress
-                    : String8("");
+            String8 address = getFirstDeviceAddress(devicesForType);
             audio_io_handle_t output = AUDIO_IO_HANDLE_NONE;
             status_t status = outputDesc->open(nullptr, profileType, address,
                                            AUDIO_STREAM_DEFAULT, AUDIO_OUTPUT_FLAG_NONE, &output);
@@ -3999,8 +3992,7 @@
 
             DeviceVector inputDevices = mAvailableInputDevices.getDevicesFromTypeMask(profileType);
             //   the inputs vector must be of size >= 1, but we don't want to crash here
-            String8 address = inputDevices.size() > 0 ? inputDevices.itemAt(0)->mAddress
-                    : String8("");
+            String8 address = getFirstDeviceAddress(inputDevices);
             ALOGV("  for input device 0x%x using address %s", profileType, address.string());
             ALOGE_IF(inputDevices.size() == 0, "Input device list is empty!");
 
@@ -4062,11 +4054,11 @@
     }
     // If microphones address is empty, set it according to device type
     for (size_t i = 0; i  < mAvailableInputDevices.size(); i++) {
-        if (mAvailableInputDevices[i]->mAddress.isEmpty()) {
+        if (mAvailableInputDevices[i]->address().isEmpty()) {
             if (mAvailableInputDevices[i]->type() == AUDIO_DEVICE_IN_BUILTIN_MIC) {
-                mAvailableInputDevices[i]->mAddress = String8(AUDIO_BOTTOM_MICROPHONE_ADDRESS);
+                mAvailableInputDevices[i]->address() = String8(AUDIO_BOTTOM_MICROPHONE_ADDRESS);
             } else if (mAvailableInputDevices[i]->type() == AUDIO_DEVICE_IN_BACK_MIC) {
-                mAvailableInputDevices[i]->mAddress = String8(AUDIO_BACK_MICROPHONE_ADDRESS);
+                mAvailableInputDevices[i]->address() = String8(AUDIO_BACK_MICROPHONE_ADDRESS);
             }
         }
     }
@@ -5235,8 +5227,9 @@
         if (!deviceList.isEmpty()) {
             PatchBuilder patchBuilder;
             patchBuilder.addSource(outputDesc);
-            for (size_t i = 0; i < deviceList.size() && i < AUDIO_PATCH_PORTS_MAX; i++) {
-                patchBuilder.addSink(deviceList.itemAt(i));
+            ALOG_ASSERT(deviceList.size() <= AUDIO_PATCH_PORTS_MAX, "Too many sink ports");
+            for (const auto &device : deviceList) {
+                patchBuilder.addSink(device);
             }
             installPatch(__func__, patchHandle, outputDesc.get(), patchBuilder.patch(), delayMs);
         }
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.h b/services/audiopolicy/managerdefault/AudioPolicyManager.h
index aa7ffc8..86993d4 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.h
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.h
@@ -519,6 +519,19 @@
             return mAvailableInputDevices.getDeviceTypesFromHwModule(
                     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) ? devices.itemAt(0)->address() : String8("");
+        }
 
         uint32_t updateCallRouting(audio_devices_t rxDevice, uint32_t delayMs = 0);
         sp<AudioPatch> createTelephonyPatch(bool isRx, audio_devices_t device, uint32_t delayMs);