Merge "Convert OggExtractor to V3 format"
diff --git a/camera/ndk/impl/ACameraDevice.cpp b/camera/ndk/impl/ACameraDevice.cpp
index 00da54e..657d41f 100644
--- a/camera/ndk/impl/ACameraDevice.cpp
+++ b/camera/ndk/impl/ACameraDevice.cpp
@@ -633,7 +633,7 @@
     }
 
     std::set<std::pair<ANativeWindow*, OutputConfiguration>> outputSet;
-    for (auto outConfig : outputs->mOutputs) {
+    for (const auto& outConfig : outputs->mOutputs) {
         ANativeWindow* anw = outConfig.mWindow;
         sp<IGraphicBufferProducer> iGBP(nullptr);
         ret = getIGBPfromAnw(anw, iGBP);
@@ -706,7 +706,7 @@
     }
 
     // add new streams
-    for (auto outputPair : addSet) {
+    for (const auto& outputPair : addSet) {
         int streamId;
         remoteRet = mRemote->createStream(outputPair.second, &streamId);
         if (!remoteRet.isOk()) {
@@ -839,7 +839,7 @@
 
         const auto& gbps = outputPairIt->second.second.getGraphicBufferProducers();
         for (const auto& outGbp : gbps) {
-            for (auto surface : request->mSurfaceList) {
+            for (const auto& surface : request->mSurfaceList) {
                 if (surface->getIGraphicBufferProducer() == outGbp) {
                     ANativeWindow* anw = static_cast<ANativeWindow*>(surface.get());
                     ALOGV("Camera %s Lost output buffer for ANW %p frame %" PRId64,
diff --git a/cmds/stagefright/Android.mk b/cmds/stagefright/Android.mk
index c7619af..7a10302 100644
--- a/cmds/stagefright/Android.mk
+++ b/cmds/stagefright/Android.mk
@@ -191,7 +191,6 @@
 LOCAL_MODULE:= mediafilter
 
 LOCAL_SANITIZE := cfi
-LOCAL_SANITIZE_DIAG := cfi
 
 include $(BUILD_EXECUTABLE)
 
diff --git a/media/libaaudio/src/client/AudioStreamInternalCapture.cpp b/media/libaaudio/src/client/AudioStreamInternalCapture.cpp
index 4a0e6da..58ef7b1 100644
--- a/media/libaaudio/src/client/AudioStreamInternalCapture.cpp
+++ b/media/libaaudio/src/client/AudioStreamInternalCapture.cpp
@@ -258,7 +258,7 @@
         callbackResult = maybeCallDataCallback(mCallbackBuffer, mCallbackFrames);
 
         if (callbackResult == AAUDIO_CALLBACK_RESULT_STOP) {
-            ALOGD("callback returned AAUDIO_CALLBACK_RESULT_STOP");
+            ALOGD("%s(): callback returned AAUDIO_CALLBACK_RESULT_STOP", __func__);
             break;
         }
     }
diff --git a/media/libaaudio/src/client/AudioStreamInternalPlay.cpp b/media/libaaudio/src/client/AudioStreamInternalPlay.cpp
index 2ae37a5..9af47b2 100644
--- a/media/libaaudio/src/client/AudioStreamInternalPlay.cpp
+++ b/media/libaaudio/src/client/AudioStreamInternalPlay.cpp
@@ -293,7 +293,7 @@
                 break;
             }
         } else if (callbackResult == AAUDIO_CALLBACK_RESULT_STOP) {
-            ALOGV("%s(): callback returned AAUDIO_CALLBACK_RESULT_STOP", __func__);
+            ALOGD("%s(): callback returned AAUDIO_CALLBACK_RESULT_STOP", __func__);
             break;
         }
     }
diff --git a/media/libaaudio/tests/Android.bp b/media/libaaudio/tests/Android.bp
index 319467e..cb243a0 100644
--- a/media/libaaudio/tests/Android.bp
+++ b/media/libaaudio/tests/Android.bp
@@ -184,3 +184,15 @@
         "libutils",
     ],
 }
+
+cc_test {
+    name: "test_return_stop",
+    defaults: ["libaaudio_tests_defaults"],
+    srcs: ["test_return_stop.cpp"],
+    shared_libs: [
+        "libaaudio",
+        "libbinder",
+        "libcutils",
+        "libutils",
+    ],
+}
diff --git a/media/libaaudio/tests/test_return_stop.cpp b/media/libaaudio/tests/test_return_stop.cpp
new file mode 100644
index 0000000..f34c3c8
--- /dev/null
+++ b/media/libaaudio/tests/test_return_stop.cpp
@@ -0,0 +1,284 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Return stop from the callback.
+ * Expect the callback to cease.
+ * Check the logcat for bad behavior.
+ */
+
+#include <stdio.h>
+#include <thread>
+#include <unistd.h>
+
+#include <aaudio/AAudio.h>
+
+#define DEFAULT_TIMEOUT_NANOS  ((int64_t)1000000000)
+#define STOP_AT_MSEC          1000
+#define LOOP_DURATION_MSEC    4000
+#define SLEEP_DURATION_MSEC    200
+
+static void s_myErrorCallbackProc(
+        AAudioStream *stream,
+        void *userData,
+        aaudio_result_t error);
+
+struct AudioEngine {
+    AAudioStreamBuilder *builder = nullptr;
+    AAudioStream        *stream = nullptr;
+    std::thread         *thread = nullptr;
+    int32_t              stopAtFrame = 0;
+    bool                 stopped = false;
+    // These counters are read and written by the callback and the main thread.
+    std::atomic<int32_t> framesRead{};
+    std::atomic<int32_t> startingFramesRead{};
+    std::atomic<int32_t> framesCalled{};
+    std::atomic<int32_t> callbackCount{};
+    std::atomic<int32_t> callbackCountAfterStop{};
+
+    void reset() {
+        framesRead.store(0);
+        startingFramesRead.store(0);
+        framesCalled.store(0);
+        callbackCount.store(0);
+        callbackCountAfterStop.store(0);
+        stopped = false;
+    }
+};
+
+// Callback function that fills the audio output buffer.
+static aaudio_data_callback_result_t s_myDataCallbackProc(
+        AAudioStream *stream,
+        void *userData,
+        void *audioData,
+        int32_t numFrames
+) {
+    (void) audioData;
+    (void) numFrames;
+    AudioEngine *engine = (struct AudioEngine *)userData;
+    engine->callbackCount++;
+    if (engine->stopped) {
+        engine->callbackCountAfterStop++;
+    }
+
+    engine->framesRead = (int32_t)AAudioStream_getFramesRead(stream);
+    if (engine->startingFramesRead == 0) {
+        engine->startingFramesRead.store(engine->framesRead.load());
+    }
+    engine->framesCalled += numFrames;
+    if (engine->framesCalled >= engine->stopAtFrame) {
+        engine->stopped = true;
+        return AAUDIO_CALLBACK_RESULT_STOP;
+    } else {
+        return AAUDIO_CALLBACK_RESULT_CONTINUE;
+    }
+}
+
+static aaudio_result_t s_OpenAudioStream(struct AudioEngine *engine,
+                                         aaudio_direction_t direction,
+                                         aaudio_sharing_mode_t sharingMode,
+                                         aaudio_performance_mode_t perfMode) {
+    // Use an AAudioStreamBuilder to contain requested parameters.
+    aaudio_result_t result = AAudio_createStreamBuilder(&engine->builder);
+    if (result != AAUDIO_OK) {
+        printf("AAudio_createStreamBuilder returned %s",
+               AAudio_convertResultToText(result));
+        return result;
+    }
+
+    // Request stream properties.
+    AAudioStreamBuilder_setFormat(engine->builder, AAUDIO_FORMAT_PCM_FLOAT);
+    AAudioStreamBuilder_setPerformanceMode(engine->builder, perfMode);
+    AAudioStreamBuilder_setSharingMode(engine->builder, sharingMode);
+    AAudioStreamBuilder_setDirection(engine->builder, direction);
+    AAudioStreamBuilder_setDataCallback(engine->builder, s_myDataCallbackProc, engine);
+    AAudioStreamBuilder_setErrorCallback(engine->builder, s_myErrorCallbackProc, engine);
+
+    // Create an AAudioStream using the Builder.
+    result = AAudioStreamBuilder_openStream(engine->builder, &engine->stream);
+    if (result != AAUDIO_OK) {
+        printf("AAudioStreamBuilder_openStream returned %s",
+               AAudio_convertResultToText(result));
+        return result;
+    }
+
+    return result;
+}
+
+static aaudio_result_t s_CloseAudioStream(struct AudioEngine *engine) {
+    aaudio_result_t result = AAUDIO_OK;
+    if (engine->stream != nullptr) {
+        result = AAudioStream_close(engine->stream);
+        if (result != AAUDIO_OK) {
+            printf("AAudioStream_close returned %s\n",
+                   AAudio_convertResultToText(result));
+        }
+        engine->stream = nullptr;
+    }
+    AAudioStreamBuilder_delete(engine->builder);
+    engine->builder = nullptr;
+    return result;
+}
+
+static void s_myErrorCallbackProc(
+        AAudioStream *stream __unused,
+        void *userData __unused,
+        aaudio_result_t error) {
+    printf("%s() - error = %d\n", __func__, error);
+}
+
+void usage() {
+    printf("test_return_stop [-i] [-x] [-n] [-c]\n");
+    printf("     -i direction INPUT, otherwise OUTPUT\n");
+    printf("     -x sharing mode EXCLUSIVE, otherwise SHARED\n");
+    printf("     -n performance mode NONE, otherwise LOW_LATENCY\n");
+    printf("     -c always return CONTINUE from callback, not STOP\n");
+}
+
+int main(int argc, char **argv) {
+    (void) argc;
+    (void) argv;
+    struct AudioEngine engine;
+    aaudio_sharing_mode_t sharingMode = AAUDIO_SHARING_MODE_SHARED;
+    aaudio_performance_mode_t perfMode = AAUDIO_PERFORMANCE_MODE_LOW_LATENCY;
+    aaudio_direction_t direction = AAUDIO_DIRECTION_OUTPUT;
+    aaudio_result_t result = AAUDIO_OK;
+    bool alwaysContinue = false;
+    int errorCount = 0;
+    int callbackResult = EXIT_SUCCESS;
+
+    // Make printf print immediately so that debug info is not stuck
+    // in a buffer if we hang or crash.
+    setvbuf(stdout, nullptr, _IONBF, (size_t) 0);
+
+    printf("Test Return Stop V1.0\n");
+    printf("Wait for a few seconds.\n");
+    printf("You should see callbackCount and framesRead stop advancing\n");
+    printf("when callbackCount reaches %d msec\n", STOP_AT_MSEC);
+    printf("\n");
+
+    for (int i = 1; i < argc; i++) {
+        const char *arg = argv[i];
+        if (arg[0] == '-') {
+            char option = arg[1];
+            switch (option) {
+                case 'c':
+                    alwaysContinue = true;
+                    break;
+                case 'i':
+                    direction = AAUDIO_DIRECTION_INPUT;
+                    break;
+                case 'n':
+                    perfMode = AAUDIO_PERFORMANCE_MODE_NONE;
+                    break;
+                case 'x':
+                    sharingMode = AAUDIO_SHARING_MODE_EXCLUSIVE;
+                    break;
+                default:
+                    usage();
+                    exit(EXIT_FAILURE);
+                    break;
+            }
+        } else {
+            usage();
+            exit(EXIT_FAILURE);
+            break;
+        }
+    }
+
+    result = s_OpenAudioStream(&engine, direction, sharingMode, perfMode);
+    if (result != AAUDIO_OK) {
+        printf("s_OpenAudioStream returned %s",
+               AAudio_convertResultToText(result));
+        errorCount++;
+    }
+
+    int32_t framesPerBurst = AAudioStream_getFramesPerBurst(engine.stream);
+    // Check to see what kind of stream we actually got.
+    int32_t deviceId = AAudioStream_getDeviceId(engine.stream);
+    aaudio_performance_mode_t actualPerfMode = AAudioStream_getPerformanceMode(engine.stream);
+    printf("-------- opened: deviceId = %3d, framesPerBurst = %3d, perfMode = %d\n",
+           deviceId, framesPerBurst, actualPerfMode);
+
+    // Calculate how many callbacks needed.
+    if (alwaysContinue) {
+        engine.stopAtFrame = INT32_MAX;
+    } else {
+        int32_t sampleRate = AAudioStream_getSampleRate(engine.stream);
+        engine.stopAtFrame = STOP_AT_MSEC * sampleRate / 1000;
+    }
+
+    for (int loops = 0; loops < 2 && result == AAUDIO_OK; loops++) {
+        engine.reset();
+
+        // Start stream.
+        result = AAudioStream_requestStart(engine.stream);
+        printf("AAudioStream_requestStart() returned %d >>>>>>>>>>>>>>>>>>>>>>\n", result);
+        if (result != AAUDIO_OK) {
+            printf("ERROR - AAudioStream_requestStart returned %s",
+                   AAudio_convertResultToText(result));
+            errorCount++;
+            break;
+        }
+
+        if (result == AAUDIO_OK) {
+            const int watchLoops = LOOP_DURATION_MSEC / SLEEP_DURATION_MSEC;
+            for (int i = watchLoops; i > 0; i--) {
+                printf("playing silence #%02d, framesRead = %7d, framesWritten = %7d,"
+                       " framesCalled = %6d, callbackCount = %4d\n",
+                       i,
+                       (int32_t) AAudioStream_getFramesRead(engine.stream),
+                       (int32_t) AAudioStream_getFramesWritten(engine.stream),
+                       engine.framesCalled.load(),
+                       engine.callbackCount.load()
+                );
+                usleep(SLEEP_DURATION_MSEC * 1000);
+            }
+        }
+
+        if (engine.stopAtFrame != INT32_MAX) {
+            callbackResult = (engine.callbackCountAfterStop == 0) ? EXIT_SUCCESS
+                                                                             : EXIT_FAILURE;
+            if (callbackResult) {
+                printf("ERROR - Callback count after STOP = %d\n",
+                       engine.callbackCountAfterStop.load());
+                errorCount++;
+            }
+        }
+
+        if (engine.startingFramesRead.load() == engine.framesRead.load()) {
+            printf("ERROR - framesRead did not advance across callbacks\n");
+            errorCount++;
+        }
+
+        result = AAudioStream_requestStop(engine.stream);
+        printf("AAudioStream_requestStop() returned %d <<<<<<<<<<<<<<<<<<<<<\n", result);
+        if (result != AAUDIO_OK) {
+            errorCount++;
+        }
+        usleep(SLEEP_DURATION_MSEC * 1000);
+        printf("getFramesRead() = %d, getFramesWritten() = %d\n",
+               (int32_t) AAudioStream_getFramesRead(engine.stream),
+               (int32_t) AAudioStream_getFramesWritten(engine.stream));
+    }
+
+    s_CloseAudioStream(&engine);
+
+    printf("aaudio result = %d = %s\n", result, AAudio_convertResultToText(result));
+    printf("test %s\n", errorCount ? "FAILED" : "PASSED");
+
+    return errorCount ? EXIT_FAILURE : EXIT_SUCCESS;
+}
diff --git a/media/libaudiohal/EffectsFactoryHalInterface.cpp b/media/libaudiohal/EffectsFactoryHalInterface.cpp
index e21c235..bd3ef61 100644
--- a/media/libaudiohal/EffectsFactoryHalInterface.cpp
+++ b/media/libaudiohal/EffectsFactoryHalInterface.cpp
@@ -25,13 +25,13 @@
 // static
 sp<EffectsFactoryHalInterface> EffectsFactoryHalInterface::create() {
     if (hardware::audio::effect::V5_0::IEffectsFactory::getService() != nullptr) {
-        return V5_0::createEffectsFactoryHal();
+        return effect::V5_0::createEffectsFactoryHal();
     }
     if (hardware::audio::effect::V4_0::IEffectsFactory::getService() != nullptr) {
-        return V4_0::createEffectsFactoryHal();
+        return effect::V4_0::createEffectsFactoryHal();
     }
     if (hardware::audio::effect::V2_0::IEffectsFactory::getService() != nullptr) {
-        return V2_0::createEffectsFactoryHal();
+        return effect::V2_0::createEffectsFactoryHal();
     }
     return nullptr;
 }
diff --git a/media/libaudiohal/HalDeathHandlerHidl.cpp b/media/libaudiohal/HalDeathHandlerHidl.cpp
index 1e3ab58..6e33523 100644
--- a/media/libaudiohal/HalDeathHandlerHidl.cpp
+++ b/media/libaudiohal/HalDeathHandlerHidl.cpp
@@ -54,7 +54,7 @@
         handler.second();
     }
     ALOGE("HAL server crashed, audio server is restarting");
-    exit(1);
+    _exit(1);  // Avoid calling atexit handlers, as this code runs on a thread from RPC threadpool.
 }
 
 } // namespace android
