AudioPolicy: remove devices while Sw bridge established

When devices are disconnected while involved in a SwBridge,
the connectAudioSource function may be called while the cache
of the engine has not yet been updated with availability of devices.

This CL forces to retrieve sinkDevices from engine without using
the cache.

It also ensures that Audio Source using Direct Output are also
re routed while sink device has been made UNAVAILABLE then AVAILABLE
again. In this case, no SwOutput will keep track of the AudioSource.
Orphans Audio Source shall be handled independantly.

So far, robustness cases added to the following test.
In some case, fallback on speaker is allowed, in other,
device none is selected while given sink has been made unavailable:

Test: So far: adb shell /data/nativetest64/AudioPolicyEmulatorTests/AudioPolicyEmulatorTests --gtest_filter=AudioPatchTest/AudioModeBridgingTest.
adb shell /data/nativetest64/AudioPolicyEmulatorTests/AudioPolicyEmulatorTests --gtest_filter=AudioSourceTest/AudioSourceBridgingTest.UsingAudioSourceAPI/

Signed-off-by: Francois Gaffie <francois.gaffie@renault.com>
Change-Id: I2663d10f08de3191de4d95bc81749ede9b8a360f
Merged-In: I2663d10f08de3191de4d95bc81749ede9b8a360f
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index beaa979..d1825b9 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -247,6 +247,7 @@
                     if ((state == AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE) ||
                             (((desc->mFlags & AUDIO_OUTPUT_FLAG_DIRECT) != 0) &&
                                 (desc->mDirectOpenCount == 0))) {
+                        clearAudioSourcesForOutput(output);
                         closeOutput(output);
                     }
                 }
@@ -3944,8 +3945,9 @@
                 sp<SwAudioOutputDescriptor> outputDesc =
                         mOutputs.getOutputFromId(patch->sources[1].id);
                 if (outputDesc == NULL) {
-                    ALOGE("%s output not found for id %d", __func__, patch->sources[0].id);
-                    return BAD_VALUE;
+                    ALOGW("%s output not found for id %d", __func__, patch->sources[0].id);
+                    // releaseOutput has already called closeOuput in case of direct output
+                    return NO_ERROR;
                 }
                 if (patchDesc->getHandle() != outputDesc->getPatchHandle()) {
                     // force SwOutput patch removal as AF counter part patch has already gone.
@@ -4209,12 +4211,13 @@
 
     // make sure we only have one patch per source.
     disconnectAudioSource(sourceDesc);
+    sourceDesc->setPatchHandle(AUDIO_PATCH_HANDLE_NONE);
 
     audio_attributes_t attributes = sourceDesc->attributes();
     sp<DeviceDescriptor> srcDevice = sourceDesc->srcDevice();
 
     DeviceVector sinkDevices =
-            mEngine->getOutputDevicesForAttributes(attributes, nullptr, true);
+            mEngine->getOutputDevicesForAttributes(attributes, nullptr, false /*fromCache*/);
     ALOG_ASSERT(!sinkDevices.isEmpty(), "connectAudioSource(): no device found for attributes");
     sp<DeviceDescriptor> sinkDevice = sinkDevices.itemAt(0);
     ALOG_ASSERT(mAvailableOutputDevices.contains(sinkDevice), "%s: Device %s not available",
@@ -5346,6 +5349,28 @@
             mEngine->getProductStrategyForAttributes(rAttr);
 }
 
+void AudioPolicyManager::checkAudioSourceForAttributes(const audio_attributes_t &attr)
+{
+    for (size_t i = 0; i < mAudioSources.size(); i++)  {
+        sp<SourceClientDescriptor> sourceDesc = mAudioSources.valueAt(i);
+        if (sourceDesc != nullptr && followsSameRouting(attr, sourceDesc->attributes())
+                && sourceDesc->getPatchHandle() == AUDIO_PATCH_HANDLE_NONE) {
+            connectAudioSource(sourceDesc);
+        }
+    }
+}
+
+void AudioPolicyManager::clearAudioSourcesForOutput(audio_io_handle_t output)
+{
+    for (size_t i = 0; i < mAudioSources.size(); i++)  {
+        sp<SourceClientDescriptor> sourceDesc = mAudioSources.valueAt(i);
+        if (sourceDesc != nullptr && sourceDesc->swOutput().promote() != nullptr
+                && sourceDesc->swOutput().promote()->mIoHandle == output) {
+            disconnectAudioSource(sourceDesc);
+        }
+    }
+}
+
 void AudioPolicyManager::checkOutputForAttributes(const audio_attributes_t &attr)
 {
     auto psId = mEngine->getProductStrategyForAttributes(attr);
@@ -5441,7 +5466,7 @@
                                 newDevices.types());
             }
             sp<SourceClientDescriptor> source = getSourceForAttributesOnOutput(srcOut, attr);
-            if (source != 0){
+            if (source != nullptr) {
                 connectAudioSource(source);
             }
         }
@@ -5464,6 +5489,7 @@
     for (const auto &strategy : mEngine->getOrderedProductStrategies()) {
         auto attributes = mEngine->getAllAttributesForProductStrategy(strategy).front();
         checkOutputForAttributes(attributes);
+        checkAudioSourceForAttributes(attributes);
     }
 }