libaudiohal@aidl: Fix handling of transient patch updates

There are cases when the framework opens a stream for one
device, and then issues a "create patch" command with
AUDIO_PATCH_HANDLE_NONE, and a different device. In that
case the mapper must match the patch using the mix port
handle, and then send a patch update command to the HAL.

Bug: 341326679
Test: atest CoreAudioHalAidlTest
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:0be9192fb5def6ff2c46a3ec9fe68bd4d859aa14)
Merged-In: Ic2ed15343f494f346de70af0f6d22fd59a3a81d7
Change-Id: Ic2ed15343f494f346de70af0f6d22fd59a3a81d7
diff --git a/media/libaudiohal/impl/Hal2AidlMapper.cpp b/media/libaudiohal/impl/Hal2AidlMapper.cpp
index 453f9e2..cbade70 100644
--- a/media/libaudiohal/impl/Hal2AidlMapper.cpp
+++ b/media/libaudiohal/impl/Hal2AidlMapper.cpp
@@ -136,8 +136,8 @@
     // 'sinks' will not be updated because 'setAudioPatch' only needs IDs. Here we log
     // the source arguments, where only the audio configuration and device specifications
     // are relevant.
-    ALOGD("%s: [disregard IDs] sources: %s, sinks: %s",
-            __func__, ::android::internal::ToString(sources).c_str(),
+    ALOGD("%s: patch ID: %d, [disregard IDs] sources: %s, sinks: %s",
+            __func__, *patchId, ::android::internal::ToString(sources).c_str(),
             ::android::internal::ToString(sinks).c_str());
     auto fillPortConfigs = [&](
             const std::vector<AudioPortConfig>& configs,
@@ -209,11 +209,24 @@
         // that there can only be one patch for an I/O thread.
         PatchMatch match = sourceIsDevice && sinkIsDevice ?
                 MATCH_BOTH : (sourceIsDevice ? MATCH_SINKS : MATCH_SOURCES);
+        auto requestedPatch = patch;
         RETURN_STATUS_IF_ERROR(findOrCreatePatch(patch, match,
                                                  &patch, &created));
         // No cleanup of the patch is needed, it is managed by the framework.
         *patchId = patch.id;
         if (!created) {
+            requestedPatch.id = patch.id;
+            if (patch != requestedPatch) {
+                ALOGI("%s: Updating transient patch. Current: %s, new: %s",
+                        __func__, patch.toString().c_str(), requestedPatch.toString().c_str());
+                // Since matching may be done by mix port only, update the patch if the device port
+                // config has changed.
+                patch = requestedPatch;
+                RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
+                                mModule->setAudioPatch(patch, &patch)));
+                existingPatchIt = mPatches.find(patch.id);
+                existingPatchIt->second = patch;
+            }
             // The framework might have "created" a patch which already existed due to
             // stream creation. Need to release the ownership from the stream.
             for (auto& s : mStreams) {