diff --git a/media/libaudiohal/impl/EffectBufferHalHidl.cpp b/media/libaudiohal/impl/EffectBufferHalHidl.cpp
index 6ef4e8a..5367972 100644
--- a/media/libaudiohal/impl/EffectBufferHalHidl.cpp
+++ b/media/libaudiohal/impl/EffectBufferHalHidl.cpp
@@ -30,6 +30,7 @@
 using ::android::hidl::allocator::V1_0::IAllocator;
 
 namespace android {
+namespace effect {
 namespace CPP_VERSION {
 
 // static
@@ -142,5 +143,6 @@
     memcpy(mExternalData, mAudioBuffer.raw, size);
 }
 
+} // namespace effect
 } // namespace CPP_VERSION
 } // namespace android
diff --git a/media/libaudiohal/impl/EffectBufferHalHidl.h b/media/libaudiohal/impl/EffectBufferHalHidl.h
index 0c99a02..4826813 100644
--- a/media/libaudiohal/impl/EffectBufferHalHidl.h
+++ b/media/libaudiohal/impl/EffectBufferHalHidl.h
@@ -23,13 +23,15 @@
 #include <media/audiohal/EffectBufferHalInterface.h>
 #include <system/audio_effect.h>
 
-using android::hardware::audio::effect::CPP_VERSION::AudioBuffer;
 using android::hardware::hidl_memory;
 using android::hidl::memory::V1_0::IMemory;
 
 namespace android {
+namespace effect {
 namespace CPP_VERSION {
 
+using namespace ::android::hardware::audio::effect::CPP_VERSION;
+
 class EffectBufferHalHidl : public EffectBufferHalInterface
 {
   public:
@@ -73,6 +75,7 @@
 };
 
 } // namespace CPP_VERSION
+} // namespace effect
 } // namespace android
 
 #endif // ANDROID_HARDWARE_EFFECT_BUFFER_HAL_HIDL_H
diff --git a/media/libaudiohal/impl/EffectHalHidl.cpp b/media/libaudiohal/impl/EffectHalHidl.cpp
index df79b95..b0597b3 100644
--- a/media/libaudiohal/impl/EffectHalHidl.cpp
+++ b/media/libaudiohal/impl/EffectHalHidl.cpp
@@ -26,11 +26,6 @@
 #include "EffectHalHidl.h"
 #include "HidlUtils.h"
 
-using ::android::hardware::audio::effect::CPP_VERSION::AudioBuffer;
-using ::android::hardware::audio::effect::CPP_VERSION::EffectBufferAccess;
-using ::android::hardware::audio::effect::CPP_VERSION::EffectConfigParameters;
-using ::android::hardware::audio::effect::CPP_VERSION::MessageQueueFlagBits;
-using ::android::hardware::audio::effect::CPP_VERSION::Result;
 using ::android::hardware::audio::common::CPP_VERSION::implementation::HidlUtils;
 using ::android::hardware::audio::common::utils::EnumBitfield;
 using ::android::hardware::hidl_vec;
@@ -38,9 +33,11 @@
 using ::android::hardware::Return;
 
 namespace android {
+namespace effect {
 namespace CPP_VERSION {
 
 using namespace ::android::hardware::audio::common::CPP_VERSION;
+using namespace ::android::hardware::audio::effect::CPP_VERSION;
 
 EffectHalHidl::EffectHalHidl(const sp<IEffect>& effect, uint64_t effectId)
         : mEffect(effect), mEffectId(effectId), mBuffersChanged(true), mEfGroup(nullptr) {
@@ -338,4 +335,5 @@
 }
 
 } // namespace CPP_VERSION
+} // namespace effect
 } // namespace android
diff --git a/media/libaudiohal/impl/EffectHalHidl.h b/media/libaudiohal/impl/EffectHalHidl.h
index cd447ff..9d9f707 100644
--- a/media/libaudiohal/impl/EffectHalHidl.h
+++ b/media/libaudiohal/impl/EffectHalHidl.h
@@ -23,17 +23,15 @@
 #include <fmq/MessageQueue.h>
 #include <system/audio_effect.h>
 
-using ::android::hardware::audio::effect::CPP_VERSION::EffectBufferConfig;
-using ::android::hardware::audio::effect::CPP_VERSION::EffectConfig;
-using ::android::hardware::audio::effect::CPP_VERSION::EffectDescriptor;
-using ::android::hardware::audio::effect::CPP_VERSION::IEffect;
-using EffectResult = ::android::hardware::audio::effect::CPP_VERSION::Result;
 using ::android::hardware::EventFlag;
 using ::android::hardware::MessageQueue;
 
 namespace android {
+namespace effect {
 namespace CPP_VERSION {
 
+using namespace ::android::hardware::audio::effect::CPP_VERSION;
+
 class EffectHalHidl : public EffectHalInterface
 {
   public:
@@ -70,7 +68,7 @@
 
   private:
     friend class EffectsFactoryHalHidl;
-    typedef MessageQueue<EffectResult, hardware::kSynchronizedReadWrite> StatusMQ;
+    typedef MessageQueue<Result, hardware::kSynchronizedReadWrite> StatusMQ;
 
     sp<IEffect> mEffect;
     const uint64_t mEffectId;
@@ -80,7 +78,7 @@
     std::unique_ptr<StatusMQ> mStatusMQ;
     EventFlag* mEfGroup;
 
-    static status_t analyzeResult(const EffectResult& result);
+    static status_t analyzeResult(const Result& result);
     static void effectBufferConfigFromHal(
             const buffer_config_t& halConfig, EffectBufferConfig* config);
     static void effectBufferConfigToHal(
@@ -105,6 +103,7 @@
 };
 
 } // namespace CPP_VERSION
+} // namespace effect
 } // namespace android
 
 #endif // ANDROID_HARDWARE_EFFECT_HAL_HIDL_H
diff --git a/media/libaudiohal/impl/EffectsFactoryHalHidl.cpp b/media/libaudiohal/impl/EffectsFactoryHalHidl.cpp
index 7fea466..7fd6bde 100644
--- a/media/libaudiohal/impl/EffectsFactoryHalHidl.cpp
+++ b/media/libaudiohal/impl/EffectsFactoryHalHidl.cpp
@@ -26,14 +26,14 @@
 #include "HidlUtils.h"
 
 using ::android::hardware::audio::common::CPP_VERSION::implementation::HidlUtils;
-using ::android::hardware::audio::effect::CPP_VERSION::IEffect;
-using ::android::hardware::audio::effect::CPP_VERSION::Result;
 using ::android::hardware::Return;
 
 namespace android {
+namespace effect {
 namespace CPP_VERSION {
 
 using namespace ::android::hardware::audio::common::CPP_VERSION;
+using namespace ::android::hardware::audio::effect::CPP_VERSION;
 
 EffectsFactoryHalHidl::EffectsFactoryHalHidl() : ConversionHelperHidl("EffectsFactory") {
     mEffectsFactory = IEffectsFactory::getService();
@@ -145,6 +145,6 @@
     return EffectBufferHalHidl::mirror(external, size, buffer);
 }
 
-
 } // namespace CPP_VERSION
+} // namespace effect
 } // namespace android
diff --git a/media/libaudiohal/impl/EffectsFactoryHalHidl.h b/media/libaudiohal/impl/EffectsFactoryHalHidl.h
index 7027153..01178ff 100644
--- a/media/libaudiohal/impl/EffectsFactoryHalHidl.h
+++ b/media/libaudiohal/impl/EffectsFactoryHalHidl.h
@@ -24,11 +24,12 @@
 #include "ConversionHelperHidl.h"
 
 namespace android {
+namespace effect {
 namespace CPP_VERSION {
 
-using ::android::hardware::audio::effect::CPP_VERSION::EffectDescriptor;
-using ::android::hardware::audio::effect::CPP_VERSION::IEffectsFactory;
 using ::android::hardware::hidl_vec;
+using ::android::CPP_VERSION::ConversionHelperHidl;
+using namespace ::android::hardware::audio::effect::CPP_VERSION;
 
 class EffectsFactoryHalHidl : public EffectsFactoryHalInterface, public ConversionHelperHidl
 {
@@ -70,6 +71,7 @@
 }
 
 } // namespace CPP_VERSION
+} // namespace effect
 } // namespace android
 
 #endif // ANDROID_HARDWARE_EFFECTS_FACTORY_HAL_HIDL_H
diff --git a/media/libaudiohal/impl/StreamHalHidl.cpp b/media/libaudiohal/impl/StreamHalHidl.cpp
index 9765f1e..c12b362 100644
--- a/media/libaudiohal/impl/StreamHalHidl.cpp
+++ b/media/libaudiohal/impl/StreamHalHidl.cpp
@@ -35,6 +35,7 @@
 namespace android {
 namespace CPP_VERSION {
 
+using EffectHalHidl = ::android::effect::CPP_VERSION::EffectHalHidl;
 using ReadCommand = ::android::hardware::audio::CPP_VERSION::IStreamIn::ReadCommand;
 
 using namespace ::android::hardware::audio::common::CPP_VERSION;
diff --git a/media/libaudiohal/impl/include/libaudiohal/FactoryHalHidl.h b/media/libaudiohal/impl/include/libaudiohal/FactoryHalHidl.h
index 1d912a0..c7319d0 100644
--- a/media/libaudiohal/impl/include/libaudiohal/FactoryHalHidl.h
+++ b/media/libaudiohal/impl/include/libaudiohal/FactoryHalHidl.h
@@ -25,18 +25,29 @@
 
 namespace android {
 
+namespace effect {
 namespace V2_0 {
 sp<EffectsFactoryHalInterface> createEffectsFactoryHal();
-sp<DevicesFactoryHalInterface> createDevicesFactoryHal();
 } // namespace V2_0
 
 namespace V4_0 {
 sp<EffectsFactoryHalInterface> createEffectsFactoryHal();
-sp<DevicesFactoryHalInterface> createDevicesFactoryHal();
 } // namespace V4_0
 
 namespace V5_0 {
 sp<EffectsFactoryHalInterface> createEffectsFactoryHal();
+} // namespace V5_0
+} // namespace effect
+
+namespace V2_0 {
+sp<DevicesFactoryHalInterface> createDevicesFactoryHal();
+} // namespace V2_0
+
+namespace V4_0 {
+sp<DevicesFactoryHalInterface> createDevicesFactoryHal();
+} // namespace V4_0
+
+namespace V5_0 {
 sp<DevicesFactoryHalInterface> createDevicesFactoryHal();
 } // namespace V5_0
 
diff --git a/media/libeffects/config/src/EffectsConfig.cpp b/media/libeffects/config/src/EffectsConfig.cpp
index 351b1ee..76b4adc 100644
--- a/media/libeffects/config/src/EffectsConfig.cpp
+++ b/media/libeffects/config/src/EffectsConfig.cpp
@@ -305,7 +305,7 @@
         return parseWithPath(path);
     }
 
-    for (std::string location : DEFAULT_LOCATIONS) {
+    for (const std::string& location : DEFAULT_LOCATIONS) {
         std::string defaultPath = location + '/' + DEFAULT_NAME;
         if (access(defaultPath.c_str(), R_OK) != 0) {
             continue;
diff --git a/media/libmedia/TypeConverter.cpp b/media/libmedia/TypeConverter.cpp
index fb861d7..b5a7172 100644
--- a/media/libmedia/TypeConverter.cpp
+++ b/media/libmedia/TypeConverter.cpp
@@ -285,6 +285,7 @@
 
 template <>
 const StreamTypeConverter::Table StreamTypeConverter::mTable[] = {
+    MAKE_STRING_FROM_ENUM(AUDIO_STREAM_DEFAULT),
     MAKE_STRING_FROM_ENUM(AUDIO_STREAM_VOICE_CALL),
     MAKE_STRING_FROM_ENUM(AUDIO_STREAM_SYSTEM),
     MAKE_STRING_FROM_ENUM(AUDIO_STREAM_RING),
@@ -361,6 +362,22 @@
     TERMINATOR
 };
 
+template <>
+const AudioFlagConverter::Table AudioFlagConverter::mTable[] = {
+    MAKE_STRING_FROM_ENUM(AUDIO_FLAG_NONE),
+    MAKE_STRING_FROM_ENUM(AUDIO_FLAG_AUDIBILITY_ENFORCED),
+    MAKE_STRING_FROM_ENUM(AUDIO_FLAG_SECURE),
+    MAKE_STRING_FROM_ENUM(AUDIO_FLAG_SCO),
+    MAKE_STRING_FROM_ENUM(AUDIO_FLAG_BEACON),
+    MAKE_STRING_FROM_ENUM(AUDIO_FLAG_HW_AV_SYNC),
+    MAKE_STRING_FROM_ENUM(AUDIO_FLAG_HW_HOTWORD),
+    MAKE_STRING_FROM_ENUM(AUDIO_FLAG_BYPASS_INTERRUPTION_POLICY),
+    MAKE_STRING_FROM_ENUM(AUDIO_FLAG_BYPASS_MUTE),
+    MAKE_STRING_FROM_ENUM(AUDIO_FLAG_LOW_LATENCY),
+    MAKE_STRING_FROM_ENUM(AUDIO_FLAG_DEEP_BUFFER),
+    TERMINATOR
+};
+
 template class TypeConverter<OutputDeviceTraits>;
 template class TypeConverter<InputDeviceTraits>;
 template class TypeConverter<OutputFlagTraits>;
@@ -374,6 +391,7 @@
 template class TypeConverter<AudioModeTraits>;
 template class TypeConverter<UsageTraits>;
 template class TypeConverter<SourceTraits>;
+template class TypeConverter<AudioFlagTraits>;
 
 bool deviceFromString(const std::string& literalDevice, audio_devices_t& device) {
     return InputDeviceConverter::fromString(literalDevice, device) ||
diff --git a/media/libmedia/include/media/TypeConverter.h b/media/libmedia/include/media/TypeConverter.h
index 86f0d4c..418e09c 100644
--- a/media/libmedia/include/media/TypeConverter.h
+++ b/media/libmedia/include/media/TypeConverter.h
@@ -20,6 +20,7 @@
 #include <string>
 #include <string.h>
 
+#include <vector>
 #include <system/audio.h>
 #include <utils/Log.h>
 #include <utils/Vector.h>
@@ -30,77 +31,55 @@
 
 namespace android {
 
-struct SampleRateTraits
-{
-    typedef uint32_t Type;
-    typedef SortedVector<Type> Collection;
-};
-struct DeviceTraits
-{
-    typedef audio_devices_t Type;
-    typedef Vector<Type> Collection;
-};
-struct OutputDeviceTraits : public DeviceTraits {};
-struct InputDeviceTraits : public DeviceTraits {};
-struct OutputFlagTraits
-{
-    typedef audio_output_flags_t Type;
-    typedef Vector<Type> Collection;
-};
-struct InputFlagTraits
-{
-    typedef audio_input_flags_t Type;
-    typedef Vector<Type> Collection;
-};
-struct FormatTraits
-{
-    typedef audio_format_t Type;
-    typedef Vector<Type> Collection;
-};
-struct ChannelTraits
-{
-    typedef audio_channel_mask_t Type;
-    typedef SortedVector<Type> Collection;
-};
-struct OutputChannelTraits : public ChannelTraits {};
-struct InputChannelTraits : public ChannelTraits {};
-struct ChannelIndexTraits : public ChannelTraits {};
-struct GainModeTraits
-{
-    typedef audio_gain_mode_t Type;
-    typedef Vector<Type> Collection;
-};
-struct StreamTraits
-{
-    typedef audio_stream_type_t Type;
-    typedef Vector<Type> Collection;
-};
-struct AudioModeTraits
-{
-    typedef audio_mode_t Type;
-    typedef Vector<Type> Collection;
-};
-struct AudioContentTraits
-{
-    typedef audio_content_type_t Type;
-    typedef Vector<Type> Collection;
-};
-struct UsageTraits
-{
-    typedef audio_usage_t Type;
-    typedef Vector<Type> Collection;
-};
-struct SourceTraits
-{
-    typedef audio_source_t Type;
-    typedef Vector<Type> Collection;
-};
 template <typename T>
 struct DefaultTraits
 {
     typedef T Type;
-    typedef Vector<Type> Collection;
+    typedef std::vector<Type> Collection;
+    static void add(Collection &collection, Type value)
+    {
+        collection.push_back(value);
+    }
 };
+template <typename T>
+struct VectorTraits
+{
+    typedef T Type;
+    typedef Vector<Type> Collection;
+    static void add(Collection &collection, Type value)
+    {
+        collection.add(value);
+    }
+};
+template <typename T>
+struct SortedVectorTraits
+{
+    typedef T Type;
+    typedef SortedVector<Type> Collection;
+    static void add(Collection &collection, Type value)
+    {
+        collection.add(value);
+    }
+};
+
+using SampleRateTraits = SortedVectorTraits<uint32_t>;
+using DeviceTraits = DefaultTraits<audio_devices_t>;
+struct OutputDeviceTraits : public DeviceTraits {};
+struct InputDeviceTraits : public DeviceTraits {};
+using ChannelTraits = SortedVectorTraits<audio_channel_mask_t>;
+struct OutputChannelTraits : public ChannelTraits {};
+struct InputChannelTraits : public ChannelTraits {};
+struct ChannelIndexTraits : public ChannelTraits {};
+using InputFlagTraits = DefaultTraits<audio_input_flags_t>;
+using OutputFlagTraits = DefaultTraits<audio_output_flags_t>;
+using FormatTraits = VectorTraits<audio_format_t>;
+using GainModeTraits = DefaultTraits<audio_gain_mode_t>;
+using StreamTraits = DefaultTraits<audio_stream_type_t>;
+using AudioModeTraits = DefaultTraits<audio_mode_t>;
+using AudioContentTraits = DefaultTraits<audio_content_type_t>;
+using UsageTraits = DefaultTraits<audio_usage_t>;
+using SourceTraits = DefaultTraits<audio_source_t>;
+struct AudioFlagTraits : public DefaultTraits<audio_flags_mask_t> {};
 
 template <class Traits>
 static void collectionFromString(const std::string &str, typename Traits::Collection &collection,
@@ -110,7 +89,7 @@
     for (const char *cstr = strtok(literal, del); cstr != NULL; cstr = strtok(NULL, del)) {
         typename Traits::Type value;
         if (utilities::convertTo<std::string, typename Traits::Type >(cstr, value)) {
-            collection.add(value);
+            Traits::add(collection, value);
         }
     }
     free(literal);
@@ -181,7 +160,7 @@
     for (const char *cstr = strtok(literal, del); cstr != NULL; cstr = strtok(NULL, del)) {
         typename Traits::Type value;
         if (fromString(cstr, value)) {
-            collection.add(value);
+            Traits::add(collection, value);
         }
     }
     free(literal);
@@ -234,6 +213,7 @@
 typedef TypeConverter<AudioContentTraits> AudioContentTypeConverter;
 typedef TypeConverter<UsageTraits> UsageTypeConverter;
 typedef TypeConverter<SourceTraits> SourceTypeConverter;
+typedef TypeConverter<AudioFlagTraits> AudioFlagConverter;
 
 template<> const OutputDeviceConverter::Table OutputDeviceConverter::mTable[];
 template<> const InputDeviceConverter::Table InputDeviceConverter::mTable[];
@@ -249,6 +229,7 @@
 template<> const AudioContentTypeConverter::Table AudioContentTypeConverter::mTable[];
 template<> const UsageTypeConverter::Table UsageTypeConverter::mTable[];
 template<> const SourceTypeConverter::Table SourceTypeConverter::mTable[];
+template<> const AudioFlagConverter::Table AudioFlagConverter::mTable[];
 
 bool deviceFromString(const std::string& literalDevice, audio_devices_t& device);
 
@@ -274,6 +255,69 @@
 OutputChannelTraits::Collection outputChannelMasksFromString(
         const std::string &outChannels, const char *del = AudioParameter::valueListSeparator);
 
+static inline std::string toString(audio_usage_t usage)
+{
+    std::string usageLiteral;
+    if (!android::UsageTypeConverter::toString(usage, usageLiteral)) {
+        ALOGV("failed to convert usage: %d", usage);
+        return "AUDIO_USAGE_UNKNOWN";
+    }
+    return usageLiteral;
+}
+
+static inline std::string toString(audio_content_type_t content)
+{
+    std::string contentLiteral;
+    if (!android::AudioContentTypeConverter::toString(content, contentLiteral)) {
+        ALOGV("failed to convert content type: %d", content);
+        return "AUDIO_CONTENT_TYPE_UNKNOWN";
+    }
+    return contentLiteral;
+}
+
+static inline std::string toString(audio_stream_type_t stream)
+{
+    std::string streamLiteral;
+    if (!android::StreamTypeConverter::toString(stream, streamLiteral)) {
+        ALOGV("failed to convert stream: %d", stream);
+        return "AUDIO_STREAM_DEFAULT";
+    }
+    return streamLiteral;
+}
+
+static inline std::string toString(audio_source_t source)
+{
+    std::string sourceLiteral;
+    if (!android::SourceTypeConverter::toString(source, sourceLiteral)) {
+        ALOGV("failed to convert source: %d", source);
+        return "AUDIO_SOURCE_DEFAULT";
+    }
+    return sourceLiteral;
+}
+
+static inline std::string toString(const audio_attributes_t &attributes)
+{
+    std::ostringstream result;
+    result << "{ Content type: " << toString(attributes.content_type)
+           << " Usage: " << toString(attributes.usage)
+           << " Source: " << toString(attributes.source)
+           << " Flags: " << attributes.flags
+           << " Tags: " << attributes.tags
+           << " }";
+
+    return result.str();
+}
+
+static inline std::string toString(audio_mode_t mode)
+{
+    std::string modeLiteral;
+    if (!android::AudioModeConverter::toString(mode, modeLiteral)) {
+        ALOGV("failed to convert mode: %d", mode);
+        return "AUDIO_MODE_INVALID";
+    }
+    return modeLiteral;
+}
+
 }; // namespace android
 
 #endif  /*ANDROID_TYPE_CONVERTER_H_*/
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/AudioRoute.h b/services/audiopolicy/common/managerdefinitions/include/AudioRoute.h
index 330f1d4..0357ff4 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioRoute.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioRoute.h
@@ -46,6 +46,19 @@
 
     audio_route_type_t getType() const { return mType; }
 
+    /**
+     * @brief supportsPatch checks if an audio patch is supported by a Route declared in
+     * the audio_policy_configuration.xml file.
+     * If the patch is supported natively by an AudioHAL (which supports of course Routing API 3.0),
+     * audiopolicy will not request AudioFlinger to use a software bridge to realize a patch
+     * between 2 ports.
+     * @param srcPort (aka the source) to be considered
+     * @param dstPort (aka the sink) to be considered
+     * @return true if the audio route supports the connection between the sink and the source,
+     * false otherwise
+     */
+    bool supportsPatch(const sp<AudioPort> &srcPort, const sp<AudioPort> &dstPort) const;
+
     void dump(String8 *dst, int spaces) const;
 
 private:
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/HwModule.h b/services/audiopolicy/common/managerdefinitions/include/HwModule.h
index 6560431..2b57fa9 100644
--- a/services/audiopolicy/common/managerdefinitions/include/HwModule.h
+++ b/services/audiopolicy/common/managerdefinitions/include/HwModule.h
@@ -81,6 +81,17 @@
         return mPorts.findByTagName(tagName);
     }
 
+    /**
+     * @brief supportsPatch checks if an audio patch between 2 ports beloging to this HwModule
+     * is supported by a HwModule. The ports and the route shall be declared in the
+     * audio_policy_configuration.xml file.
+     * @param srcPort (aka the source) to be considered
+     * @param dstPort (aka the sink) to be considered
+     * @return true if the HwModule supports the connection between the sink and the source,
+     * false otherwise
+     */
+    bool supportsPatch(const sp<AudioPort> &srcPort, const sp<AudioPort> &dstPort) const;
+
     // TODO remove from here (split serialization)
     void dump(String8 *dst) const;
 
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/include/TypeConverter.h b/services/audiopolicy/common/managerdefinitions/include/TypeConverter.h
index 63c19d1..6b0476c 100644
--- a/services/audiopolicy/common/managerdefinitions/include/TypeConverter.h
+++ b/services/audiopolicy/common/managerdefinitions/include/TypeConverter.h
@@ -23,26 +23,10 @@
 
 namespace android {
 
-struct DeviceCategoryTraits
-{
-    typedef device_category Type;
-    typedef Vector<Type> Collection;
-};
-struct MixTypeTraits
-{
-    typedef int32_t Type;
-    typedef Vector<Type> Collection;
-};
-struct RouteFlagTraits
-{
-    typedef uint32_t Type;
-    typedef Vector<Type> Collection;
-};
-struct RuleTraits
-{
-    typedef uint32_t Type;
-    typedef Vector<Type> Collection;
-};
+struct RuleTraits : public DefaultTraits<uint32_t> {};
+using DeviceCategoryTraits = DefaultTraits<device_category>;
+struct MixTypeTraits : public DefaultTraits<int32_t> {};
+struct RouteFlagTraits : public DefaultTraits<uint32_t> {};
 
 typedef TypeConverter<DeviceCategoryTraits> DeviceCategoryConverter;
 typedef TypeConverter<MixTypeTraits> MixTypeConverter;
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/AudioRoute.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioRoute.cpp
index c1fe5b0..79f0919 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioRoute.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioRoute.cpp
@@ -37,4 +37,19 @@
     dst->append("\n");
 }
 
+bool AudioRoute::supportsPatch(const sp<AudioPort> &srcPort, const sp<AudioPort> &dstPort) const
+{
+    if (mSink == 0 || dstPort == 0 || dstPort != mSink) {
+        return false;
+    }
+    ALOGV("%s: sinks %s matching", __FUNCTION__, mSink->getTagName().string());
+    for (const auto &sourcePort : mSources) {
+        if (sourcePort == srcPort) {
+            ALOGV("%s: sources %s matching", __FUNCTION__, sourcePort->getTagName().string());
+            return true;
+        }
+    }
+    return false;
+}
+
 }
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 92bc595..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",
@@ -218,6 +218,15 @@
     mHandle = handle;
 }
 
+bool HwModule::supportsPatch(const sp<AudioPort> &srcPort, const sp<AudioPort> &dstPort) const {
+    for (const auto &route : mRoutes) {
+        if (route->supportsPatch(srcPort, dstPort)) {
+            return true;
+        }
+    }
+    return false;
+}
+
 void HwModule::dump(String8 *dst) const
 {
     dst->appendFormat("  - name: %s\n", getName());
@@ -287,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 179a678..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;
 }
 
@@ -742,7 +742,7 @@
             }
             ALOGV("%s: %s=%s",
                     __func__, tag, reinterpret_cast<const char*>(pointDefinition.get()));
-            Vector<int32_t> point;
+            std::vector<int32_t> point;
             collectionFromString<DefaultTraits<int32_t>>(
                     reinterpret_cast<const char*>(pointDefinition.get()), point, ",");
             if (point.size() != 2) {
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index f07b797..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
@@ -780,17 +780,39 @@
     return output;
 }
 
-status_t AudioPolicyManager::getOutputForAttr(const audio_attributes_t *attr,
-                                              audio_io_handle_t *output,
-                                              audio_session_t session,
-                                              audio_stream_type_t *stream,
-                                              uid_t uid,
-                                              const audio_config_t *config,
-                                              audio_output_flags_t *flags,
-                                              audio_port_handle_t *selectedDeviceId,
-                                              audio_port_handle_t *portId)
+status_t AudioPolicyManager::getAudioAttributes(audio_attributes_t *dstAttr,
+                                                const audio_attributes_t *srcAttr,
+                                                audio_stream_type_t srcStream)
 {
-    audio_attributes_t attributes;
+    if (srcAttr != NULL) {
+        if (!isValidAttributes(srcAttr)) {
+            ALOGE("%s invalid attributes: usage=%d content=%d flags=0x%x tags=[%s]",
+                    __func__,
+                    srcAttr->usage, srcAttr->content_type, srcAttr->flags,
+                    srcAttr->tags);
+            return BAD_VALUE;
+        }
+        *dstAttr = *srcAttr;
+    } else {
+        if (srcStream < AUDIO_STREAM_MIN || srcStream >= AUDIO_STREAM_PUBLIC_CNT) {
+            ALOGE("%s:  invalid stream type", __func__);
+            return BAD_VALUE;
+        }
+        stream_type_to_audio_attributes(srcStream, dstAttr);
+    }
+    return NO_ERROR;
+}
+
+status_t AudioPolicyManager::getOutputForAttrInt(audio_attributes_t *resultAttr,
+                                                 audio_io_handle_t *output,
+                                                 audio_session_t session,
+                                                 const audio_attributes_t *attr,
+                                                 audio_stream_type_t *stream,
+                                                 uid_t uid,
+                                                 const audio_config_t *config,
+                                                 audio_output_flags_t *flags,
+                                                 audio_port_handle_t *selectedDeviceId)
+{
     DeviceVector outputDevices;
     routing_strategy strategy;
     audio_devices_t device;
@@ -798,35 +820,20 @@
     audio_devices_t msdDevice =
             getModuleDeviceTypes(mAvailableOutputDevices, AUDIO_HARDWARE_MODULE_ID_MSD);
 
-    // The supplied portId must be AUDIO_PORT_HANDLE_NONE
-    if (*portId != AUDIO_PORT_HANDLE_NONE) {
-        return INVALID_OPERATION;
+    status_t status = getAudioAttributes(resultAttr, attr, *stream);
+    if (status != NO_ERROR) {
+        return status;
     }
 
-    if (attr != NULL) {
-        if (!isValidAttributes(attr)) {
-            ALOGE("getOutputForAttr() invalid attributes: usage=%d content=%d flags=0x%x tags=[%s]",
-                  attr->usage, attr->content_type, attr->flags,
-                  attr->tags);
-            return BAD_VALUE;
-        }
-        attributes = *attr;
-    } else {
-        if (*stream < AUDIO_STREAM_MIN || *stream >= AUDIO_STREAM_PUBLIC_CNT) {
-            ALOGE("getOutputForAttr():  invalid stream type");
-            return BAD_VALUE;
-        }
-        stream_type_to_audio_attributes(*stream, &attributes);
-    }
-
-    ALOGV("getOutputForAttr() usage=%d, content=%d, tag=%s flags=%08x"
+    ALOGV("%s usage=%d, content=%d, tag=%s flags=%08x"
           " session %d selectedDeviceId %d",
-          attributes.usage, attributes.content_type, attributes.tags, attributes.flags,
+          __func__,
+          resultAttr->usage, resultAttr->content_type, resultAttr->tags, resultAttr->flags,
           session, requestedDeviceId);
 
-    *stream = streamTypefromAttributesInt(&attributes);
+    *stream = streamTypefromAttributesInt(resultAttr);
 
-    strategy = getStrategyForAttr(&attributes);
+    strategy = getStrategyForAttr(resultAttr);
 
     // First check for explicit routing (eg. setPreferredDevice)
     if (requestedDeviceId != AUDIO_PORT_HANDLE_NONE) {
@@ -836,30 +843,30 @@
     } else {
         // If no explict route, is there a matching dynamic policy that applies?
         sp<SwAudioOutputDescriptor> desc;
-        if (mPolicyMixes.getOutputForAttr(attributes, uid, desc) == NO_ERROR) {
+        if (mPolicyMixes.getOutputForAttr(*resultAttr, uid, desc) == NO_ERROR) {
             ALOG_ASSERT(desc != 0, "Invalid desc returned by getOutputForAttr");
             if (!audio_has_proportional_frames(config->format)) {
                 return BAD_VALUE;
             }
-            *stream = streamTypefromAttributesInt(&attributes);
+            *stream = streamTypefromAttributesInt(resultAttr);
             *output = desc->mIoHandle;
             AudioMix *mix = desc->mPolicyMix;
             sp<DeviceDescriptor> deviceDesc =
                 mAvailableOutputDevices.getDevice(mix->mDeviceType, mix->mDeviceAddress);
             *selectedDeviceId = deviceDesc != 0 ? deviceDesc->getId() : AUDIO_PORT_HANDLE_NONE;
-            ALOGV("getOutputForAttr() returns output %d", *output);
-            goto exit;
+            ALOGV("%s returns output %d", __func__, *output);
+            return NO_ERROR;
         }
 
         // Virtual sources must always be dynamicaly or explicitly routed
-        if (attributes.usage == AUDIO_USAGE_VIRTUAL_SOURCE) {
-            ALOGW("getOutputForAttr() no policy mix found for usage AUDIO_USAGE_VIRTUAL_SOURCE");
+        if (resultAttr->usage == AUDIO_USAGE_VIRTUAL_SOURCE) {
+            ALOGW("%s no policy mix found for usage AUDIO_USAGE_VIRTUAL_SOURCE", __func__);
             return BAD_VALUE;
         }
         device = getDeviceForStrategy(strategy, false /*fromCache*/);
     }
 
-    if ((attributes.flags & AUDIO_FLAG_HW_AV_SYNC) != 0) {
+    if ((resultAttr->flags & AUDIO_FLAG_HW_AV_SYNC) != 0) {
         *flags = (audio_output_flags_t)(*flags | AUDIO_OUTPUT_FLAG_HW_AV_SYNC);
     }
 
@@ -869,7 +876,7 @@
     // to getOutputForDevice.
     // TODO: Remove check of AUDIO_STREAM_MUSIC once migration is completed on the app side.
     if (device == AUDIO_DEVICE_OUT_TELEPHONY_TX &&
-        (*stream == AUDIO_STREAM_MUSIC || attributes.usage == AUDIO_USAGE_VOICE_COMMUNICATION) &&
+        (*stream == AUDIO_STREAM_MUSIC || resultAttr->usage == AUDIO_USAGE_VOICE_COMMUNICATION) &&
         audio_is_linear_pcm(config->format) &&
         isInCall()) {
         if (requestedDeviceId != AUDIO_PORT_HANDLE_NONE) {
@@ -880,9 +887,9 @@
         }
     }
 
-    ALOGV("getOutputForAttr() device 0x%x, sampling rate %d, format %#x, channel mask %#x, "
+    ALOGV("%s device 0x%x, sampling rate %d, format %#x, channel mask %#x, "
           "flags %#x",
-          device, config->sample_rate, config->format, config->channel_mask, *flags);
+          __func__, device, config->sample_rate, config->format, config->channel_mask, *flags);
 
     *output = AUDIO_IO_HANDLE_NONE;
     if (msdDevice != AUDIO_DEVICE_NONE) {
@@ -903,25 +910,50 @@
     }
 
     outputDevices = mAvailableOutputDevices.getDevicesFromTypeMask(device);
-    *selectedDeviceId = outputDevices.size() > 0 ? outputDevices.itemAt(0)->getId()
-            : AUDIO_PORT_HANDLE_NONE;
+    *selectedDeviceId = getFirstDeviceId(outputDevices);
 
-exit:
+    ALOGV("%s returns output %d selectedDeviceId %d", __func__, *output, *selectedDeviceId);
+
+    return NO_ERROR;
+}
+
+status_t AudioPolicyManager::getOutputForAttr(const audio_attributes_t *attr,
+                                              audio_io_handle_t *output,
+                                              audio_session_t session,
+                                              audio_stream_type_t *stream,
+                                              uid_t uid,
+                                              const audio_config_t *config,
+                                              audio_output_flags_t *flags,
+                                              audio_port_handle_t *selectedDeviceId,
+                                              audio_port_handle_t *portId)
+{
+    // The supplied portId must be AUDIO_PORT_HANDLE_NONE
+    if (*portId != AUDIO_PORT_HANDLE_NONE) {
+        return INVALID_OPERATION;
+    }
+    const audio_port_handle_t requestedDeviceId = *selectedDeviceId;
+    audio_attributes_t resultAttr;
+    status_t status = getOutputForAttrInt(&resultAttr, output, session, attr, stream, uid,
+            config, flags, selectedDeviceId);
+    if (status != NO_ERROR) {
+        return status;
+    }
+
     audio_config_base_t clientConfig = {.sample_rate = config->sample_rate,
         .format = config->format,
         .channel_mask = config->channel_mask };
     *portId = AudioPort::getNextUniqueId();
 
     sp<TrackClientDescriptor> clientDesc =
-        new TrackClientDescriptor(*portId, uid, session, attributes, clientConfig,
+        new TrackClientDescriptor(*portId, uid, session, resultAttr, clientConfig,
                                   requestedDeviceId, *stream,
-                                  getStrategyForAttr(&attributes),
+                                  getStrategyForAttr(&resultAttr),
                                   *flags);
     sp<SwAudioOutputDescriptor> outputDesc = mOutputs.valueFor(*output);
     outputDesc->addClient(clientDesc);
 
-    ALOGV("  getOutputForAttr() returns output %d selectedDeviceId %d for port ID %d",
-          *output, *selectedDeviceId, *portId);
+    ALOGV("%s returns output %d selectedDeviceId %d for port ID %d",
+          __func__, *output, requestedDeviceId, *portId);
 
     return NO_ERROR;
 }
@@ -1020,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.
@@ -1722,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
@@ -1831,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;
@@ -1963,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,
@@ -2930,7 +2957,7 @@
             }
 
             if (!outputDesc->mProfile->isCompatibleProfile(devDesc->type(),
-                                                           devDesc->mAddress,
+                                                           devDesc->address(),
                                                            patch->sources[0].sample_rate,
                                                            NULL,  // updatedSamplingRate
                                                            patch->sources[0].format,
@@ -2987,7 +3014,7 @@
             }
 
             if (!inputDesc->mProfile->isCompatibleProfile(devDesc->type(),
-                                                          devDesc->mAddress,
+                                                          devDesc->address(),
                                                           patch->sinks[0].sample_rate,
                                                           NULL, /*updatedSampleRate*/
                                                           patch->sinks[0].format,
@@ -3050,8 +3077,10 @@
                 // create a software bridge in PatchPanel if:
                 // - source and sink devices are on different HW modules OR
                 // - 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->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;
@@ -3395,16 +3424,25 @@
 
     audio_patch_handle_t afPatchHandle = AUDIO_PATCH_HANDLE_NONE;
 
-    if (srcDeviceDesc->getAudioPort()->mModule->getHandle() ==
-            sinkDeviceDesc->getAudioPort()->mModule->getHandle() &&
-            srcDeviceDesc->getAudioPort()->mModule->getHalVersionMajor() >= 3 &&
+    if (srcDeviceDesc->hasSameHwModuleAs(sinkDeviceDesc) &&
+            srcDeviceDesc->getModuleVersionMajor() >= 3 &&
+            sinkDeviceDesc->getModule()->supportsPatch(srcDeviceDesc, sinkDeviceDesc) &&
             srcDeviceDesc->getAudioPort()->mGains.size() > 0) {
-        ALOGV("%s AUDIO_DEVICE_API_VERSION_3_0", __FUNCTION__);
+        ALOGV("%s Device to Device route supported by >=3.0 HAL", __FUNCTION__);
+        // TODO: may explicitly specify whether we should use HW or SW patch
         //   create patch between src device and output device
         //   create Hwoutput and add to mHwOutputs
     } else {
-        SortedVector<audio_io_handle_t> outputs = getOutputsForDevice(sinkDevice, mOutputs);
-        audio_io_handle_t output = selectOutput(outputs);
+        audio_attributes_t resultAttr;
+        audio_io_handle_t output = AUDIO_IO_HANDLE_NONE;
+        audio_config_t config = AUDIO_CONFIG_INITIALIZER;
+        config.sample_rate = sourceDesc->config().sample_rate;
+        config.channel_mask = sourceDesc->config().channel_mask;
+        config.format = sourceDesc->config().format;
+        audio_output_flags_t flags = AUDIO_OUTPUT_FLAG_NONE;
+        audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE;
+        getOutputForAttrInt(&resultAttr, &output, AUDIO_SESSION_NONE,
+                &attributes, &stream, sourceDesc->uid(), &config, &flags, &selectedDeviceId);
         if (output == AUDIO_IO_HANDLE_NONE) {
             ALOGV("%s no output for device %08x", __FUNCTION__, sinkDevice);
             return INVALID_OPERATION;
@@ -3437,6 +3475,13 @@
                   __FUNCTION__, status);
             return INVALID_OPERATION;
         }
+
+        if (outputDesc->getClient(sourceDesc->portId()) != nullptr) {
+            ALOGW("%s source portId has already been attached to outputDesc", __func__);
+            return INVALID_OPERATION;
+        }
+        outputDesc->addClient(sourceDesc);
+
         uint32_t delayMs = 0;
         status = startSource(outputDesc, sourceDesc, &delayMs);
 
@@ -3615,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,
@@ -3635,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,
@@ -3893,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);
@@ -3948,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!");
 
@@ -4011,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);
             }
         }
     }
@@ -5184,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 d0708b8..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);
@@ -661,6 +674,21 @@
                 const String8& address /*in*/,
                 SortedVector<audio_io_handle_t>& outputs /*out*/);
         uint32_t curAudioPortGeneration() const { return mAudioPortGeneration; }
+        // internal method, get audio_attributes_t from either a source audio_attributes_t
+        // or audio_stream_type_t, respectively.
+        status_t getAudioAttributes(audio_attributes_t *dstAttr,
+                const audio_attributes_t *srcAttr,
+                audio_stream_type_t srcStream);
+        // internal method, called by getOutputForAttr() and connectAudioSource.
+        status_t getOutputForAttrInt(audio_attributes_t *resultAttr,
+                audio_io_handle_t *output,
+                audio_session_t session,
+                const audio_attributes_t *attr,
+                audio_stream_type_t *stream,
+                uid_t uid,
+                const audio_config_t *config,
+                audio_output_flags_t *flags,
+                audio_port_handle_t *selectedDeviceId);
         // internal method to return the output handle for the given device and format
         audio_io_handle_t getOutputForDevice(
                 audio_devices_t device,
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
index c1a4c11..46fbc3e 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
@@ -256,7 +256,7 @@
         Vector<int32_t> outputStreamIds;
         std::vector<std::string> requestedPhysicalIds;
         if (request.mSurfaceList.size() > 0) {
-            for (sp<Surface> surface : request.mSurfaceList) {
+            for (const sp<Surface>& surface : request.mSurfaceList) {
                 if (surface == 0) continue;
 
                 int32_t streamId;
diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp
index 856af13..12fbf82 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Device.cpp
@@ -175,7 +175,7 @@
         session->interfaceChain([](
             ::android::hardware::hidl_vec<::android::hardware::hidl_string> interfaceChain) {
                 ALOGV("Session interface chain:");
-                for (auto iface : interfaceChain) {
+                for (const auto& iface : interfaceChain) {
                     ALOGV("  %s", iface.c_str());
                 }
             });
diff --git a/services/oboeservice/AAudioEndpointManager.cpp b/services/oboeservice/AAudioEndpointManager.cpp
index cca1895..a1fc0ea 100644
--- a/services/oboeservice/AAudioEndpointManager.cpp
+++ b/services/oboeservice/AAudioEndpointManager.cpp
@@ -108,7 +108,7 @@
         const AAudioStreamConfiguration &configuration) {
     sp<AAudioServiceEndpoint> endpoint;
     mExclusiveSearchCount++;
-    for (const auto ep : mExclusiveStreams) {
+    for (const auto& ep : mExclusiveStreams) {
         if (ep->matches(configuration)) {
             mExclusiveFoundCount++;
             endpoint = ep;
@@ -126,7 +126,7 @@
         const AAudioStreamConfiguration &configuration) {
     sp<AAudioServiceEndpointShared> endpoint;
     mSharedSearchCount++;
-    for (const auto ep  : mSharedStreams) {
+    for (const auto& ep  : mSharedStreams) {
         if (ep->matches(configuration)) {
             mSharedFoundCount++;
             endpoint = ep;
diff --git a/services/oboeservice/AAudioServiceEndpoint.cpp b/services/oboeservice/AAudioServiceEndpoint.cpp
index 539735a..4dfb62a 100644
--- a/services/oboeservice/AAudioServiceEndpoint.cpp
+++ b/services/oboeservice/AAudioServiceEndpoint.cpp
@@ -65,7 +65,7 @@
     result << "    Connected:            " << mConnected.load() << "\n";
     result << "    Registered Streams:" << "\n";
     result << AAudioServiceStreamShared::dumpHeader() << "\n";
-    for (const auto stream : mRegisteredStreams) {
+    for (const auto& stream : mRegisteredStreams) {
         result << stream->dump() << "\n";
     }
 
@@ -78,7 +78,7 @@
 // @return true if stream found
 bool AAudioServiceEndpoint::isStreamRegistered(audio_port_handle_t portHandle) {
     std::lock_guard<std::mutex> lock(mLockStreams);
-    for (const auto stream : mRegisteredStreams) {
+    for (const auto& stream : mRegisteredStreams) {
         if (stream->getPortHandle() == portHandle) {
             return true;
         }
@@ -89,7 +89,7 @@
 void AAudioServiceEndpoint::disconnectRegisteredStreams() {
     std::lock_guard<std::mutex> lock(mLockStreams);
     mConnected.store(false);
-    for (const auto stream : mRegisteredStreams) {
+    for (const auto& stream : mRegisteredStreams) {
         ALOGD("disconnectRegisteredStreams() stop and disconnect %p", stream.get());
         stream->stop();
         stream->disconnect();
diff --git a/services/oboeservice/AAudioServiceEndpointCapture.cpp b/services/oboeservice/AAudioServiceEndpointCapture.cpp
index 7ae7f1b..37d105b 100644
--- a/services/oboeservice/AAudioServiceEndpointCapture.cpp
+++ b/services/oboeservice/AAudioServiceEndpointCapture.cpp
@@ -81,9 +81,10 @@
         { // brackets are for lock_guard
 
             std::lock_guard <std::mutex> lock(mLockStreams);
-            for (const auto clientStream : mRegisteredStreams) {
-                if (clientStream->isRunning()) {
+            for (const auto& clientStream : mRegisteredStreams) {
+                if (clientStream->isRunning() && !clientStream->isSuspended()) {
                     int64_t clientFramesWritten = 0;
+
                     sp<AAudioServiceStreamShared> streamShared =
                             static_cast<AAudioServiceStreamShared *>(clientStream.get());
 
diff --git a/services/oboeservice/AAudioServiceEndpointMMAP.cpp b/services/oboeservice/AAudioServiceEndpointMMAP.cpp
index e4dbee1..6c28083 100644
--- a/services/oboeservice/AAudioServiceEndpointMMAP.cpp
+++ b/services/oboeservice/AAudioServiceEndpointMMAP.cpp
@@ -371,7 +371,7 @@
     float volume = values[0];
     ALOGD("%s(%p) volume[0] = %f", __func__, this, volume);
     std::lock_guard<std::mutex> lock(mLockStreams);
-    for(const auto stream : mRegisteredStreams) {
+    for(const auto& stream : mRegisteredStreams) {
         stream->onVolumeChanged(volume);
     }
 };
diff --git a/services/oboeservice/AAudioServiceEndpointPlay.cpp b/services/oboeservice/AAudioServiceEndpointPlay.cpp
index 923a1a4..1e1c552 100644
--- a/services/oboeservice/AAudioServiceEndpointPlay.cpp
+++ b/services/oboeservice/AAudioServiceEndpointPlay.cpp
@@ -80,10 +80,14 @@
             int64_t mmapFramesWritten = getStreamInternal()->getFramesWritten();
 
             std::lock_guard <std::mutex> lock(mLockStreams);
-            for (const auto clientStream : mRegisteredStreams) {
+            for (const auto& clientStream : mRegisteredStreams) {
                 int64_t clientFramesRead = 0;
                 bool allowUnderflow = true;
 
+                if (clientStream->isSuspended()) {
+                    continue; // dead stream
+                }
+
                 aaudio_stream_state_t state = clientStream->getState();
                 if (state == AAUDIO_STREAM_STATE_STOPPING) {
                     allowUnderflow = false; // just read what is already in the FIFO
diff --git a/services/oboeservice/AAudioServiceStreamBase.cpp b/services/oboeservice/AAudioServiceStreamBase.cpp
index 354b36a..defbb7b 100644
--- a/services/oboeservice/AAudioServiceStreamBase.cpp
+++ b/services/oboeservice/AAudioServiceStreamBase.cpp
@@ -179,6 +179,7 @@
     }
 
     setFlowing(false);
+    setSuspended(false);
 
     // Start with fresh presentation timestamps.
     mAtomicTimestamp.clear();
@@ -345,7 +346,9 @@
     }
     int32_t count = mUpMessageQueue->getFifoBuffer()->write(command, 1);
     if (count != 1) {
-        ALOGE("%s(): Queue full. Did client die? %s", __func__, getTypeText());
+        ALOGW("%s(): Queue full. Did client stop? Suspending stream. what = %u, %s",
+              __func__, command->what, getTypeText());
+        setSuspended(true);
         return AAUDIO_ERROR_WOULD_BLOCK;
     } else {
         return AAUDIO_OK;
diff --git a/services/oboeservice/AAudioServiceStreamBase.h b/services/oboeservice/AAudioServiceStreamBase.h
index a1815d0..7904b25 100644
--- a/services/oboeservice/AAudioServiceStreamBase.h
+++ b/services/oboeservice/AAudioServiceStreamBase.h
@@ -204,6 +204,20 @@
     }
 
     /**
+     * Set false when the stream should not longer be processed.
+     * This may be caused by a message queue overflow.
+     * Set true when stream is started.
+     * @param suspended
+     */
+    void setSuspended(bool suspended) {
+        mSuspended = suspended;
+    }
+
+    bool isSuspended() const {
+        return mSuspended;
+    }
+
+    /**
      * Atomically increment the number of active references to the stream by AAudioService.
      *
      * This is called under a global lock in AAudioStreamTracker.
@@ -304,7 +318,12 @@
     // This is modified under a global lock in AAudioStreamTracker.
     int32_t                 mCallingCount = 0;
 
+    // This indicates that a stream that is being referenced by a binder call needs to closed.
     std::atomic<bool>       mCloseNeeded{false};
+
+    // This indicate that a running stream should not be processed because of an error,
+    // for example a full message queue. Note that this atomic is unrelated to mCloseNeeded.
+    std::atomic<bool>       mSuspended{false};
 };
 
 } /* namespace aaudio */