Merge "RecordBufferConverter: Release converter buffer after conversion" into qt-dev
diff --git a/camera/ndk/include/camera/NdkCameraMetadataTags.h b/camera/ndk/include/camera/NdkCameraMetadataTags.h
index ef5f26c..4563b41 100644
--- a/camera/ndk/include/camera/NdkCameraMetadataTags.h
+++ b/camera/ndk/include/camera/NdkCameraMetadataTags.h
@@ -7670,6 +7670,24 @@
      * <li>ACAMERA_LENS_POSE_REFERENCE</li>
      * <li>ACAMERA_LENS_DISTORTION</li>
      * </ul>
+     * <p>The field of view of all non-RAW physical streams must be the same or as close as
+     * possible to that of non-RAW logical streams. If the requested FOV is outside of the
+     * range supported by the physical camera, the physical stream for that physical camera
+     * will use either the maximum or minimum scaler crop region, depending on which one is
+     * closer to the requested FOV. For example, for a logical camera with wide-tele lens
+     * configuration where the wide lens is the default, if the logical camera's crop region
+     * is set to maximum, the physical stream for the tele lens will be configured to its
+     * maximum crop region. On the other hand, if the logical camera has a normal-wide lens
+     * configuration where the normal lens is the default, when the logical camera's crop
+     * region is set to maximum, the FOV of the logical streams will be that of the normal
+     * lens. The FOV of the physical streams for the wide lens will be the same as the
+     * logical stream, by making the crop region smaller than its active array size to
+     * compensate for the smaller focal length.</p>
+     * <p>Even if the underlying physical cameras have different RAW characteristics (such as
+     * size or CFA pattern), a logical camera can still advertise RAW capability. In this
+     * case, when the application configures a RAW stream, the camera device will make sure
+     * the active physical camera will remain active to ensure consistent RAW output
+     * behavior, and not switch to other physical cameras.</p>
      * <p>To maintain backward compatibility, the capture request and result metadata tags
      * required for basic camera functionalities will be solely based on the
      * logical camera capabiltity. Other request and result metadata tags, on the other
diff --git a/media/extractors/mkv/MatroskaExtractor.cpp b/media/extractors/mkv/MatroskaExtractor.cpp
index e284cda..a1c81f3 100644
--- a/media/extractors/mkv/MatroskaExtractor.cpp
+++ b/media/extractors/mkv/MatroskaExtractor.cpp
@@ -150,6 +150,7 @@
         AAC,
         HEVC,
         MP3,
+        PCM,
         OTHER
     };
 
@@ -270,6 +271,8 @@
         mType = AAC;
     } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_MPEG)) {
         mType = MP3;
+    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW)) {
+        mType = PCM;
     }
 }
 
@@ -1054,6 +1057,27 @@
                     AMEDIAFORMAT_KEY_TARGET_TIME, targetSampleTimeUs);
         }
 
+        if (mType == PCM) {
+            int32_t bitPerFrame = 16;
+            int32_t bigEndian = 0;
+            AMediaFormat *meta = AMediaFormat_new();
+            if (getFormat(meta) == AMEDIA_OK && meta != NULL) {
+                AMediaFormat_getInt32(meta,
+                                AMEDIAFORMAT_KEY_BITS_PER_SAMPLE, &bitPerFrame);
+                AMediaFormat_getInt32(meta,
+                                AMEDIAFORMAT_KEY_PCM_BIG_ENDIAN, &bigEndian);
+            }
+            AMediaFormat_delete(meta);
+            if (bigEndian == 1 && bitPerFrame == 16) {
+                // Big-endian -> little-endian
+                uint16_t *dstData = (uint16_t *)frame->data() + frame->range_offset();
+                uint16_t *srcData = (uint16_t *)frame->data() + frame->range_offset();
+                for (size_t i = 0; i < frame->range_length() / 2; i++) {
+                    dstData[i] = ntohs(srcData[i]);
+                }
+            }
+        }
+
         *out = frame;
 
         return AMEDIA_OK;
@@ -1170,6 +1194,51 @@
 
 ////////////////////////////////////////////////////////////////////////////////
 
+enum WaveID {
+    MKV_RIFF_WAVE_FORMAT_PCM = 0x0001,
+    MKV_RIFF_WAVE_FORMAT_ADPCM_ms = 0x0002,
+    MKV_RIFF_WAVE_FORMAT_ADPCM_ima_wav = 0x0011,
+    MKV_RIFF_WAVE_FORMAT_MPEGL12 = 0x0050,
+    MKV_RIFF_WAVE_FORMAT_MPEGL3 = 0x0055,
+    MKV_RIFF_WAVE_FORMAT_WMAV1 = 0x0160,
+    MKV_RIFF_WAVE_FORMAT_WMAV2 = 0x0161,
+};
+
+static const char *MKVWave2MIME(uint16_t id) {
+    switch (id) {
+        case  MKV_RIFF_WAVE_FORMAT_MPEGL12:
+            return MEDIA_MIMETYPE_AUDIO_MPEG_LAYER_II;
+
+        case  MKV_RIFF_WAVE_FORMAT_MPEGL3:
+            return MEDIA_MIMETYPE_AUDIO_MPEG;
+
+        case MKV_RIFF_WAVE_FORMAT_PCM:
+            return MEDIA_MIMETYPE_AUDIO_RAW;
+
+        case MKV_RIFF_WAVE_FORMAT_ADPCM_ms:
+            return MEDIA_MIMETYPE_AUDIO_MS_ADPCM;
+        case MKV_RIFF_WAVE_FORMAT_ADPCM_ima_wav:
+            return MEDIA_MIMETYPE_AUDIO_DVI_IMA_ADPCM;
+
+        case MKV_RIFF_WAVE_FORMAT_WMAV1:
+        case MKV_RIFF_WAVE_FORMAT_WMAV2:
+            return MEDIA_MIMETYPE_AUDIO_WMA;
+        default:
+            ALOGW("unknown wave %x", id);
+            return "";
+    };
+}
+
+static bool isMkvAudioCsdSizeOK(const char* mime, size_t csdSize) {
+    if ((!strcmp(mime, MEDIA_MIMETYPE_AUDIO_MS_ADPCM) && csdSize < 50) ||
+        (!strcmp(mime, MEDIA_MIMETYPE_AUDIO_DVI_IMA_ADPCM) && csdSize < 20) ||
+        (!strcmp(mime, MEDIA_MIMETYPE_AUDIO_WMA) && csdSize < 28) ||
+        (!strcmp(mime, MEDIA_MIMETYPE_AUDIO_MPEG) && csdSize < 30)) {
+        return false;
+    }
+    return true;
+}
+
 // trans all FOURCC  to lower char
 static uint32_t FourCCtoLower(uint32_t fourcc) {
     uint8_t ch_1 = tolower((fourcc >> 24) & 0xff);
@@ -2036,20 +2105,40 @@
                 } else if (!strcmp("A_FLAC", codecID)) {
                     AMediaFormat_setString(meta, AMEDIAFORMAT_KEY_MIME, MEDIA_MIMETYPE_AUDIO_FLAC);
                     err = addFlacMetadata(meta, codecPrivate, codecPrivateSize);
+                } else if (!strcmp("A_MPEG/L2", codecID)) {
+                    AMediaFormat_setString(meta,
+                            AMEDIAFORMAT_KEY_MIME, MEDIA_MIMETYPE_AUDIO_MPEG_LAYER_II);
+                } else if (!strcmp("A_PCM/INT/LIT", codecID) ||
+                         !strcmp("A_PCM/INT/BIG", codecID)) {
+                    AMediaFormat_setString(meta,
+                            AMEDIAFORMAT_KEY_MIME, MEDIA_MIMETYPE_AUDIO_RAW);
+                    int32_t bigEndian = !strcmp("A_PCM/INT/BIG", codecID) ? 1: 0;
+                    AMediaFormat_setInt32(meta,
+                            AMEDIAFORMAT_KEY_PCM_BIG_ENDIAN, bigEndian);
                 } else if ((!strcmp("A_MS/ACM", codecID))) {
-                    if ((NULL == codecPrivate) || (codecPrivateSize < 30)) {
+                    if ((NULL == codecPrivate) || (codecPrivateSize < 18)) {
                         ALOGW("unsupported audio: A_MS/ACM has no valid private data: %s, size: %zu",
                                codecPrivate == NULL ? "null" : "non-null", codecPrivateSize);
                         continue;
                     } else {
                         uint16_t ID = *(uint16_t *)codecPrivate;
-                        if (ID == 0x0055) {
-                            AMediaFormat_setString(meta,
-                                    AMEDIAFORMAT_KEY_MIME, MEDIA_MIMETYPE_AUDIO_MPEG);
+                        const char* mime = MKVWave2MIME(ID);
+                        ALOGV("A_MS/ACM type is %s", mime);
+                        if (!strncasecmp("audio/", mime, 6) &&
+                                isMkvAudioCsdSizeOK(mime, codecPrivateSize)) {
+                            AMediaFormat_setString(meta, AMEDIAFORMAT_KEY_MIME, mime);
                         } else {
-                            ALOGW("A_MS/ACM unsupported type , continue");
+                            ALOGE("A_MS/ACM continue, unsupported audio type=%s, csdSize:%zu",
+                                mime, codecPrivateSize);
                             continue;
                         }
+                        if (!strcmp(mime, MEDIA_MIMETYPE_AUDIO_WMA)) {
+                            addESDSFromCodecPrivate(meta, true, codecPrivate, codecPrivateSize);
+                        } else if (!strcmp(mime, MEDIA_MIMETYPE_AUDIO_MS_ADPCM) ||
+                                    !strcmp(mime, MEDIA_MIMETYPE_AUDIO_DVI_IMA_ADPCM)) {
+                            uint32_t blockAlign = *(uint16_t*)(codecPrivate + 12);
+                            addESDSFromCodecPrivate(meta, true, &blockAlign, sizeof(blockAlign));
+                        }
                     }
                 } else {
                     ALOGW("%s is not supported.", codecID);
@@ -2058,6 +2147,7 @@
 
                 AMediaFormat_setInt32(meta, AMEDIAFORMAT_KEY_SAMPLE_RATE, atrack->GetSamplingRate());
                 AMediaFormat_setInt32(meta, AMEDIAFORMAT_KEY_CHANNEL_COUNT, atrack->GetChannels());
+                AMediaFormat_setInt32(meta, AMEDIAFORMAT_KEY_BITS_PER_SAMPLE, atrack->GetBitDepth());
                 break;
             }
 
diff --git a/media/libaaudio/src/binding/AAudioBinderClient.cpp b/media/libaaudio/src/binding/AAudioBinderClient.cpp
index dd620e3..7b0d31f 100644
--- a/media/libaaudio/src/binding/AAudioBinderClient.cpp
+++ b/media/libaaudio/src/binding/AAudioBinderClient.cpp
@@ -97,8 +97,7 @@
                 status_t status = binder->linkToDeath(mAAudioClient);
                 // TODO review what we should do if this fails
                 if (status != NO_ERROR) {
-                    ALOGE("getAAudioService: linkToDeath(mAAudioClient = %p) returned %d",
-                          mAAudioClient.get(), status);
+                    ALOGE("%s() - linkToDeath() returned %d", __func__, status);
                 }
                 mAAudioService = interface_cast<IAAudioService>(binder);
                 needToRegister = true;
diff --git a/media/libaaudio/src/binding/SharedMemoryParcelable.cpp b/media/libaaudio/src/binding/SharedMemoryParcelable.cpp
index 67955e8..b6e8472 100644
--- a/media/libaaudio/src/binding/SharedMemoryParcelable.cpp
+++ b/media/libaaudio/src/binding/SharedMemoryParcelable.cpp
@@ -157,5 +157,4 @@
 void SharedMemoryParcelable::dump() {
     ALOGD("mFd = %d", mFd.get());
     ALOGD("mSizeInBytes = %d", mSizeInBytes);
-    ALOGD("mResolvedAddress = %p", mResolvedAddress);
 }
diff --git a/media/libaaudio/src/client/AAudioFlowGraph.cpp b/media/libaaudio/src/client/AAudioFlowGraph.cpp
index 3e43c6b..8f2c488 100644
--- a/media/libaaudio/src/client/AAudioFlowGraph.cpp
+++ b/media/libaaudio/src/client/AAudioFlowGraph.cpp
@@ -38,7 +38,7 @@
                           int32_t sinkChannelCount) {
     AudioFloatOutputPort *lastOutput = nullptr;
 
-    ALOGD("%s() source format = 0x%08x, channels = %d, sink format = 0x%08x, channels = %d",
+    ALOGV("%s() source format = 0x%08x, channels = %d, sink format = 0x%08x, channels = %d",
           __func__, sourceFormat, sourceChannelCount, sinkFormat, sinkChannelCount);
 
     switch (sourceFormat) {
diff --git a/media/libaaudio/src/client/AudioStreamInternal.cpp b/media/libaaudio/src/client/AudioStreamInternal.cpp
index ec270f3..db98d58 100644
--- a/media/libaaudio/src/client/AudioStreamInternal.cpp
+++ b/media/libaaudio/src/client/AudioStreamInternal.cpp
@@ -195,13 +195,13 @@
     if (isDataCallbackSet()) {
         mCallbackFrames = builder.getFramesPerDataCallback();
         if (mCallbackFrames > getBufferCapacity() / 2) {
-            ALOGE("%s - framesPerCallback too big = %d, capacity = %d",
+            ALOGW("%s - framesPerCallback too big = %d, capacity = %d",
                   __func__, mCallbackFrames, getBufferCapacity());
             result = AAUDIO_ERROR_OUT_OF_RANGE;
             goto error;
 
         } else if (mCallbackFrames < 0) {
-            ALOGE("%s - framesPerCallback negative", __func__);
+            ALOGW("%s - framesPerCallback negative", __func__);
             result = AAUDIO_ERROR_OUT_OF_RANGE;
             goto error;
 
@@ -225,7 +225,7 @@
 
 aaudio_result_t AudioStreamInternal::close() {
     aaudio_result_t result = AAUDIO_OK;
-    ALOGD("%s(): mServiceStreamHandle = 0x%08X", __func__, mServiceStreamHandle);
+    ALOGV("%s(): mServiceStreamHandle = 0x%08X", __func__, mServiceStreamHandle);
     if (mServiceStreamHandle != AAUDIO_HANDLE_INVALID) {
         // Don't close a stream while it is running.
         aaudio_stream_state_t currentState = getState();
@@ -236,7 +236,7 @@
             result = waitForStateChange(currentState, &nextState,
                                                        timeoutNanoseconds);
             if (result != AAUDIO_OK) {
-                ALOGE("%s() waitForStateChange() returned %d %s",
+                ALOGW("%s() waitForStateChange() returned %d %s",
                 __func__, result, AAudio_convertResultToText(result));
             }
         }
@@ -283,17 +283,17 @@
 {
     int64_t startTime;
     if (mServiceStreamHandle == AAUDIO_HANDLE_INVALID) {
-        ALOGE("requestStart() mServiceStreamHandle invalid");
+        ALOGD("requestStart() mServiceStreamHandle invalid");
         return AAUDIO_ERROR_INVALID_STATE;
     }
     if (isActive()) {
-        ALOGE("requestStart() already active");
+        ALOGD("requestStart() already active");
         return AAUDIO_ERROR_INVALID_STATE;
     }
 
     aaudio_stream_state_t originalState = getState();
     if (originalState == AAUDIO_STREAM_STATE_DISCONNECTED) {
-        ALOGE("requestStart() but DISCONNECTED");
+        ALOGD("requestStart() but DISCONNECTED");
         return AAUDIO_ERROR_DISCONNECTED;
     }
     setState(AAUDIO_STREAM_STATE_STARTING);
@@ -356,8 +356,8 @@
     }
 
     if (mServiceStreamHandle == AAUDIO_HANDLE_INVALID) {
-        ALOGE("requestStopInternal() mServiceStreamHandle invalid = 0x%08X",
-              mServiceStreamHandle);
+        ALOGW("%s() mServiceStreamHandle invalid = 0x%08X",
+              __func__, mServiceStreamHandle);
         return AAUDIO_ERROR_INVALID_STATE;
     }
 
@@ -370,7 +370,7 @@
 
 aaudio_result_t AudioStreamInternal::registerThread() {
     if (mServiceStreamHandle == AAUDIO_HANDLE_INVALID) {
-        ALOGE("registerThread() mServiceStreamHandle invalid");
+        ALOGW("%s() mServiceStreamHandle invalid", __func__);
         return AAUDIO_ERROR_INVALID_STATE;
     }
     return mServiceInterface.registerAudioThread(mServiceStreamHandle,
@@ -380,7 +380,7 @@
 
 aaudio_result_t AudioStreamInternal::unregisterThread() {
     if (mServiceStreamHandle == AAUDIO_HANDLE_INVALID) {
-        ALOGE("unregisterThread() mServiceStreamHandle invalid");
+        ALOGW("%s() mServiceStreamHandle invalid", __func__);
         return AAUDIO_ERROR_INVALID_STATE;
     }
     return mServiceInterface.unregisterAudioThread(mServiceStreamHandle, gettid());
diff --git a/media/libaaudio/src/client/AudioStreamInternalPlay.cpp b/media/libaaudio/src/client/AudioStreamInternalPlay.cpp
index e1443d9..164ad2b 100644
--- a/media/libaaudio/src/client/AudioStreamInternalPlay.cpp
+++ b/media/libaaudio/src/client/AudioStreamInternalPlay.cpp
@@ -65,7 +65,7 @@
         return result;
     }
     if (mServiceStreamHandle == AAUDIO_HANDLE_INVALID) {
-        ALOGE("%s() mServiceStreamHandle invalid", __func__);
+        ALOGW("%s() mServiceStreamHandle invalid", __func__);
         return AAUDIO_ERROR_INVALID_STATE;
     }
 
@@ -77,7 +77,7 @@
 
 aaudio_result_t AudioStreamInternalPlay::requestFlush() {
     if (mServiceStreamHandle == AAUDIO_HANDLE_INVALID) {
-        ALOGE("%s() mServiceStreamHandle invalid", __func__);
+        ALOGW("%s() mServiceStreamHandle invalid", __func__);
         return AAUDIO_ERROR_INVALID_STATE;
     }
 
diff --git a/media/libaaudio/src/core/AAudioAudio.cpp b/media/libaaudio/src/core/AAudioAudio.cpp
index 8ae2644..44d5122 100644
--- a/media/libaaudio/src/core/AAudioAudio.cpp
+++ b/media/libaaudio/src/core/AAudioAudio.cpp
@@ -246,18 +246,20 @@
                                                      AAudioStream** streamPtr)
 {
     AudioStream *audioStream = nullptr;
+    aaudio_stream_id_t id = 0;
     // Please leave these logs because they are very helpful when debugging.
-    ALOGD("%s() called ----------------------------------------", __func__);
+    ALOGI("%s() called ----------------------------------------", __func__);
     AudioStreamBuilder *streamBuilder = COMMON_GET_FROM_BUILDER_OR_RETURN(streamPtr);
     aaudio_result_t result = streamBuilder->build(&audioStream);
-    ALOGD("AAudioStreamBuilder_openStream() returns %d = %s for (%p) ----------------",
-          result, AAudio_convertResultToText(result), audioStream);
     if (result == AAUDIO_OK) {
         audioStream->registerPlayerBase();
         *streamPtr = (AAudioStream*) audioStream;
+        id = audioStream->getId();
     } else {
         *streamPtr = nullptr;
     }
+    ALOGI("%s() returns %d = %s for s#%u ----------------",
+        __func__, result, AAudio_convertResultToText(result), id);
     return result;
 }
 
@@ -275,8 +277,9 @@
 {
     aaudio_result_t result = AAUDIO_ERROR_NULL;
     AudioStream *audioStream = convertAAudioStreamToAudioStream(stream);
-    ALOGD("%s(%p) called ---------------", __func__, stream);
     if (audioStream != nullptr) {
+        aaudio_stream_id_t id = audioStream->getId();
+        ALOGD("%s(s#%u) called ---------------", __func__, id);
         result = audioStream->safeClose();
         // Close will only fail if called illegally, for example, from a callback.
         // That would result in deleting an active stream, which would cause a crash.
@@ -286,42 +289,39 @@
         } else {
             ALOGW("%s attempt to close failed. Close it from another thread.", __func__);
         }
+        ALOGD("%s(s#%u) returned %d ---------", __func__, id, result);
     }
-    // We're potentially freeing `stream` above, so its use here makes some
-    // static analysis tools unhappy. Casting to uintptr_t helps assure
-    // said tools that we're not doing anything bad here.
-    ALOGD("%s(%#" PRIxPTR ") returned %d ---------", __func__,
-          reinterpret_cast<uintptr_t>(stream), result);
     return result;
 }
 
 AAUDIO_API aaudio_result_t  AAudioStream_requestStart(AAudioStream* stream)
 {
     AudioStream *audioStream = convertAAudioStreamToAudioStream(stream);
-    ALOGD("%s(%p) called --------------", __func__, stream);
+    aaudio_stream_id_t id = audioStream->getId();
+    ALOGD("%s(s#%u) called --------------", __func__, id);
     aaudio_result_t result = audioStream->systemStart();
-    ALOGD("%s(%p) returned %d ---------", __func__, stream, result);
+    ALOGD("%s(s#%u) returned %d ---------", __func__, id, result);
     return result;
 }
 
 AAUDIO_API aaudio_result_t  AAudioStream_requestPause(AAudioStream* stream)
 {
     AudioStream *audioStream = convertAAudioStreamToAudioStream(stream);
-    ALOGD("%s(%p) called", __func__, stream);
+    ALOGD("%s(s#%u) called", __func__, audioStream->getId());
     return audioStream->systemPause();
 }
 
 AAUDIO_API aaudio_result_t  AAudioStream_requestFlush(AAudioStream* stream)
 {
     AudioStream *audioStream = convertAAudioStreamToAudioStream(stream);
-    ALOGD("%s(%p) called", __func__, stream);
+    ALOGD("%s(s#%u) called", __func__, audioStream->getId());
     return audioStream->safeFlush();
 }
 
 AAUDIO_API aaudio_result_t  AAudioStream_requestStop(AAudioStream* stream)
 {
     AudioStream *audioStream = convertAAudioStreamToAudioStream(stream);
-    ALOGD("%s(%p) called", __func__, stream);
+    ALOGD("%s(s#%u) called", __func__, audioStream->getId());
     return audioStream->systemStopFromApp();
 }
 
@@ -371,7 +371,7 @@
 
     // Don't allow writes when playing with a callback.
     if (audioStream->isDataCallbackActive()) {
-        ALOGE("Cannot write to a callback stream when running.");
+        ALOGD("Cannot write to a callback stream when running.");
         return AAUDIO_ERROR_INVALID_STATE;
     }
 
diff --git a/media/libaaudio/src/core/AAudioStreamParameters.cpp b/media/libaaudio/src/core/AAudioStreamParameters.cpp
index e5bda30..c9711da 100644
--- a/media/libaaudio/src/core/AAudioStreamParameters.cpp
+++ b/media/libaaudio/src/core/AAudioStreamParameters.cpp
@@ -56,7 +56,7 @@
         case AUDIO_FORMAT_PCM_FLOAT:
             break; // valid
         default:
-            ALOGE("audioFormat not valid, audio_format_t = 0x%08x", format);
+            ALOGD("audioFormat not valid, audio_format_t = 0x%08x", format);
             return AAUDIO_ERROR_INVALID_FORMAT;
             // break;
     }
@@ -66,12 +66,12 @@
 aaudio_result_t AAudioStreamParameters::validate() const {
     if (mSamplesPerFrame != AAUDIO_UNSPECIFIED
         && (mSamplesPerFrame < SAMPLES_PER_FRAME_MIN || mSamplesPerFrame > SAMPLES_PER_FRAME_MAX)) {
-        ALOGE("channelCount out of range = %d", mSamplesPerFrame);
+        ALOGD("channelCount out of range = %d", mSamplesPerFrame);
         return AAUDIO_ERROR_OUT_OF_RANGE;
     }
 
     if (mDeviceId < 0) {
-        ALOGE("deviceId out of range = %d", mDeviceId);
+        ALOGD("deviceId out of range = %d", mDeviceId);
         return AAUDIO_ERROR_OUT_OF_RANGE;
     }
 
@@ -89,7 +89,7 @@
         case AAUDIO_SHARING_MODE_SHARED:
             break;
         default:
-            ALOGE("illegal sharingMode = %d", mSharingMode);
+            ALOGD("illegal sharingMode = %d", mSharingMode);
             return AAUDIO_ERROR_ILLEGAL_ARGUMENT;
             // break;
     }
@@ -99,12 +99,12 @@
 
     if (mSampleRate != AAUDIO_UNSPECIFIED
         && (mSampleRate < SAMPLE_RATE_HZ_MIN || mSampleRate > SAMPLE_RATE_HZ_MAX)) {
-        ALOGE("sampleRate out of range = %d", mSampleRate);
+        ALOGD("sampleRate out of range = %d", mSampleRate);
         return AAUDIO_ERROR_INVALID_RATE;
     }
 
     if (mBufferCapacity < 0) {
-        ALOGE("bufferCapacity out of range = %d", mBufferCapacity);
+        ALOGD("bufferCapacity out of range = %d", mBufferCapacity);
         return AAUDIO_ERROR_OUT_OF_RANGE;
     }
 
@@ -113,7 +113,7 @@
         case AAUDIO_DIRECTION_OUTPUT:
             break; // valid
         default:
-            ALOGE("direction not valid = %d", mDirection);
+            ALOGD("direction not valid = %d", mDirection);
             return AAUDIO_ERROR_ILLEGAL_ARGUMENT;
             // break;
     }
@@ -134,7 +134,7 @@
         case AAUDIO_USAGE_ASSISTANT:
             break; // valid
         default:
-            ALOGE("usage not valid = %d", mUsage);
+            ALOGD("usage not valid = %d", mUsage);
             return AAUDIO_ERROR_ILLEGAL_ARGUMENT;
             // break;
     }
@@ -147,7 +147,7 @@
         case AAUDIO_CONTENT_TYPE_SPEECH:
             break; // valid
         default:
-            ALOGE("content type not valid = %d", mContentType);
+            ALOGD("content type not valid = %d", mContentType);
             return AAUDIO_ERROR_ILLEGAL_ARGUMENT;
             // break;
     }
@@ -162,7 +162,7 @@
         case AAUDIO_INPUT_PRESET_VOICE_PERFORMANCE:
             break; // valid
         default:
-            ALOGE("input preset not valid = %d", mInputPreset);
+            ALOGD("input preset not valid = %d", mInputPreset);
             return AAUDIO_ERROR_ILLEGAL_ARGUMENT;
             // break;
     }
@@ -174,7 +174,7 @@
         case AAUDIO_ALLOW_CAPTURE_BY_NONE:
             break; // valid
         default:
-            ALOGE("allowed capture policy not valid = %d", mAllowedCapturePolicy);
+            ALOGD("allowed capture policy not valid = %d", mAllowedCapturePolicy);
             return AAUDIO_ERROR_ILLEGAL_ARGUMENT;
             // break;
     }
diff --git a/media/libaaudio/src/core/AudioStream.cpp b/media/libaaudio/src/core/AudioStream.cpp
index 732d45c..25669be 100644
--- a/media/libaaudio/src/core/AudioStream.cpp
+++ b/media/libaaudio/src/core/AudioStream.cpp
@@ -28,9 +28,17 @@
 
 using namespace aaudio;
 
+
+// Sequential number assigned to streams solely for debugging purposes.
+static aaudio_stream_id_t AAudio_getNextStreamId() {
+    static std::atomic <aaudio_stream_id_t> nextStreamId{1};
+    return nextStreamId++;
+}
+
 AudioStream::AudioStream()
         : mPlayerBase(new MyPlayerBase(this))
-{
+        , mStreamId(AAudio_getNextStreamId())
+        {
     // mThread is a pthread_t of unknown size so we need memset.
     memset(&mThread, 0, sizeof(mThread));
     setPeriodNanoseconds(0);
@@ -48,22 +56,6 @@
     mPlayerBase->clearParentReference(); // remove reference to this AudioStream
 }
 
-static const char *AudioStream_convertSharingModeToShortText(aaudio_sharing_mode_t sharingMode) {
-    const char *result;
-    switch (sharingMode) {
-        case AAUDIO_SHARING_MODE_EXCLUSIVE:
-            result = "EX";
-            break;
-        case AAUDIO_SHARING_MODE_SHARED:
-            result = "SH";
-            break;
-        default:
-            result = "?!";
-            break;
-    }
-    return result;
-}
-
 aaudio_result_t AudioStream::open(const AudioStreamBuilder& builder)
 {
     // Call here as well because the AAudioService will call this without calling build().
@@ -106,20 +98,6 @@
     mDataCallbackUserData = builder.getDataCallbackUserData();
     mErrorCallbackUserData = builder.getErrorCallbackUserData();
 
-    // This is very helpful for debugging in the future. Please leave it in.
-    ALOGI("open() rate   = %d, channels    = %d, format   = %d, sharing = %s, dir = %s",
-          mSampleRate, mSamplesPerFrame, mFormat,
-          AudioStream_convertSharingModeToShortText(mSharingMode),
-          (getDirection() == AAUDIO_DIRECTION_OUTPUT) ? "OUTPUT" : "INPUT");
-    ALOGI("open() device = %d, sessionId   = %d, perfMode = %d, callback: %s with frames = %d",
-          mDeviceId,
-          mSessionId,
-          mPerformanceMode,
-          (isDataCallbackSet() ? "ON" : "OFF"),
-          mFramesPerDataCallback);
-    ALOGI("open() usage  = %d, contentType = %d, inputPreset = %d, allowedCapturePolicy = %d",
-          mUsage, mContentType, mInputPreset, mAllowedCapturePolicy);
-
     return AAUDIO_OK;
 }
 
@@ -278,15 +256,15 @@
 }
 
 void AudioStream::setState(aaudio_stream_state_t state) {
-    ALOGV("%s(%p) from %d to %d", __func__, this, mState, state);
+    ALOGV("%s(%d) from %d to %d", __func__, getId(), mState, state);
     // CLOSED is a final state
     if (mState == AAUDIO_STREAM_STATE_CLOSED) {
-        ALOGE("%s(%p) tried to set to %d but already CLOSED", __func__, this, state);
+        ALOGE("%s(%d) tried to set to %d but already CLOSED", __func__, getId(), state);
 
     // Once DISCONNECTED, we can only move to CLOSED state.
     } else if (mState == AAUDIO_STREAM_STATE_DISCONNECTED
                && state != AAUDIO_STREAM_STATE_CLOSED) {
-        ALOGE("%s(%p) tried to set to %d but already DISCONNECTED", __func__, this, state);
+        ALOGE("%s(%d) tried to set to %d but already DISCONNECTED", __func__, getId(), state);
 
     } else {
         mState = state;
@@ -485,7 +463,6 @@
 }
 
 AudioStream::MyPlayerBase::~MyPlayerBase() {
-    ALOGV("MyPlayerBase::~MyPlayerBase(%p) deleted", this);
 }
 
 void AudioStream::MyPlayerBase::registerWithAudioManager() {
diff --git a/media/libaaudio/src/core/AudioStream.h b/media/libaaudio/src/core/AudioStream.h
index 32713b1..044c979 100644
--- a/media/libaaudio/src/core/AudioStream.h
+++ b/media/libaaudio/src/core/AudioStream.h
@@ -36,6 +36,7 @@
 namespace aaudio {
 
 typedef void *(*aaudio_audio_thread_proc_t)(void *);
+typedef uint32_t aaudio_stream_id_t;
 
 class AudioStreamBuilder;
 
@@ -121,6 +122,12 @@
         return AAUDIO_OK;
     }
 
+    // This is only used to identify a stream in the logs without
+    // revealing any pointers.
+    aaudio_stream_id_t getId() {
+        return mStreamId;
+    }
+
     virtual aaudio_result_t setBufferSize(int32_t requestedFrames) = 0;
 
     virtual aaudio_result_t createThread(int64_t periodNanoseconds,
@@ -587,6 +594,8 @@
     void                       *mThreadArg = nullptr;
     aaudio_result_t             mThreadRegistrationResult = AAUDIO_OK;
 
+    const aaudio_stream_id_t    mStreamId;
+
 };
 
 } /* namespace aaudio */
diff --git a/media/libaaudio/src/core/AudioStreamBuilder.cpp b/media/libaaudio/src/core/AudioStreamBuilder.cpp
index 4ef765d..08f4958 100644
--- a/media/libaaudio/src/core/AudioStreamBuilder.cpp
+++ b/media/libaaudio/src/core/AudioStreamBuilder.cpp
@@ -104,6 +104,8 @@
     }
     *streamPtr = nullptr;
 
+    logParameters();
+
     aaudio_result_t result = validate();
     if (result != AAUDIO_OK) {
         return result;
@@ -217,3 +219,41 @@
 
     return AAUDIO_OK;
 }
+
+static const char *AAudio_convertSharingModeToShortText(aaudio_sharing_mode_t sharingMode) {
+    switch (sharingMode) {
+        case AAUDIO_SHARING_MODE_EXCLUSIVE:
+            return "EX";
+        case AAUDIO_SHARING_MODE_SHARED:
+            return "SH";
+        default:
+            return "?!";
+    }
+}
+
+static const char *AAudio_convertDirectionToText(aaudio_direction_t direction) {
+    switch (direction) {
+        case AAUDIO_DIRECTION_OUTPUT:
+            return "OUTPUT";
+        case AAUDIO_DIRECTION_INPUT:
+            return "INPUT";
+        default:
+            return "?!";
+    }
+}
+
+void AudioStreamBuilder::logParameters() const {
+    // This is very helpful for debugging in the future. Please leave it in.
+    ALOGI("rate   = %6d, channels  = %d, format   = %d, sharing = %s, dir = %s",
+          getSampleRate(), getSamplesPerFrame(), getFormat(),
+          AAudio_convertSharingModeToShortText(getSharingMode()),
+          AAudio_convertDirectionToText(getDirection()));
+    ALOGI("device = %6d, sessionId = %d, perfMode = %d, callback: %s with frames = %d",
+          getDeviceId(),
+          getSessionId(),
+          getPerformanceMode(),
+          ((getDataCallbackProc() != nullptr) ? "ON" : "OFF"),
+          mFramesPerDataCallback);
+    ALOGI("usage  = %6d, contentType = %d, inputPreset = %d, allowedCapturePolicy = %d",
+          getUsage(), getContentType(), getInputPreset(), getAllowedCapturePolicy());
+}
diff --git a/media/libaaudio/src/core/AudioStreamBuilder.h b/media/libaaudio/src/core/AudioStreamBuilder.h
index a43cfa8..8149af2 100644
--- a/media/libaaudio/src/core/AudioStreamBuilder.h
+++ b/media/libaaudio/src/core/AudioStreamBuilder.h
@@ -102,6 +102,8 @@
 
     virtual aaudio_result_t validate() const override;
 
+    void logParameters() const;
+
 private:
     bool                       mSharingModeMatchRequired = false; // must match sharing mode requested
     aaudio_performance_mode_t  mPerformanceMode = AAUDIO_PERFORMANCE_MODE_NONE;
diff --git a/media/libaaudio/src/legacy/AudioStreamLegacy.cpp b/media/libaaudio/src/legacy/AudioStreamLegacy.cpp
index 2edab58..91d2eff 100644
--- a/media/libaaudio/src/legacy/AudioStreamLegacy.cpp
+++ b/media/libaaudio/src/legacy/AudioStreamLegacy.cpp
@@ -206,7 +206,9 @@
 
 void AudioStreamLegacy::onAudioDeviceUpdate(audio_port_handle_t deviceId)
 {
-    ALOGD("onAudioDeviceUpdate() deviceId %d", (int)deviceId);
+    // Device routing is a common source of errors and DISCONNECTS.
+    // Please leave this log in place.
+    ALOGD("%s() devId %d => %d", __func__, (int) getDeviceId(), (int)deviceId);
     if (getDeviceId() != AAUDIO_UNSPECIFIED && getDeviceId() != deviceId &&
             getState() != AAUDIO_STREAM_STATE_DISCONNECTED) {
         // Note that isDataCallbackActive() is affected by state so call it before DISCONNECTING.
diff --git a/media/libaudioclient/AudioSystem.cpp b/media/libaudioclient/AudioSystem.cpp
index f324669..de82d2b 100644
--- a/media/libaudioclient/AudioSystem.cpp
+++ b/media/libaudioclient/AudioSystem.cpp
@@ -1067,6 +1067,13 @@
     return aps->setEffectEnabled(id, enabled);
 }
 
+status_t AudioSystem::moveEffectsToIo(const std::vector<int>& ids, audio_io_handle_t io)
+{
+    const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+    if (aps == 0) return PERMISSION_DENIED;
+    return aps->moveEffectsToIo(ids, io);
+}
+
 status_t AudioSystem::isStreamActive(audio_stream_type_t stream, bool* state, uint32_t inPastMs)
 {
     const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
diff --git a/media/libaudioclient/IAudioFlinger.cpp b/media/libaudioclient/IAudioFlinger.cpp
index 825cd4e..dd95e34 100644
--- a/media/libaudioclient/IAudioFlinger.cpp
+++ b/media/libaudioclient/IAudioFlinger.cpp
@@ -89,6 +89,7 @@
     GET_MICROPHONES,
     SET_MASTER_BALANCE,
     GET_MASTER_BALANCE,
+    SET_EFFECT_SUSPENDED,
 };
 
 #define MAX_ITEMS_PER_LIST 1024
@@ -718,6 +719,18 @@
         return reply.readInt32();
     }
 
+    virtual void setEffectSuspended(int effectId,
+                                    audio_session_t sessionId,
+                                    bool suspended)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
+        data.writeInt32(effectId);
+        data.writeInt32(sessionId);
+        data.writeInt32(suspended ? 1 : 0);
+        remote()->transact(SET_EFFECT_SUSPENDED, data, &reply);
+    }
+
     virtual audio_module_handle_t loadHwModule(const char *name)
     {
         Parcel data, reply;
@@ -913,6 +926,7 @@
         case INVALIDATE_STREAM:
         case SET_VOICE_VOLUME:
         case MOVE_EFFECTS:
+        case SET_EFFECT_SUSPENDED:
         case LOAD_HW_MODULE:
         case LIST_AUDIO_PORTS:
         case GET_AUDIO_PORT:
@@ -926,6 +940,7 @@
             // return status only for non void methods
             switch (code) {
                 case SET_RECORD_SILENCED:
+                case SET_EFFECT_SUSPENDED:
                     break;
                 default:
                     reply->writeInt32(static_cast<int32_t> (INVALID_OPERATION));
@@ -1371,6 +1386,14 @@
             reply->writeInt32(moveEffects(session, srcOutput, dstOutput));
             return NO_ERROR;
         } break;
+        case SET_EFFECT_SUSPENDED: {
+            CHECK_INTERFACE(IAudioFlinger, data, reply);
+            int effectId = data.readInt32();
+            audio_session_t sessionId = (audio_session_t) data.readInt32();
+            bool suspended = data.readInt32() == 1;
+            setEffectSuspended(effectId, sessionId, suspended);
+            return NO_ERROR;
+        } break;
         case LOAD_HW_MODULE: {
             CHECK_INTERFACE(IAudioFlinger, data, reply);
             reply->writeInt32(loadHwModule(data.readCString()));
diff --git a/media/libaudioclient/IAudioPolicyService.cpp b/media/libaudioclient/IAudioPolicyService.cpp
index bf98c60..4a8bb52 100644
--- a/media/libaudioclient/IAudioPolicyService.cpp
+++ b/media/libaudioclient/IAudioPolicyService.cpp
@@ -103,6 +103,7 @@
     LIST_AUDIO_VOLUME_GROUPS,
     GET_VOLUME_GROUP_FOR_ATTRIBUTES,
     SET_ALLOWED_CAPTURE_POLICY,
+    MOVE_EFFECTS_TO_IO,
 };
 
 #define MAX_ITEMS_PER_LIST 1024
@@ -550,6 +551,22 @@
         return static_cast <status_t> (reply.readInt32());
     }
 
+    status_t moveEffectsToIo(const std::vector<int>& ids, audio_io_handle_t io) override
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
+        data.writeInt32(ids.size());
+        for (auto id : ids) {
+            data.writeInt32(id);
+        }
+        data.writeInt32(io);
+        status_t status = remote()->transact(MOVE_EFFECTS_TO_IO, data, &reply);
+        if (status != NO_ERROR) {
+            return status;
+        }
+        return static_cast <status_t> (reply.readInt32());
+    }
+
     virtual bool isStreamActive(audio_stream_type_t stream, uint32_t inPastMs) const
     {
         Parcel data, reply;
@@ -1284,6 +1301,7 @@
         case GET_OUTPUT_FOR_ATTR:
         case ACQUIRE_SOUNDTRIGGER_SESSION:
         case RELEASE_SOUNDTRIGGER_SESSION:
+        case MOVE_EFFECTS_TO_IO:
             ALOGW("%s: transaction %d received from PID %d",
                   __func__, code, IPCThreadState::self()->getCallingPid());
             // return status only for non void methods
@@ -1700,6 +1718,31 @@
             return NO_ERROR;
         } break;
 
+        case MOVE_EFFECTS_TO_IO: {
+            CHECK_INTERFACE(IAudioPolicyService, data, reply);
+            std::vector<int> ids;
+            int32_t size;
+            status_t status = data.readInt32(&size);
+            if (status != NO_ERROR) {
+                return status;
+            }
+            if (size > MAX_ITEMS_PER_LIST) {
+                return BAD_VALUE;
+            }
+            for (int32_t i = 0; i < size; i++) {
+                int id;
+                status =  data.readInt32(&id);
+                if (status != NO_ERROR) {
+                    return status;
+                }
+                ids.push_back(id);
+            }
+
+            audio_io_handle_t io = data.readInt32();
+            reply->writeInt32(static_cast <int32_t>(moveEffectsToIo(ids, io)));
+            return NO_ERROR;
+        } break;
+
         case IS_STREAM_ACTIVE: {
             CHECK_INTERFACE(IAudioPolicyService, data, reply);
             audio_stream_type_t stream = (audio_stream_type_t) data.readInt32();
diff --git a/media/libaudioclient/include/media/AudioSystem.h b/media/libaudioclient/include/media/AudioSystem.h
index 05a1d56..d180bbc 100644
--- a/media/libaudioclient/include/media/AudioSystem.h
+++ b/media/libaudioclient/include/media/AudioSystem.h
@@ -286,6 +286,7 @@
                                     int id);
     static status_t unregisterEffect(int id);
     static status_t setEffectEnabled(int id, bool enabled);
+    static status_t moveEffectsToIo(const std::vector<int>& ids, audio_io_handle_t io);
 
     // clear stream to output mapping cache (gStreamOutputMap)
     // and output configuration cache (gOutputs)
diff --git a/media/libaudioclient/include/media/IAudioFlinger.h b/media/libaudioclient/include/media/IAudioFlinger.h
index ef0ed0c..dcc18b6 100644
--- a/media/libaudioclient/include/media/IAudioFlinger.h
+++ b/media/libaudioclient/include/media/IAudioFlinger.h
@@ -457,6 +457,10 @@
     virtual status_t moveEffects(audio_session_t session, audio_io_handle_t srcOutput,
                                     audio_io_handle_t dstOutput) = 0;
 
+    virtual void setEffectSuspended(int effectId,
+                                    audio_session_t sessionId,
+                                    bool suspended) = 0;
+
     virtual audio_module_handle_t loadHwModule(const char *name) = 0;
 
     // helpers for android.media.AudioManager.getProperty(), see description there for meaning
diff --git a/media/libaudioclient/include/media/IAudioPolicyService.h b/media/libaudioclient/include/media/IAudioPolicyService.h
index 95530ac..11983d5 100644
--- a/media/libaudioclient/include/media/IAudioPolicyService.h
+++ b/media/libaudioclient/include/media/IAudioPolicyService.h
@@ -114,6 +114,7 @@
                                     int id) = 0;
     virtual status_t unregisterEffect(int id) = 0;
     virtual status_t setEffectEnabled(int id, bool enabled) = 0;
+    virtual status_t moveEffectsToIo(const std::vector<int>& ids, audio_io_handle_t io) = 0;
     virtual bool     isStreamActive(audio_stream_type_t stream, uint32_t inPastMs = 0) const = 0;
     virtual bool     isStreamActiveRemotely(audio_stream_type_t stream, uint32_t inPastMs = 0)
                              const = 0;
diff --git a/media/libeffects/preprocessing/PreProcessing.cpp b/media/libeffects/preprocessing/PreProcessing.cpp
index 50c33c6..5fab5be 100644
--- a/media/libeffects/preprocessing/PreProcessing.cpp
+++ b/media/libeffects/preprocessing/PreProcessing.cpp
@@ -926,7 +926,7 @@
         delete session->revBuf;
         session->revBuf = NULL;
 
-        session->io = 0;
+        session->id = 0;
     }
 
     return 0;
@@ -1155,7 +1155,7 @@
 {
     size_t i;
     for (i = 0; i < PREPROC_NUM_SESSIONS; i++) {
-        if (sSessions[i].io == ioId) {
+        if (sSessions[i].id == sessionId) {
             if (sSessions[i].createdMsk & (1 << procId)) {
                 return NULL;
             }
@@ -1163,7 +1163,7 @@
         }
     }
     for (i = 0; i < PREPROC_NUM_SESSIONS; i++) {
-        if (sSessions[i].io == 0) {
+        if (sSessions[i].id == 0) {
             sSessions[i].id = sessionId;
             sSessions[i].io = ioId;
             return &sSessions[i];
@@ -1915,7 +1915,7 @@
     status = Session_CreateEffect(session, procId, pInterface);
 
     if (status < 0 && session->createdMsk == 0) {
-        session->io = 0;
+        session->id = 0;
     }
     return status;
 }
@@ -1929,7 +1929,7 @@
 
     preproc_effect_t *fx = (preproc_effect_t *)interface;
 
-    if (fx->session->io == 0) {
+    if (fx->session->id == 0) {
         return -EINVAL;
     }
     return Session_ReleaseEffect(fx->session, fx);
diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp
index b1fdb2c..2ca5eee 100644
--- a/media/libstagefright/MediaCodec.cpp
+++ b/media/libstagefright/MediaCodec.cpp
@@ -1659,10 +1659,12 @@
         return;
     }
     int32_t colorFormat;
-    if (mSoftRenderer != NULL
-            && mOutputFormat->contains("hdr-static-info")
+    if (mOutputFormat->contains("hdr-static-info")
             && mOutputFormat->findInt32("color-format", &colorFormat)
-            && (colorFormat == OMX_COLOR_FormatYUV420Planar16)) {
+            // check format for OMX only, for C2 the format is always opaque since the
+            // software rendering doesn't go through client
+            && ((mSoftRenderer != NULL && colorFormat == OMX_COLOR_FormatYUV420Planar16)
+                    || mOwnerName.equalsIgnoreCase("codec2::software"))) {
         int32_t left, top, right, bottom, width, height;
         int64_t totalPixel = 0;
         if (mOutputFormat->findRect("crop", &left, &top, &right, &bottom)) {
@@ -1958,6 +1960,7 @@
                     } else {
                         mFlags &= ~kFlagUsesSoftwareRenderer;
                     }
+                    mOwnerName = owner;
 
                     MediaResource::Type resourceType;
                     if (mComponentName.endsWith(".secure")) {
diff --git a/media/libstagefright/Utils.cpp b/media/libstagefright/Utils.cpp
index c7b2719..537e4c0 100644
--- a/media/libstagefright/Utils.cpp
+++ b/media/libstagefright/Utils.cpp
@@ -1756,7 +1756,11 @@
                 size_t outsize = reassembleAVCC(csd0, csd1, avcc.data());
                 meta->setData(kKeyAVCC, kTypeAVCC, avcc.data(), outsize);
             }
-        } else if (mime == MEDIA_MIMETYPE_AUDIO_AAC || mime == MEDIA_MIMETYPE_VIDEO_MPEG4) {
+        } else if (mime == MEDIA_MIMETYPE_AUDIO_AAC ||
+                mime == MEDIA_MIMETYPE_VIDEO_MPEG4 ||
+                mime == MEDIA_MIMETYPE_AUDIO_WMA ||
+                mime == MEDIA_MIMETYPE_AUDIO_MS_ADPCM ||
+                mime == MEDIA_MIMETYPE_AUDIO_DVI_IMA_ADPCM) {
             std::vector<char> esds(csd0size + 31);
             // The written ESDS is actually for an audio stream, but it's enough
             // for transporting the CSD to muxers.
diff --git a/media/libstagefright/foundation/MediaDefs.cpp b/media/libstagefright/foundation/MediaDefs.cpp
index 52b2765..a08fed1 100644
--- a/media/libstagefright/foundation/MediaDefs.cpp
+++ b/media/libstagefright/foundation/MediaDefs.cpp
@@ -59,6 +59,10 @@
 const char *MEDIA_MIMETYPE_AUDIO_AC4 = "audio/ac4";
 const char *MEDIA_MIMETYPE_AUDIO_SCRAMBLED = "audio/scrambled";
 const char *MEDIA_MIMETYPE_AUDIO_ALAC = "audio/alac";
+const char *MEDIA_MIMETYPE_AUDIO_WMA = "audio/x-ms-wma";
+const char *MEDIA_MIMETYPE_AUDIO_MS_ADPCM = "audio/x-adpcm-ms";
+const char *MEDIA_MIMETYPE_AUDIO_DVI_IMA_ADPCM = "audio/x-adpcm-dvi-ima";
+
 
 const char *MEDIA_MIMETYPE_CONTAINER_MPEG4 = "video/mp4";
 const char *MEDIA_MIMETYPE_CONTAINER_WAV = "audio/x-wav";
diff --git a/media/libstagefright/foundation/include/media/stagefright/foundation/MediaDefs.h b/media/libstagefright/foundation/include/media/stagefright/foundation/MediaDefs.h
index 007a09b..1f9e636 100644
--- a/media/libstagefright/foundation/include/media/stagefright/foundation/MediaDefs.h
+++ b/media/libstagefright/foundation/include/media/stagefright/foundation/MediaDefs.h
@@ -61,6 +61,10 @@
 extern const char *MEDIA_MIMETYPE_AUDIO_AC4;
 extern const char *MEDIA_MIMETYPE_AUDIO_SCRAMBLED;
 extern const char *MEDIA_MIMETYPE_AUDIO_ALAC;
+extern const char *MEDIA_MIMETYPE_AUDIO_WMA;
+extern const char *MEDIA_MIMETYPE_AUDIO_MS_ADPCM;
+extern const char *MEDIA_MIMETYPE_AUDIO_DVI_IMA_ADPCM;
+
 
 extern const char *MEDIA_MIMETYPE_CONTAINER_MPEG4;
 extern const char *MEDIA_MIMETYPE_CONTAINER_WAV;
diff --git a/media/libstagefright/include/media/stagefright/MediaCodec.h b/media/libstagefright/include/media/stagefright/MediaCodec.h
index 7f6aae6..6cd4265 100644
--- a/media/libstagefright/include/media/stagefright/MediaCodec.h
+++ b/media/libstagefright/include/media/stagefright/MediaCodec.h
@@ -313,6 +313,7 @@
     sp<ALooper> mCodecLooper;
     sp<CodecBase> mCodec;
     AString mComponentName;
+    AString mOwnerName;
     sp<MediaCodecInfo> mCodecInfo;
     sp<AReplyToken> mReplyID;
     uint32_t mFlags;
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 0825cb4..55db699 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -687,6 +687,10 @@
     bool updatePid = (input.clientInfo.clientPid == -1);
     const uid_t callingUid = IPCThreadState::self()->getCallingUid();
     uid_t clientUid = input.clientInfo.clientUid;
+    audio_io_handle_t effectThreadId = AUDIO_IO_HANDLE_NONE;
+    std::vector<int> effectIds;
+
+
     if (!isAudioServerOrMediaServerUid(callingUid)) {
         ALOGW_IF(clientUid != callingUid,
                 "%s uid %d tried to pass itself off as %d",
@@ -851,7 +855,10 @@
             // no risk of deadlock because AudioFlinger::mLock is held
             Mutex::Autolock _dl(thread->mLock);
             Mutex::Autolock _sl(effectThread->mLock);
-            moveEffectChain_l(sessionId, effectThread, thread, true);
+            if (moveEffectChain_l(sessionId, effectThread, thread) == NO_ERROR) {
+                effectThreadId = thread->id();
+                effectIds = thread->getEffectIds_l(sessionId);
+            }
         }
 
         // Look for sync events awaiting for a session to be used.
@@ -885,6 +892,12 @@
         goto Exit;
     }
 
+    // effectThreadId is not NONE if an effect chain corresponding to the track session
+    // was found on another thread and must be moved on this thread
+    if (effectThreadId != AUDIO_IO_HANDLE_NONE) {
+        AudioSystem::moveEffectsToIo(effectIds, effectThreadId);
+    }
+
     // return handle to client
     trackHandle = new TrackHandle(track);
 
@@ -1225,7 +1238,8 @@
     if (output == AUDIO_IO_HANDLE_NONE) {
         return BAD_VALUE;
     }
-    ALOG_ASSERT(stream != AUDIO_STREAM_PATCH, "attempt to change AUDIO_STREAM_PATCH volume");
+    LOG_ALWAYS_FATAL_IF(stream == AUDIO_STREAM_PATCH && value != 1.0f,
+                        "AUDIO_STREAM_PATCH must have full scale volume");
 
     AutoMutex lock(mLock);
     VolumeInterface *volumeInterface = getVolumeInterface_l(output);
@@ -1630,30 +1644,36 @@
 
 void AudioFlinger::removeNotificationClient(pid_t pid)
 {
-    Mutex::Autolock _l(mLock);
+    std::vector< sp<AudioFlinger::EffectModule> > removedEffects;
     {
-        Mutex::Autolock _cl(mClientLock);
-        mNotificationClients.removeItem(pid);
-    }
+        Mutex::Autolock _l(mLock);
+        {
+            Mutex::Autolock _cl(mClientLock);
+            mNotificationClients.removeItem(pid);
+        }
 
-    ALOGV("%d died, releasing its sessions", pid);
-    size_t num = mAudioSessionRefs.size();
-    bool removed = false;
-    for (size_t i = 0; i < num; ) {
-        AudioSessionRef *ref = mAudioSessionRefs.itemAt(i);
-        ALOGV(" pid %d @ %zu", ref->mPid, i);
-        if (ref->mPid == pid) {
-            ALOGV(" removing entry for pid %d session %d", pid, ref->mSessionid);
-            mAudioSessionRefs.removeAt(i);
-            delete ref;
-            removed = true;
-            num--;
-        } else {
-            i++;
+        ALOGV("%d died, releasing its sessions", pid);
+        size_t num = mAudioSessionRefs.size();
+        bool removed = false;
+        for (size_t i = 0; i < num; ) {
+            AudioSessionRef *ref = mAudioSessionRefs.itemAt(i);
+            ALOGV(" pid %d @ %zu", ref->mPid, i);
+            if (ref->mPid == pid) {
+                ALOGV(" removing entry for pid %d session %d", pid, ref->mSessionid);
+                mAudioSessionRefs.removeAt(i);
+                delete ref;
+                removed = true;
+                num--;
+            } else {
+                i++;
+            }
+        }
+        if (removed) {
+            removedEffects = purgeStaleEffects_l();
         }
     }
-    if (removed) {
-        purgeStaleEffects_l();
+    for (auto& effect : removedEffects) {
+        effect->updatePolicyState();
     }
 }
 
@@ -1679,18 +1699,35 @@
 }
 
 // getEffectThread_l() must be called with AudioFlinger::mLock held
-sp<AudioFlinger::PlaybackThread> AudioFlinger::getEffectThread_l(audio_session_t sessionId,
-        int EffectId)
+sp<AudioFlinger::ThreadBase> AudioFlinger::getEffectThread_l(audio_session_t sessionId,
+        int effectId)
 {
-    sp<PlaybackThread> thread;
+    sp<ThreadBase> thread;
 
     for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
-        if (mPlaybackThreads.valueAt(i)->getEffect(sessionId, EffectId) != 0) {
+        if (mPlaybackThreads.valueAt(i)->getEffect(sessionId, effectId) != 0) {
             ALOG_ASSERT(thread == 0);
             thread = mPlaybackThreads.valueAt(i);
         }
     }
-
+    if (thread != nullptr) {
+        return thread;
+    }
+    for (size_t i = 0; i < mRecordThreads.size(); i++) {
+        if (mRecordThreads.valueAt(i)->getEffect(sessionId, effectId) != 0) {
+            ALOG_ASSERT(thread == 0);
+            thread = mRecordThreads.valueAt(i);
+        }
+    }
+    if (thread != nullptr) {
+        return thread;
+    }
+    for (size_t i = 0; i < mMmapThreads.size(); i++) {
+        if (mMmapThreads.valueAt(i)->getEffect(sessionId, effectId) != 0) {
+            ALOG_ASSERT(thread == 0);
+            thread = mMmapThreads.valueAt(i);
+        }
+    }
     return thread;
 }
 
@@ -2425,7 +2462,7 @@
                     Vector< sp<EffectChain> > effectChains = playbackThread->getEffectChains_l();
                     for (size_t i = 0; i < effectChains.size(); i ++) {
                         moveEffectChain_l(effectChains[i]->sessionId(), playbackThread.get(),
-                                dstThread, true);
+                                dstThread);
                     }
                 }
             }
@@ -2792,31 +2829,40 @@
 
 void AudioFlinger::releaseAudioSessionId(audio_session_t audioSession, pid_t pid)
 {
-    Mutex::Autolock _l(mLock);
-    pid_t caller = IPCThreadState::self()->getCallingPid();
-    ALOGV("releasing %d from %d for %d", audioSession, caller, pid);
-    const uid_t callerUid = IPCThreadState::self()->getCallingUid();
-    if (pid != -1 && isAudioServerUid(callerUid)) { // check must match acquireAudioSessionId()
-        caller = pid;
-    }
-    size_t num = mAudioSessionRefs.size();
-    for (size_t i = 0; i < num; i++) {
-        AudioSessionRef *ref = mAudioSessionRefs.itemAt(i);
-        if (ref->mSessionid == audioSession && ref->mPid == caller) {
-            ref->mCnt--;
-            ALOGV(" decremented refcount to %d", ref->mCnt);
-            if (ref->mCnt == 0) {
-                mAudioSessionRefs.removeAt(i);
-                delete ref;
-                purgeStaleEffects_l();
-            }
-            return;
+    std::vector< sp<EffectModule> > removedEffects;
+    {
+        Mutex::Autolock _l(mLock);
+        pid_t caller = IPCThreadState::self()->getCallingPid();
+        ALOGV("releasing %d from %d for %d", audioSession, caller, pid);
+        const uid_t callerUid = IPCThreadState::self()->getCallingUid();
+        if (pid != -1 && isAudioServerUid(callerUid)) { // check must match acquireAudioSessionId()
+            caller = pid;
         }
+        size_t num = mAudioSessionRefs.size();
+        for (size_t i = 0; i < num; i++) {
+            AudioSessionRef *ref = mAudioSessionRefs.itemAt(i);
+            if (ref->mSessionid == audioSession && ref->mPid == caller) {
+                ref->mCnt--;
+                ALOGV(" decremented refcount to %d", ref->mCnt);
+                if (ref->mCnt == 0) {
+                    mAudioSessionRefs.removeAt(i);
+                    delete ref;
+                    std::vector< sp<EffectModule> > effects = purgeStaleEffects_l();
+                    removedEffects.insert(removedEffects.end(), effects.begin(), effects.end());
+                }
+                goto Exit;
+            }
+        }
+        // If the caller is audioserver it is likely that the session being released was acquired
+        // on behalf of a process not in notification clients and we ignore the warning.
+        ALOGW_IF(!isAudioServerUid(callerUid),
+                 "session id %d not found for pid %d", audioSession, caller);
     }
-    // If the caller is audioserver it is likely that the session being released was acquired
-    // on behalf of a process not in notification clients and we ignore the warning.
-    ALOGW_IF(!isAudioServerUid(callerUid),
-            "session id %d not found for pid %d", audioSession, caller);
+
+Exit:
+    for (auto& effect : removedEffects) {
+        effect->updatePolicyState();
+    }
 }
 
 bool AudioFlinger::isSessionAcquired_l(audio_session_t audioSession)
@@ -2831,11 +2877,12 @@
     return false;
 }
 
-void AudioFlinger::purgeStaleEffects_l() {
+std::vector<sp<AudioFlinger::EffectModule>> AudioFlinger::purgeStaleEffects_l() {
 
     ALOGV("purging stale effects");
 
     Vector< sp<EffectChain> > chains;
+    std::vector< sp<EffectModule> > removedEffects;
 
     for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
         sp<PlaybackThread> t = mPlaybackThreads.valueAt(i);
@@ -2847,6 +2894,7 @@
             }
         }
     }
+
     for (size_t i = 0; i < mRecordThreads.size(); i++) {
         sp<RecordThread> t = mRecordThreads.valueAt(i);
         Mutex::Autolock _l(t->mLock);
@@ -2856,6 +2904,15 @@
         }
     }
 
+    for (size_t i = 0; i < mMmapThreads.size(); i++) {
+        sp<MmapThread> t = mMmapThreads.valueAt(i);
+        Mutex::Autolock _l(t->mLock);
+        for (size_t j = 0; j < t->mEffectChains.size(); j++) {
+            sp<EffectChain> ec = t->mEffectChains[j];
+            chains.push(ec);
+        }
+    }
+
     for (size_t i = 0; i < chains.size(); i++) {
         sp<EffectChain> ec = chains[i];
         int sessionid = ec->sessionId();
@@ -2884,11 +2941,11 @@
                 if (effect->purgeHandles()) {
                     t->checkSuspendOnEffectEnabled_l(effect, false, effect->sessionId());
                 }
-                AudioSystem::unregisterEffect(effect->id());
+                removedEffects.push_back(effect);
             }
         }
     }
-    return;
+    return removedEffects;
 }
 
 // dumpToThreadLog_l() must be called with AudioFlinger::mLock held
@@ -3380,8 +3437,16 @@
         }
     }
 
-    if (lStatus != NO_ERROR && lStatus != ALREADY_EXISTS) {
-        // handle must be cleared outside lock.
+    if (lStatus == NO_ERROR || lStatus == ALREADY_EXISTS) {
+        // Check CPU and memory usage
+        sp<EffectModule> effect = handle->effect().promote();
+        if (effect != nullptr) {
+            status_t rStatus = effect->updatePolicyState();
+            if (rStatus != NO_ERROR) {
+                lStatus = rStatus;
+            }
+        }
+    } else {
         handle.clear();
     }
 
@@ -3413,14 +3478,30 @@
 
     Mutex::Autolock _dl(dstThread->mLock);
     Mutex::Autolock _sl(srcThread->mLock);
-    return moveEffectChain_l(sessionId, srcThread, dstThread, false);
+    return moveEffectChain_l(sessionId, srcThread, dstThread);
 }
 
+
+void AudioFlinger::setEffectSuspended(int effectId,
+                                audio_session_t sessionId,
+                                bool suspended)
+{
+    Mutex::Autolock _l(mLock);
+
+    sp<ThreadBase> thread = getEffectThread_l(sessionId, effectId);
+    if (thread == nullptr) {
+      return;
+    }
+    Mutex::Autolock _sl(thread->mLock);
+    sp<EffectModule> effect = thread->getEffect_l(sessionId, effectId);
+    thread->setEffectSuspended_l(&effect->desc().type, suspended, sessionId);
+}
+
+
 // moveEffectChain_l must be called with both srcThread and dstThread mLocks held
 status_t AudioFlinger::moveEffectChain_l(audio_session_t sessionId,
                                    AudioFlinger::PlaybackThread *srcThread,
-                                   AudioFlinger::PlaybackThread *dstThread,
-                                   bool reRegister)
+                                   AudioFlinger::PlaybackThread *dstThread)
 {
     ALOGV("moveEffectChain_l() session %d from thread %p to thread %p",
             sessionId, srcThread, dstThread);
@@ -3476,36 +3557,68 @@
             }
             strategy = dstChain->strategy();
         }
-        if (reRegister) {
-            AudioSystem::unregisterEffect(effect->id());
-            AudioSystem::registerEffect(&effect->desc(),
-                                        dstThread->id(),
-                                        strategy,
-                                        sessionId,
-                                        effect->id());
-            AudioSystem::setEffectEnabled(effect->id(), effect->isEnabled());
-        }
         effect = chain->getEffectFromId_l(0);
     }
 
     if (status != NO_ERROR) {
         for (size_t i = 0; i < removed.size(); i++) {
             srcThread->addEffect_l(removed[i]);
-            if (dstChain != 0 && reRegister) {
-                AudioSystem::unregisterEffect(removed[i]->id());
-                AudioSystem::registerEffect(&removed[i]->desc(),
-                                            srcThread->id(),
-                                            strategy,
-                                            sessionId,
-                                            removed[i]->id());
-                AudioSystem::setEffectEnabled(effect->id(), effect->isEnabled());
-            }
         }
     }
 
     return status;
 }
 
+status_t AudioFlinger::moveAuxEffectToIo(int EffectId,
+                                         const sp<PlaybackThread>& dstThread,
+                                         sp<PlaybackThread> *srcThread)
+{
+    status_t status = NO_ERROR;
+    Mutex::Autolock _l(mLock);
+    sp<PlaybackThread> thread =
+        static_cast<PlaybackThread *>(getEffectThread_l(AUDIO_SESSION_OUTPUT_MIX, EffectId).get());
+
+    if (EffectId != 0 && thread != 0 && dstThread != thread.get()) {
+        Mutex::Autolock _dl(dstThread->mLock);
+        Mutex::Autolock _sl(thread->mLock);
+        sp<EffectChain> srcChain = thread->getEffectChain_l(AUDIO_SESSION_OUTPUT_MIX);
+        sp<EffectChain> dstChain;
+        if (srcChain == 0) {
+            return INVALID_OPERATION;
+        }
+
+        sp<EffectModule> effect = srcChain->getEffectFromId_l(EffectId);
+        if (effect == 0) {
+            return INVALID_OPERATION;
+        }
+        thread->removeEffect_l(effect);
+        status = dstThread->addEffect_l(effect);
+        if (status != NO_ERROR) {
+            thread->addEffect_l(effect);
+            status = INVALID_OPERATION;
+            goto Exit;
+        }
+
+        dstChain = effect->chain().promote();
+        if (dstChain == 0) {
+            thread->addEffect_l(effect);
+            status = INVALID_OPERATION;
+        }
+
+Exit:
+        // removeEffect_l() has stopped the effect if it was active so it must be restarted
+        if (effect->state() == EffectModule::ACTIVE ||
+            effect->state() == EffectModule::STOPPING) {
+            effect->start();
+        }
+    }
+
+    if (status == NO_ERROR && srcThread != nullptr) {
+        *srcThread = thread;
+    }
+    return status;
+}
+
 bool AudioFlinger::isNonOffloadableGlobalEffectEnabled_l()
 {
     if (mGlobalEffectEnableTime != 0 &&
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index 9960f0e..72e669a 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -239,6 +239,10 @@
     virtual status_t moveEffects(audio_session_t sessionId, audio_io_handle_t srcOutput,
                         audio_io_handle_t dstOutput);
 
+            void setEffectSuspended(int effectId,
+                                    audio_session_t sessionId,
+                                    bool suspended) override;
+
     virtual audio_module_handle_t loadHwModule(const char *name);
 
     virtual uint32_t getPrimaryOutputSamplingRate();
@@ -369,7 +373,6 @@
 
     AudioHwDevice*          findSuitableHwDev_l(audio_module_handle_t module,
                                                 audio_devices_t devices);
-    void                    purgeStaleEffects_l();
 
     // Set kEnableExtendedChannels to true to enable greater than stereo output
     // for the MixerThread and device sink.  Number of channels allowed is
@@ -696,8 +699,11 @@
 
               status_t moveEffectChain_l(audio_session_t sessionId,
                                      PlaybackThread *srcThread,
-                                     PlaybackThread *dstThread,
-                                     bool reRegister);
+                                     PlaybackThread *dstThread);
+
+              status_t moveAuxEffectToIo(int EffectId,
+                                         const sp<PlaybackThread>& dstThread,
+                                         sp<PlaybackThread> *srcThread);
 
               // return thread associated with primary hardware device, or NULL
               PlaybackThread *primaryPlaybackThread_l() const;
@@ -706,7 +712,7 @@
               // return the playback thread with smallest HAL buffer size, and prefer fast
               PlaybackThread *fastPlaybackThread_l() const;
 
-              sp<PlaybackThread> getEffectThread_l(audio_session_t sessionId, int EffectId);
+              sp<ThreadBase> getEffectThread_l(audio_session_t sessionId, int effectId);
 
 
                 void        removeClient_l(pid_t pid);
@@ -732,6 +738,8 @@
                 // Return true if the effect was found in mOrphanEffectChains, false otherwise.
                 bool            updateOrphanEffectChains(const sp<EffectModule>& effect);
 
+                std::vector< sp<EffectModule> > purgeStaleEffects_l();
+
                 void broacastParametersToRecordThreads_l(const String8& keyValuePairs);
                 void forwardParametersToDownstreamPatches_l(
                         audio_io_handle_t upStream, const String8& keyValuePairs,
diff --git a/services/audioflinger/Effects.cpp b/services/audioflinger/Effects.cpp
index 2b34267..3c4fbba 100644
--- a/services/audioflinger/Effects.cpp
+++ b/services/audioflinger/Effects.cpp
@@ -168,6 +168,68 @@
     return status;
 }
 
+status_t AudioFlinger::EffectModule::updatePolicyState()
+{
+    status_t status = NO_ERROR;
+    bool doRegister = false;
+    bool registered = false;
+    bool doEnable = false;
+    bool enabled = false;
+    audio_io_handle_t io;
+    uint32_t strategy;
+
+    {
+        Mutex::Autolock _l(mLock);
+        // register effect when first handle is attached and unregister when last handle is removed
+        if (mPolicyRegistered != mHandles.size() > 0) {
+            doRegister = true;
+            mPolicyRegistered = mHandles.size() > 0;
+            if (mPolicyRegistered) {
+              sp <EffectChain> chain = mChain.promote();
+              sp <ThreadBase> thread = mThread.promote();
+
+              if (thread == nullptr || chain == nullptr) {
+                    return INVALID_OPERATION;
+                }
+                io = thread->id();
+                strategy = chain->strategy();
+            }
+        }
+        // enable effect when registered according to enable state requested by controlling handle
+        if (mHandles.size() > 0) {
+            EffectHandle *handle = controlHandle_l();
+            if (handle != nullptr && mPolicyEnabled != handle->enabled()) {
+                doEnable = true;
+                mPolicyEnabled = handle->enabled();
+            }
+        }
+        registered = mPolicyRegistered;
+        enabled = mPolicyEnabled;
+        mPolicyLock.lock();
+    }
+    ALOGV("%s name %s id %d session %d doRegister %d registered %d doEnable %d enabled %d",
+        __func__, mDescriptor.name, mId, mSessionId, doRegister, registered, doEnable, enabled);
+    if (doRegister) {
+        if (registered) {
+            status = AudioSystem::registerEffect(
+                &mDescriptor,
+                io,
+                strategy,
+                mSessionId,
+                mId);
+        } else {
+            status = AudioSystem::unregisterEffect(mId);
+        }
+    }
+    if (registered && doEnable) {
+        status = AudioSystem::setEffectEnabled(mId, enabled);
+    }
+    mPolicyLock.unlock();
+
+    return status;
+}
+
+
 ssize_t AudioFlinger::EffectModule::removeHandle(EffectHandle *handle)
 {
     Mutex::Autolock _l(mLock);
@@ -230,7 +292,6 @@
     Mutex::Autolock _l(mLock);
     ssize_t numHandles = removeHandle_l(handle);
     if ((numHandles == 0) && (!mPinned || unpinIfLast)) {
-        AudioSystem::unregisterEffect(mId);
         sp<AudioFlinger> af = mAudioFlinger.promote();
         if (af != 0) {
             mLock.unlock();
@@ -943,11 +1004,6 @@
     ALOGV("setEnabled %p enabled %d", this, enabled);
 
     if (enabled != isEnabled()) {
-        status_t status = AudioSystem::setEffectEnabled(mId, enabled);
-        if (enabled && status != NO_ERROR) {
-            return status;
-        }
-
         switch (mState) {
         // going from disabled to enabled
         case IDLE:
@@ -1253,14 +1309,11 @@
 {
     bool enabled = false;
     Mutex::Autolock _l(mLock);
-    for (size_t i = 0; i < mHandles.size(); i++) {
-        EffectHandle *handle = mHandles[i];
-        if (handle != NULL && !handle->disconnected()) {
-            if (handle->hasControl()) {
-                enabled = handle->enabled();
-            }
-        }
+    EffectHandle *handle = controlHandle_l();
+    if (handle != NULL) {
+        enabled = handle->enabled();
     }
+    mHandles.clear();
     return enabled;
 }
 
@@ -1435,9 +1488,10 @@
         result.append("\t\tCould not lock Fx mutex:\n");
     }
 
-    result.append("\t\tSession Status State Engine:\n");
-    result.appendFormat("\t\t%05d   %03d    %03d   %p\n",
-            mSessionId, mStatus, mState, mEffectInterface.get());
+    result.append("\t\tSession Status State Registered Enabled Suspended Engine:\n");
+    result.appendFormat("\t\t%05d   %03d    %03d   %s          %s       %s         %p\n",
+            mSessionId, mStatus, mState, mPolicyRegistered ? "y" : "n", mPolicyEnabled ? "y" : "n",
+            mSuspended ? "y" : "n", mEffectInterface.get());
 
     result.append("\t\tDescriptor:\n");
     char uuidStr[64];
@@ -1572,6 +1626,12 @@
 
     mEnabled = true;
 
+    status_t status = effect->updatePolicyState();
+    if (status != NO_ERROR) {
+        mEnabled = false;
+        return status;
+    }
+
     sp<ThreadBase> thread = effect->thread().promote();
     if (thread != 0) {
         thread->checkSuspendOnEffectEnabled(effect, true, effect->sessionId());
@@ -1582,7 +1642,7 @@
         return NO_ERROR;
     }
 
-    status_t status = effect->setEnabled(true);
+    status = effect->setEnabled(true);
     if (status != NO_ERROR) {
         if (thread != 0) {
             thread->checkSuspendOnEffectEnabled(effect, false, effect->sessionId());
@@ -1625,6 +1685,8 @@
     }
     mEnabled = false;
 
+    effect->updatePolicyState();
+
     if (effect->suspended()) {
         return NO_ERROR;
     }
@@ -1660,20 +1722,17 @@
         return;
     }
     mDisconnected = true;
-    sp<ThreadBase> thread;
     {
         sp<EffectModule> effect = mEffect.promote();
         if (effect != 0) {
-            thread = effect->thread().promote();
-        }
-    }
-    if (thread != 0) {
-        thread->disconnectEffectHandle(this, unpinIfLast);
-    } else {
-        // try to cleanup as much as we can
-        sp<EffectModule> effect = mEffect.promote();
-        if (effect != 0 && effect->disconnectHandle(this, unpinIfLast) > 0) {
-            ALOGW("%s Effect handle %p disconnected after thread destruction", __FUNCTION__, this);
+            sp<ThreadBase> thread = effect->thread().promote();
+            if (thread != 0) {
+                thread->disconnectEffectHandle(this, unpinIfLast);
+            } else if (effect->disconnectHandle(this, unpinIfLast) > 0) {
+                ALOGW("%s Effect handle %p disconnected after thread destruction",
+                    __func__, this);
+            }
+            effect->updatePolicyState();
         }
     }
 
@@ -1947,6 +2006,16 @@
     return 0;
 }
 
+std::vector<int> AudioFlinger::EffectChain::getEffectIds()
+{
+    std::vector<int> ids;
+    Mutex::Autolock _l(mLock);
+    for (size_t i = 0; i < mEffects.size(); i++) {
+        ids.push_back(mEffects[i]->id());
+    }
+    return ids;
+}
+
 void AudioFlinger::EffectChain::clearInputBuffer()
 {
     Mutex::Autolock _l(mLock);
diff --git a/services/audioflinger/Effects.h b/services/audioflinger/Effects.h
index 58ce351..220874d 100644
--- a/services/audioflinger/Effects.h
+++ b/services/audioflinger/Effects.h
@@ -142,6 +142,8 @@
     void             addEffectToHal_l();
     void             release_l();
 
+    status_t         updatePolicyState();
+
     void             dump(int fd, const Vector<String16>& args);
 
 private:
@@ -204,6 +206,16 @@
     static constexpr pid_t INVALID_PID = (pid_t)-1;
     // this tid is allowed to call setVolume() without acquiring the mutex.
     pid_t mSetVolumeReentrantTid = INVALID_PID;
+
+    // Audio policy effect state management
+    // Mutex protecting transactions with audio policy manager as mLock cannot
+    // be held to avoid cross deadlocks with audio policy mutex
+    Mutex   mPolicyLock;
+    // Effect is registered in APM or not
+    bool    mPolicyRegistered = false;
+    // Effect enabled state communicated to APM. Enabled state corresponds to
+    // state requested by the EffectHandle with control
+    bool    mPolicyEnabled = false;
 };
 
 // The EffectHandle class implements the IEffect interface. It provides resources
@@ -334,6 +346,7 @@
     sp<EffectModule> getEffectFromDesc_l(effect_descriptor_t *descriptor);
     sp<EffectModule> getEffectFromId_l(int id);
     sp<EffectModule> getEffectFromType_l(const effect_uuid_t *type);
+    std::vector<int> getEffectIds();
     // FIXME use float to improve the dynamic range
     bool setVolume_l(uint32_t *left, uint32_t *right, bool force = false);
     void resetVolume_l();
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 6fea8be..59ced26 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -1306,7 +1306,6 @@
     sp<EffectChain> chain;
     bool chainCreated = false;
     bool effectCreated = false;
-    bool effectRegistered = false;
     audio_unique_id_t effectId = AUDIO_UNIQUE_ID_USE_UNSPECIFIED;
 
     lStatus = initCheck();
@@ -1342,13 +1341,6 @@
 
         if (effect == 0) {
             effectId = mAudioFlinger->nextUniqueId(AUDIO_UNIQUE_ID_USE_EFFECT);
-            // Check CPU and memory usage
-            lStatus = AudioSystem::registerEffect(
-                    desc, mId, chain->strategy(), sessionId, effectId);
-            if (lStatus != NO_ERROR) {
-                goto Exit;
-            }
-            effectRegistered = true;
             // create a new effect module if none present in the chain
             lStatus = chain->createEffect_l(effect, this, desc, effectId, sessionId, pinned);
             if (lStatus != NO_ERROR) {
@@ -1378,9 +1370,6 @@
         if (effectCreated) {
             chain->removeEffect_l(effect);
         }
-        if (effectRegistered) {
-            AudioSystem::unregisterEffect(effectId);
-        }
         if (chainCreated) {
             removeEffectChain_l(chain);
         }
@@ -1411,7 +1400,6 @@
     }
     if (remove) {
         mAudioFlinger->updateOrphanEffectChains(effect);
-        AudioSystem::unregisterEffect(effect->id());
         if (handle->enabled()) {
             checkSuspendOnEffectEnabled(effect, false, effect->sessionId());
         }
@@ -1432,6 +1420,12 @@
     return chain != 0 ? chain->getEffectFromId_l(effectId) : 0;
 }
 
+std::vector<int> AudioFlinger::ThreadBase::getEffectIds_l(audio_session_t sessionId)
+{
+    sp<EffectChain> chain = getEffectChain_l(sessionId);
+    return chain != nullptr ? chain->getEffectIds() : std::vector<int>{};
+}
+
 // PlaybackThread::addEffect_l() must be called with AudioFlinger::mLock and
 // PlaybackThread::mLock held
 status_t AudioFlinger::ThreadBase::addEffect_l(const sp<EffectModule>& effect)
@@ -2732,7 +2726,8 @@
     // create a copy of mEffectChains as calling moveEffectChain_l() can reorder some effect chains
     Vector< sp<EffectChain> > effectChains = mEffectChains;
     for (size_t i = 0; i < effectChains.size(); i ++) {
-        mAudioFlinger->moveEffectChain_l(effectChains[i]->sessionId(), this, this, false);
+        mAudioFlinger->moveEffectChain_l(effectChains[i]->sessionId(),
+            this/* srcThread */, this/* dstThread */);
     }
 }
 
@@ -8253,11 +8248,6 @@
 
 status_t AudioFlinger::RecordThread::addEffectChain_l(const sp<EffectChain>& chain)
 {
-    // only one chain per input thread
-    if (!mEffectChains.isEmpty()) {
-        ALOGW("addEffectChain_l() already one chain %p on thread %p", chain.get(), this);
-        return INVALID_OPERATION;
-    }
     ALOGV("addEffectChain_l() %p on thread %p", chain.get(), this);
     chain->setThread(this);
     chain->setInBuffer(NULL);
@@ -8277,13 +8267,14 @@
 size_t AudioFlinger::RecordThread::removeEffectChain_l(const sp<EffectChain>& chain)
 {
     ALOGV("removeEffectChain_l() %p from thread %p", chain.get(), this);
-    ALOGW_IF(mEffectChains.size() != 1,
-            "removeEffectChain_l() %p invalid chain size %zu on thread %p",
-            chain.get(), mEffectChains.size(), this);
-    if (mEffectChains.size() == 1) {
-        mEffectChains.removeAt(0);
+
+    for (size_t i = 0; i < mEffectChains.size(); i++) {
+        if (chain == mEffectChains[i]) {
+            mEffectChains.removeAt(i);
+            break;
+        }
     }
-    return 0;
+    return mEffectChains.size();
 }
 
 status_t AudioFlinger::RecordThread::createAudioPatch_l(const struct audio_patch *patch,
diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h
index 18cb361..37b2d08 100644
--- a/services/audioflinger/Threads.h
+++ b/services/audioflinger/Threads.h
@@ -315,6 +315,7 @@
                 sp<EffectChain> getEffectChain(audio_session_t sessionId);
                 // same as getEffectChain() but must be called with ThreadBase mutex locked
                 sp<EffectChain> getEffectChain_l(audio_session_t sessionId) const;
+                std::vector<int> getEffectIds_l(audio_session_t sessionId);
                 // add an effect chain to the chain list (mEffectChains)
     virtual     status_t addEffectChain_l(const sp<EffectChain>& chain) = 0;
                 // remove an effect chain from the chain list (mEffectChains)
@@ -334,7 +335,8 @@
                 sp<AudioFlinger::EffectModule> getEffect(audio_session_t sessionId, int effectId);
                 sp<AudioFlinger::EffectModule> getEffect_l(audio_session_t sessionId, int effectId);
                 // add and effect module. Also creates the effect chain is none exists for
-                // the effects audio session
+                // the effects audio session. Only called in a context of moving an effect
+                // from one thread to another
                 status_t addEffect_l(const sp< EffectModule>& effect);
                 // remove and effect module. Also removes the effect chain is this was the last
                 // effect
diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp
index bbda17f..2ff80c6 100644
--- a/services/audioflinger/Tracks.cpp
+++ b/services/audioflinger/Tracks.cpp
@@ -1244,54 +1244,25 @@
 
 status_t AudioFlinger::PlaybackThread::Track::attachAuxEffect(int EffectId)
 {
-    status_t status = DEAD_OBJECT;
     sp<ThreadBase> thread = mThread.promote();
-    if (thread != 0) {
-        PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
-        sp<AudioFlinger> af = mClient->audioFlinger();
+    if (thread == nullptr) {
+        return DEAD_OBJECT;
+    }
 
-        Mutex::Autolock _l(af->mLock);
+    sp<PlaybackThread> dstThread = (PlaybackThread *)thread.get();
+    sp<PlaybackThread> srcThread; // srcThread is initialized by call to moveAuxEffectToIo()
+    sp<AudioFlinger> af = mClient->audioFlinger();
+    status_t status = af->moveAuxEffectToIo(EffectId, dstThread, &srcThread);
 
-        sp<PlaybackThread> srcThread = af->getEffectThread_l(AUDIO_SESSION_OUTPUT_MIX, EffectId);
-
-        if (EffectId != 0 && srcThread != 0 && playbackThread != srcThread.get()) {
-            Mutex::Autolock _dl(playbackThread->mLock);
-            Mutex::Autolock _sl(srcThread->mLock);
-            sp<EffectChain> chain = srcThread->getEffectChain_l(AUDIO_SESSION_OUTPUT_MIX);
-            if (chain == 0) {
-                return INVALID_OPERATION;
-            }
-
-            sp<EffectModule> effect = chain->getEffectFromId_l(EffectId);
-            if (effect == 0) {
-                return INVALID_OPERATION;
-            }
-            srcThread->removeEffect_l(effect);
-            status = playbackThread->addEffect_l(effect);
-            if (status != NO_ERROR) {
-                srcThread->addEffect_l(effect);
-                return INVALID_OPERATION;
-            }
-            // removeEffect_l() has stopped the effect if it was active so it must be restarted
-            if (effect->state() == EffectModule::ACTIVE ||
-                    effect->state() == EffectModule::STOPPING) {
-                effect->start();
-            }
-
-            sp<EffectChain> dstChain = effect->chain().promote();
-            if (dstChain == 0) {
-                srcThread->addEffect_l(effect);
-                return INVALID_OPERATION;
-            }
-            AudioSystem::unregisterEffect(effect->id());
-            AudioSystem::registerEffect(&effect->desc(),
-                                        srcThread->id(),
-                                        dstChain->strategy(),
-                                        AUDIO_SESSION_OUTPUT_MIX,
-                                        effect->id());
-            AudioSystem::setEffectEnabled(effect->id(), effect->isEnabled());
+    if (EffectId != 0 && status == NO_ERROR) {
+        status = dstThread->attachAuxEffect(this, EffectId);
+        if (status == NO_ERROR) {
+            AudioSystem::moveEffectsToIo(std::vector<int>(EffectId), dstThread->id());
         }
-        status = playbackThread->attachAuxEffect(this, EffectId);
+    }
+
+    if (status != NO_ERROR && srcThread != nullptr) {
+        af->moveAuxEffectToIo(EffectId, srcThread, &dstThread);
     }
     return status;
 }
diff --git a/services/audiopolicy/AudioPolicyInterface.h b/services/audiopolicy/AudioPolicyInterface.h
index a2cf7aa..4b56a46 100644
--- a/services/audiopolicy/AudioPolicyInterface.h
+++ b/services/audiopolicy/AudioPolicyInterface.h
@@ -189,6 +189,7 @@
                                     int id) = 0;
     virtual status_t unregisterEffect(int id) = 0;
     virtual status_t setEffectEnabled(int id, bool enabled) = 0;
+    virtual status_t moveEffectsToIo(const std::vector<int>& ids, audio_io_handle_t io) = 0;
 
     virtual bool isStreamActive(audio_stream_type_t stream, uint32_t inPastMs = 0) const = 0;
     virtual bool isStreamActiveRemotely(audio_stream_type_t stream,
@@ -347,6 +348,10 @@
                                      audio_io_handle_t srcOutput,
                                      audio_io_handle_t dstOutput) = 0;
 
+    virtual void setEffectSuspended(int effectId,
+                                    audio_session_t sessionId,
+                                    bool suspended) = 0;
+
     /* Create a patch between several source and sink ports */
     virtual status_t createAudioPatch(const struct audio_patch *patch,
                                        audio_patch_handle_t *handle,
diff --git a/services/audiopolicy/common/include/Volume.h b/services/audiopolicy/common/include/Volume.h
index 54c5c76..1dbd1eb 100644
--- a/services/audiopolicy/common/include/Volume.h
+++ b/services/audiopolicy/common/include/Volume.h
@@ -23,7 +23,6 @@
 
 namespace android {
 
-
 /**
  * VolumeSource is the discriminent for volume management on an output.
  * It used to be the stream type by legacy, it may be host volume group or a volume curves if
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioInputDescriptor.h b/services/audiopolicy/common/managerdefinitions/include/AudioInputDescriptor.h
index e071fe0..37f9d14 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioInputDescriptor.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioInputDescriptor.h
@@ -68,11 +68,13 @@
     bool isSourceActive(audio_source_t source) const;
     audio_source_t source() const;
     bool isSoundTrigger() const;
+    sp<RecordClientDescriptor> getHighestPriorityClient() const;
     audio_attributes_t getHighestPriorityAttributes() const;
     void setClientActive(const sp<RecordClientDescriptor>& client, bool active);
     int32_t activeCount() { return mGlobalActiveCount; }
     void trackEffectEnabled(const sp<EffectDescriptor> &effect, bool enabled);
     EffectDescriptorCollection getEnabledEffects() const;
+    EffectDescriptorCollection getActiveEffects() const; // enabled and not suspended
     // implementation of AudioIODescriptorInterface
     audio_config_base_t getConfig() const override;
     audio_patch_handle_t getPatchHandle() const override;
@@ -100,6 +102,10 @@
     // implementation of ClientMapHandler<RecordClientDescriptor>
     void addClient(const sp<RecordClientDescriptor> &client) override;
 
+    // Go over all active clients and suspend or restore effects according highest priority
+    // active use case
+    void checkSuspendEffects();
+
  private:
 
     void updateClientRecordingConfiguration(int event, const sp<RecordClientDescriptor>& client);
diff --git a/services/audiopolicy/common/managerdefinitions/include/EffectDescriptor.h b/services/audiopolicy/common/managerdefinitions/include/EffectDescriptor.h
index 7f01dc5..c4eab30 100644
--- a/services/audiopolicy/common/managerdefinitions/include/EffectDescriptor.h
+++ b/services/audiopolicy/common/managerdefinitions/include/EffectDescriptor.h
@@ -29,8 +29,8 @@
 {
 public:
     EffectDescriptor(const effect_descriptor_t *desc, bool isMusicEffect,
-                     int id, int io, int session) :
-        mId(id), mIo(io), mSession(session), mEnabled(false),
+                     int id, audio_io_handle_t io, audio_session_t session) :
+        mId(id), mIo(io), mSession(session), mEnabled(false), mSuspended(false),
         mIsMusicEffect(isMusicEffect)
     {
         memcpy (&mDesc, desc, sizeof(effect_descriptor_t));
@@ -38,11 +38,12 @@
 
     void dump(String8 *dst, int spaces = 0) const;
 
-    int mId;                // effect unique ID
-    int mIo;                // io the effect is attached to
-    int mSession;               // audio session the effect is on
-    effect_descriptor_t mDesc;  // effect descriptor
-    bool mEnabled;              // enabled state: CPU load being used or not
+    int mId;                   // effect unique ID
+    audio_io_handle_t mIo;     // io the effect is attached to
+    audio_session_t mSession;  // audio session the effect is on
+    effect_descriptor_t mDesc; // effect descriptor
+    bool mEnabled;             // enabled state: CPU load being used or not
+    bool mSuspended;           // enabled but suspended by concurent capture policy
 
     bool isMusicEffect() const { return mIsMusicEffect; }
 
@@ -59,12 +60,18 @@
                             int session, int id, bool isMusicEffect);
     status_t unregisterEffect(int id);
     sp<EffectDescriptor> getEffect(int id) const;
+    EffectDescriptorCollection getEffectsForIo(audio_io_handle_t io) const;
     status_t setEffectEnabled(int id, bool enabled);
     bool     isEffectEnabled(int id) const;
     uint32_t getMaxEffectsCpuLoad() const;
     uint32_t getMaxEffectsMemory() const;
     bool isNonOffloadableEffectEnabled() const;
 
+    void moveEffects(audio_session_t session,
+                     audio_io_handle_t srcOutput,
+                     audio_io_handle_t dstOutput);
+    void moveEffects(const std::vector<int>& ids, audio_io_handle_t dstOutput);
+
     void dump(String8 *dst, int spaces = 0, bool verbose = true) const;
 
 private:
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioInputDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioInputDescriptor.cpp
index 5b4e2eb..58683be 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioInputDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioInputDescriptor.cpp
@@ -128,6 +128,13 @@
 audio_attributes_t AudioInputDescriptor::getHighestPriorityAttributes() const
 {
     audio_attributes_t attributes = { .source = AUDIO_SOURCE_DEFAULT };
+    sp<RecordClientDescriptor> topClient = getHighestPriorityClient();
+    return topClient ? topClient->attributes() : attributes;
+}
+
+sp<RecordClientDescriptor> AudioInputDescriptor::getHighestPriorityClient() const
+{
+    sp<RecordClientDescriptor> topClient;
 
     for (bool activeOnly : { true, false }) {
         int32_t topPriority = -1;
@@ -139,18 +146,18 @@
             app_state_t curState = client->appState();
             if (curState >= topState) {
                 int32_t curPriority = source_priority(client->source());
-                if (curPriority > topPriority) {
-                    attributes = client->attributes();
+                if (curPriority >= topPriority) {
+                    topClient = client;
                     topPriority = curPriority;
                 }
                 topState = curState;
             }
         }
-        if (attributes.source != AUDIO_SOURCE_DEFAULT) {
+        if (topClient != nullptr) {
             break;
         }
     }
-    return attributes;
+    return topClient;
 }
 
 bool AudioInputDescriptor::isSoundTrigger() const {
@@ -326,9 +333,10 @@
 
     client->setActive(active);
 
+    checkSuspendEffects();
+
     int event = active ? RECORD_CONFIG_EVENT_START : RECORD_CONFIG_EVENT_STOP;
     updateClientRecordingConfiguration(event, client);
-
 }
 
 void AudioInputDescriptor::updateClientRecordingConfiguration(
@@ -397,44 +405,90 @@
         mEnabledEffects.replaceValueFor(effect->mId, effect);
     } else {
         mEnabledEffects.removeItem(effect->mId);
+        // always exit from suspend when disabling an effect as only enabled effects
+        // are managed by checkSuspendEffects()
+        if (effect->mSuspended) {
+            effect->mSuspended = false;
+            mClientInterface->setEffectSuspended(effect->mId, effect->mSession, effect->mSuspended);
+        }
     }
 
     RecordClientVector clients = getClientsForSession((audio_session_t)effect->mSession);
+    RecordClientVector updatedClients;
+
     for (const auto& client : clients) {
         sp<EffectDescriptor> clientEffect = client->getEnabledEffects().getEffect(effect->mId);
         bool changed = (enabled && clientEffect == nullptr)
                 || (!enabled && clientEffect != nullptr);
         client->trackEffectEnabled(effect, enabled);
         if (changed && client->active()) {
-            updateClientRecordingConfiguration(RECORD_CONFIG_EVENT_START, client);
+            updatedClients.push_back(client);
         }
     }
+
+    checkSuspendEffects();
+
+    for (const auto& client : updatedClients) {
+        updateClientRecordingConfiguration(RECORD_CONFIG_EVENT_START, client);
+    }
 }
 
 EffectDescriptorCollection AudioInputDescriptor::getEnabledEffects() const
 {
-    EffectDescriptorCollection enabledEffects;
     // report effects for highest priority active source as applied to all clients
-    RecordClientVector clients =
-        clientsList(true /*activeOnly*/, source(), false /*preferredDeviceOnly*/);
-    if (clients.size() > 0) {
-        enabledEffects = clients[0]->getEnabledEffects();
+    EffectDescriptorCollection enabledEffects;
+    sp<RecordClientDescriptor> topClient = getHighestPriorityClient();
+    if (topClient != nullptr) {
+        enabledEffects = topClient->getEnabledEffects();
     }
     return enabledEffects;
 }
 
-void AudioInputDescriptor::setAppState(uid_t uid, app_state_t state) {
+void AudioInputDescriptor::setAppState(uid_t uid, app_state_t state)
+{
     RecordClientVector clients = clientsList(false /*activeOnly*/);
+    RecordClientVector updatedClients;
 
     for (const auto& client : clients) {
         if (uid == client->uid()) {
             bool wasSilenced = client->isSilenced();
             client->setAppState(state);
             if (client->active() && wasSilenced != client->isSilenced()) {
-                updateClientRecordingConfiguration(RECORD_CONFIG_EVENT_START, client);
+                updatedClients.push_back(client);
             }
         }
     }
+
+    checkSuspendEffects();
+
+    for (const auto& client : updatedClients) {
+        updateClientRecordingConfiguration(RECORD_CONFIG_EVENT_START, client);
+    }
+}
+
+void AudioInputDescriptor::checkSuspendEffects()
+{
+    sp<RecordClientDescriptor> topClient = getHighestPriorityClient();
+    if (topClient == nullptr) {
+        return;
+    }
+
+    for (size_t i = 0; i < mEnabledEffects.size(); i++) {
+        sp<EffectDescriptor> effect = mEnabledEffects.valueAt(i);
+        if (effect->mSession == topClient->session()) {
+            if (effect->mSuspended) {
+                effect->mSuspended = false;
+                mClientInterface->setEffectSuspended(effect->mId,
+                                                     effect->mSession,
+                                                     effect->mSuspended);
+            }
+        } else if (!effect->mSuspended) {
+            effect->mSuspended = true;
+            mClientInterface->setEffectSuspended(effect->mId,
+                                                 effect->mSession,
+                                                 effect->mSuspended);
+        }
+    }
 }
 
 void AudioInputDescriptor::dump(String8 *dst) const
@@ -444,7 +498,7 @@
     dst->appendFormat(" Format: %d\n", mFormat);
     dst->appendFormat(" Channels: %08x\n", mChannelMask);
     dst->appendFormat(" Devices %s\n", mDevice->toString().c_str());
-    getEnabledEffects().dump(dst, 1 /*spaces*/, false /*verbose*/);
+    mEnabledEffects.dump(dst, 1 /*spaces*/, false /*verbose*/);
     dst->append(" AudioRecord Clients:\n");
     ClientMapHandler<RecordClientDescriptor>::dump(dst);
     dst->append("\n");
diff --git a/services/audiopolicy/common/managerdefinitions/src/EffectDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/EffectDescriptor.cpp
index 89f9899..415962a 100644
--- a/services/audiopolicy/common/managerdefinitions/src/EffectDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/EffectDescriptor.cpp
@@ -30,6 +30,7 @@
     dst->appendFormat("%*sSession: %d\n", spaces, "", mSession);
     dst->appendFormat("%*sName: %s\n", spaces, "",  mDesc.name);
     dst->appendFormat("%*s%s\n", spaces, "",  mEnabled ? "Enabled" : "Disabled");
+    dst->appendFormat("%*s%s\n", spaces, "",  mSuspended ? "Suspended" : "Active");
 }
 
 EffectDescriptorCollection::EffectDescriptorCollection() :
@@ -63,7 +64,8 @@
             desc->name, io, session, id);
     ALOGV("registerEffect() memory %d, total memory %d", desc->memoryUsage, mTotalEffectsMemory);
 
-    sp<EffectDescriptor> effectDesc = new EffectDescriptor(desc, isMusicEffect, id, io, session);
+    sp<EffectDescriptor> effectDesc =
+        new EffectDescriptor(desc, isMusicEffect, id, io, (audio_session_t)session);
     add(id, effectDesc);
 
     return NO_ERROR;
@@ -174,6 +176,43 @@
     return MAX_EFFECTS_MEMORY;
 }
 
+void EffectDescriptorCollection::moveEffects(audio_session_t session,
+                                             audio_io_handle_t srcOutput,
+                                             audio_io_handle_t dstOutput)
+{
+    ALOGV("%s session %d srcOutput %d dstOutput %d", __func__, session, srcOutput, dstOutput);
+    for (size_t i = 0; i < size(); i++) {
+        sp<EffectDescriptor> effect = valueAt(i);
+        if (effect->mSession == session && effect->mIo == srcOutput) {
+            effect->mIo = dstOutput;
+        }
+    }
+}
+
+void EffectDescriptorCollection::moveEffects(const std::vector<int>& ids,
+                                             audio_io_handle_t dstOutput)
+{
+    ALOGV("%s num effects %zu, first ID %d, dstOutput %d",
+        __func__, ids.size(), ids.size() ? ids[0] : 0, dstOutput);
+    for (size_t i = 0; i < size(); i++) {
+        sp<EffectDescriptor> effect = valueAt(i);
+        if (std::find(begin(ids), end(ids), effect->mId) != end(ids)) {
+            effect->mIo = dstOutput;
+        }
+    }
+}
+
+EffectDescriptorCollection EffectDescriptorCollection::getEffectsForIo(audio_io_handle_t io) const
+{
+    EffectDescriptorCollection effects;
+    for (size_t i = 0; i < size(); i++) {
+        if (valueAt(i)->mIo == io) {
+            effects.add(keyAt(i), valueAt(i));
+        }
+    }
+    return effects;
+}
+
 void EffectDescriptorCollection::dump(String8 *dst, int spaces, bool verbose) const
 {
     if (verbose) {
diff --git a/services/audiopolicy/engineconfigurable/config/example/automotive/audio_policy_engine_product_strategies.xml b/services/audiopolicy/engineconfigurable/config/example/automotive/audio_policy_engine_product_strategies.xml
index c487da9..0ee83a2 100644
--- a/services/audiopolicy/engineconfigurable/config/example/automotive/audio_policy_engine_product_strategies.xml
+++ b/services/audiopolicy/engineconfigurable/config/example/automotive/audio_policy_engine_product_strategies.xml
@@ -166,5 +166,20 @@
             <Attributes> <Flags value="AUDIO_FLAG_BEACON"/> </Attributes>
         </AttributesGroup>
     </ProductStrategy>
+
+    <!-- Routing Strategy rerouting may be removed as following media??? -->
+    <ProductStrategy name="rerouting">
+        <AttributesGroup streamType="AUDIO_STREAM_REROUTING" volumeGroup="rerouting">
+            <Attributes></Attributes>
+        </AttributesGroup>
+    </ProductStrategy>
+
+    <!-- Patch stream needs full scale volume, define it otherwise switch to default... -->
+    <ProductStrategy name="patch">
+        <AttributesGroup streamType="AUDIO_STREAM_PATCH" volumeGroup="patch">
+            <Attributes></Attributes>
+        </AttributesGroup>
+    </ProductStrategy>
+
 </ProductStrategies>
 
diff --git a/services/audiopolicy/engineconfigurable/config/example/automotive/audio_policy_engine_volumes.xml b/services/audiopolicy/engineconfigurable/config/example/automotive/audio_policy_engine_volumes.xml
index 9ec3d77..6e72dc5 100644
--- a/services/audiopolicy/engineconfigurable/config/example/automotive/audio_policy_engine_volumes.xml
+++ b/services/audiopolicy/engineconfigurable/config/example/automotive/audio_policy_engine_volumes.xml
@@ -188,5 +188,26 @@
             <point>100,0</point>
         </volume>
     </volumeGroup>
+
+    <volumeGroup>
+        <name>rerouting</name>
+        <indexMin>0</indexMin>
+        <indexMax>1</indexMax>
+        <volume deviceCategory="DEVICE_CATEGORY_HEADSET">
+            <point>0,0</point>
+            <point>100,0</point>
+        </volume>
+    </volumeGroup>
+
+    <volumeGroup>
+        <name>patch</name>
+        <indexMin>0</indexMin>
+        <indexMax>1</indexMax>
+        <volume deviceCategory="DEVICE_CATEGORY_HEADSET">
+            <point>0,0</point>
+            <point>100,0</point>
+        </volume>
+    </volumeGroup>
+
 </volumeGroups>
 
diff --git a/services/audiopolicy/engineconfigurable/config/example/caremu/audio_policy_engine_product_strategies.xml b/services/audiopolicy/engineconfigurable/config/example/caremu/audio_policy_engine_product_strategies.xml
index c487da9..adcbd83 100644
--- a/services/audiopolicy/engineconfigurable/config/example/caremu/audio_policy_engine_product_strategies.xml
+++ b/services/audiopolicy/engineconfigurable/config/example/caremu/audio_policy_engine_product_strategies.xml
@@ -166,5 +166,19 @@
             <Attributes> <Flags value="AUDIO_FLAG_BEACON"/> </Attributes>
         </AttributesGroup>
     </ProductStrategy>
+
+    <!-- Routing Strategy rerouting may be removed as following media??? -->
+    <ProductStrategy name="rerouting">
+        <AttributesGroup streamType="AUDIO_STREAM_REROUTING" volumeGroup="rerouting">
+            <Attributes></Attributes>
+        </AttributesGroup>
+    </ProductStrategy>
+
+    <!-- Patch stream needs full scale volume, define it otherwise switch to default... -->
+    <ProductStrategy name="patch">
+        <AttributesGroup streamType="AUDIO_STREAM_PATCH" volumeGroup="patch">
+            <Attributes></Attributes>
+        </AttributesGroup>
+    </ProductStrategy>
 </ProductStrategies>
 
diff --git a/services/audiopolicy/engineconfigurable/config/example/caremu/audio_policy_engine_volumes.xml b/services/audiopolicy/engineconfigurable/config/example/caremu/audio_policy_engine_volumes.xml
index 9ec3d77..6e72dc5 100644
--- a/services/audiopolicy/engineconfigurable/config/example/caremu/audio_policy_engine_volumes.xml
+++ b/services/audiopolicy/engineconfigurable/config/example/caremu/audio_policy_engine_volumes.xml
@@ -188,5 +188,26 @@
             <point>100,0</point>
         </volume>
     </volumeGroup>
+
+    <volumeGroup>
+        <name>rerouting</name>
+        <indexMin>0</indexMin>
+        <indexMax>1</indexMax>
+        <volume deviceCategory="DEVICE_CATEGORY_HEADSET">
+            <point>0,0</point>
+            <point>100,0</point>
+        </volume>
+    </volumeGroup>
+
+    <volumeGroup>
+        <name>patch</name>
+        <indexMin>0</indexMin>
+        <indexMax>1</indexMax>
+        <volume deviceCategory="DEVICE_CATEGORY_HEADSET">
+            <point>0,0</point>
+            <point>100,0</point>
+        </volume>
+    </volumeGroup>
+
 </volumeGroups>
 
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index af29f87..6bd64d6 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -142,18 +142,7 @@
                     __func__, device->toString().c_str(), encodedFormat);
 
             // register new device as available
-            index = mAvailableOutputDevices.add(device);
-            if (index >= 0) {
-                sp<HwModule> module = mHwModules.getModuleForDevice(device, encodedFormat);
-                if (module == 0) {
-                    ALOGD("setDeviceConnectionState() could not find HW module for device %s",
-                          device->toString().c_str());
-                    mAvailableOutputDevices.remove(device);
-                    return INVALID_OPERATION;
-                }
-                ALOGV("setDeviceConnectionState() module name=%s", module->getName());
-                mAvailableOutputDevices[index]->attach(module);
-            } else {
+            if (mAvailableOutputDevices.add(device) < 0) {
                 return NO_MEMORY;
             }
 
@@ -295,13 +284,6 @@
                 ALOGW("%s() device already connected: %s", __func__, device->toString().c_str());
                 return INVALID_OPERATION;
             }
-            sp<HwModule> module = mHwModules.getModuleForDevice(device, AUDIO_FORMAT_DEFAULT);
-            if (module == NULL) {
-                ALOGW("setDeviceConnectionState(): could not find HW module for device %s",
-                      device->toString().c_str());
-                return INVALID_OPERATION;
-            }
-
             // 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);
@@ -2361,25 +2343,8 @@
 }
 
 void AudioPolicyManager::closeAllInputs() {
-    bool patchRemoved = false;
-
-    for (size_t input_index = 0; input_index < mInputs.size(); input_index++) {
-        sp<AudioInputDescriptor> inputDesc = mInputs.valueAt(input_index);
-        ssize_t patch_index = mAudioPatches.indexOfKey(inputDesc->getPatchHandle());
-        if (patch_index >= 0) {
-            sp<AudioPatch> patchDesc = mAudioPatches.valueAt(patch_index);
-            (void) /*status_t status*/ mpClientInterface->releaseAudioPatch(patchDesc->mAfPatchHandle, 0);
-            mAudioPatches.removeItemsAt(patch_index);
-            patchRemoved = true;
-        }
-        inputDesc->close();
-    }
-    mInputs.clear();
-    SoundTrigger::setCaptureState(false);
-    nextAudioPortGeneration();
-
-    if (patchRemoved) {
-        mpClientInterface->onAudioPatchListUpdate();
+    while (mInputs.size() != 0) {
+        closeInput(mInputs.keyAt(0));
     }
 }
 
@@ -2481,7 +2446,7 @@
         // HW Gain management, do not change the volume
         bool applyVolume = false;
         if (desc->useHwGain()) {
-            if (!(desc->isActive(group) || isInCall())) {
+            if (!(desc->isActive(toVolumeSource(group)) || isInCall())) {
                 continue;
             }
             for (const auto &productStrategy : mEngine->getOrderedProductStrategies()) {
@@ -2675,6 +2640,7 @@
     }
 
     if (output != mMusicEffectOutput) {
+        mEffects.moveEffects(AUDIO_SESSION_OUTPUT_MIX, mMusicEffectOutput, output);
         mpClientInterface->moveEffects(AUDIO_SESSION_OUTPUT_MIX, mMusicEffectOutput, output);
         mMusicEffectOutput = output;
     }
@@ -2712,7 +2678,6 @@
     if (mEffects.getEffect(id) == nullptr) {
         return INVALID_OPERATION;
     }
-
     if (mEffects.isEffectEnabled(id)) {
         ALOGW("%s effect %d enabled", __FUNCTION__, id);
         setEffectEnabled(id, false);
@@ -2720,6 +2685,16 @@
     return mEffects.unregisterEffect(id);
 }
 
+void AudioPolicyManager::cleanUpEffectsForIo(audio_io_handle_t io)
+{
+    EffectDescriptorCollection effects = mEffects.getEffectsForIo(io);
+    for (size_t i = 0; i < effects.size(); i++) {
+        ALOGW("%s removing stale effect %s, id %d on closed IO %d",
+              __func__, effects.valueAt(i)->mDesc.name, effects.keyAt(i), io);
+        unregisterEffect(effects.keyAt(i));
+    }
+}
+
 status_t AudioPolicyManager::setEffectEnabled(int id, bool enabled)
 {
     sp<EffectDescriptor> effect = mEffects.getEffect(id);
@@ -2734,6 +2709,13 @@
     return status;
 }
 
+
+status_t AudioPolicyManager::moveEffectsToIo(const std::vector<int>& ids, audio_io_handle_t io)
+{
+   mEffects.moveEffects(ids, io);
+   return NO_ERROR;
+}
+
 bool AudioPolicyManager::isStreamActive(audio_stream_type_t stream, uint32_t inPastMs) const
 {
     return mOutputs.isActive(toVolumeSource(stream), inPastMs);
@@ -4105,15 +4087,8 @@
 void AudioPolicyManager::setAppState(uid_t uid, app_state_t state)
 {
     ALOGV("%s(uid:%d, state:%d)", __func__, uid, state);
-
     for (size_t i = 0; i < mInputs.size(); i++) {
-        sp<AudioInputDescriptor> inputDesc = mInputs.valueAt(i);
-        RecordClientVector clients = inputDesc->clientsList(false /*activeOnly*/);
-        for (const auto& client : clients) {
-            if (uid == client->uid()) {
-                client->setAppState(state);
-            }
-        }
+        mInputs.valueAt(i)->setAppState(uid, state);
     }
 }
 
@@ -4924,6 +4899,8 @@
             setMsdPatch();
         }
     }
+
+    cleanUpEffectsForIo(output);
 }
 
 void AudioPolicyManager::closeInput(audio_io_handle_t input)
@@ -4955,6 +4932,8 @@
             mInputs.activeInputsCountOnDevices(primaryInputDevices) == 0) {
         SoundTrigger::setCaptureState(false);
     }
+
+    cleanUpEffectsForIo(input);
 }
 
 SortedVector<audio_io_handle_t> AudioPolicyManager::getOutputsForDevices(
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.h b/services/audiopolicy/managerdefault/AudioPolicyManager.h
index de447fb..3376965 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.h
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.h
@@ -200,6 +200,7 @@
                                         int id);
         virtual status_t unregisterEffect(int id);
         virtual status_t setEffectEnabled(int id, bool enabled);
+        status_t moveEffectsToIo(const std::vector<int>& ids, audio_io_handle_t io) override;
 
         virtual bool isStreamActive(audio_stream_type_t stream, uint32_t inPastMs = 0) const;
         // return whether a stream is playing remotely, override to change the definition of
@@ -344,7 +345,7 @@
         }
         virtual const DeviceVector getAvailableOutputDevices() const
         {
-            return mAvailableOutputDevices.filterForEngine();
+            return mAvailableOutputDevices;
         }
         virtual const DeviceVector getAvailableInputDevices() const
         {
@@ -869,6 +870,8 @@
                 int delayMs,
                 uid_t uid,
                 sp<AudioPatch> *patchDescPtr);
+
+        void cleanUpEffectsForIo(audio_io_handle_t io);
 };
 
 };
diff --git a/services/audiopolicy/service/AudioPolicyClientImpl.cpp b/services/audiopolicy/service/AudioPolicyClientImpl.cpp
index 5748334..d51cc6e 100644
--- a/services/audiopolicy/service/AudioPolicyClientImpl.cpp
+++ b/services/audiopolicy/service/AudioPolicyClientImpl.cpp
@@ -172,6 +172,13 @@
     return af->moveEffects(session, src_output, dst_output);
 }
 
+void AudioPolicyService::AudioPolicyClient::setEffectSuspended(int effectId,
+                                audio_session_t sessionId,
+                                bool suspended)
+{
+    mAudioPolicyService->setEffectSuspended(effectId, sessionId, suspended);
+}
+
 status_t AudioPolicyService::AudioPolicyClient::createAudioPatch(const struct audio_patch *patch,
                                                                   audio_patch_handle_t *handle,
                                                                   int delayMs)
diff --git a/services/audiopolicy/service/AudioPolicyEffects.h b/services/audiopolicy/service/AudioPolicyEffects.h
index 6ad01f7..dcf093b 100644
--- a/services/audiopolicy/service/AudioPolicyEffects.h
+++ b/services/audiopolicy/service/AudioPolicyEffects.h
@@ -225,6 +225,8 @@
                          size_t *totSize);
 
     // protects access to mInputSources, mInputSessions, mOutputStreams, mOutputSessions
+    // never hold AudioPolicyService::mLock when calling AudioPolicyEffects methods as
+    // those can call back into AudioPolicyService methods and try to acquire the mutex
     Mutex mLock;
     // Automatic input effects are configured per audio_source_t
     KeyedVector< audio_source_t, EffectDescVector* > mInputSources;
diff --git a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
index 2eb272e..2e47eb6 100644
--- a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
+++ b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
@@ -797,7 +797,7 @@
     if (mAudioPolicyManager == NULL) {
         return NO_INIT;
     }
-    Mutex::Autolock _l(mEffectsLock);
+    Mutex::Autolock _l(mLock);
     AutoCallerClear acc;
     return mAudioPolicyManager->registerEffect(desc, io, strategy, session, id);
 }
@@ -807,7 +807,7 @@
     if (mAudioPolicyManager == NULL) {
         return NO_INIT;
     }
-    Mutex::Autolock _l(mEffectsLock);
+    Mutex::Autolock _l(mLock);
     AutoCallerClear acc;
     return mAudioPolicyManager->unregisterEffect(id);
 }
@@ -817,11 +817,21 @@
     if (mAudioPolicyManager == NULL) {
         return NO_INIT;
     }
-    Mutex::Autolock _l(mEffectsLock);
+    Mutex::Autolock _l(mLock);
     AutoCallerClear acc;
     return mAudioPolicyManager->setEffectEnabled(id, enabled);
 }
 
+status_t AudioPolicyService::moveEffectsToIo(const std::vector<int>& ids, audio_io_handle_t io)
+{
+    if (mAudioPolicyManager == NULL) {
+        return NO_INIT;
+    }
+    Mutex::Autolock _l(mLock);
+    AutoCallerClear acc;
+    return mAudioPolicyManager->moveEffectsToIo(ids, io);
+}
+
 bool AudioPolicyService::isStreamActive(audio_stream_type_t stream, uint32_t inPastMs) const
 {
     if (uint32_t(stream) >= AUDIO_STREAM_PUBLIC_CNT) {
@@ -973,8 +983,6 @@
         return false;
     }
     Mutex::Autolock _l(mLock);
-    Mutex::Autolock _le(mEffectsLock); // isOffloadSupported queries for
-                                      // non-offloadable effects
     AutoCallerClear acc;
     return mAudioPolicyManager->isOffloadSupported(info);
 }
diff --git a/services/audiopolicy/service/AudioPolicyService.cpp b/services/audiopolicy/service/AudioPolicyService.cpp
index f63fa81..5389c08 100644
--- a/services/audiopolicy/service/AudioPolicyService.cpp
+++ b/services/audiopolicy/service/AudioPolicyService.cpp
@@ -1196,6 +1196,17 @@
                             data->mPatchHandle, data->mSource);
                     mLock.lock();
                     } break;
+                case SET_EFFECT_SUSPENDED: {
+                    SetEffectSuspendedData *data = (SetEffectSuspendedData *)command->mParam.get();
+                    ALOGV("AudioCommandThread() processing set effect suspended");
+                    sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
+                    if (af != 0) {
+                        mLock.unlock();
+                        af->setEffectSuspended(data->mEffectId, data->mSessionId, data->mSuspended);
+                        mLock.lock();
+                    }
+                    } break;
+
                 default:
                     ALOGW("AudioCommandThread() unknown command %d", command->mCommand);
                 }
@@ -1327,6 +1338,23 @@
     return sendCommand(command, delayMs);
 }
 
+void AudioPolicyService::AudioCommandThread::setEffectSuspendedCommand(int effectId,
+                                                                       audio_session_t sessionId,
+                                                                       bool suspended)
+{
+    sp<AudioCommand> command = new AudioCommand();
+    command->mCommand = SET_EFFECT_SUSPENDED;
+    sp<SetEffectSuspendedData> data = new SetEffectSuspendedData();
+    data->mEffectId = effectId;
+    data->mSessionId = sessionId;
+    data->mSuspended = suspended;
+    command->mParam = data;
+    ALOGV("AudioCommandThread() adding set suspended effectId %d sessionId %d suspended %d",
+        effectId, sessionId, suspended);
+    sendCommand(command);
+}
+
+
 void AudioPolicyService::AudioCommandThread::stopOutputCommand(audio_port_handle_t portId)
 {
     sp<AudioCommand> command = new AudioCommand();
@@ -1707,6 +1735,14 @@
     return (int)mAudioCommandThread->voiceVolumeCommand(volume, delayMs);
 }
 
+void AudioPolicyService::setEffectSuspended(int effectId,
+                                            audio_session_t sessionId,
+                                            bool suspended)
+{
+    mAudioCommandThread->setEffectSuspendedCommand(effectId, sessionId, suspended);
+}
+
+
 extern "C" {
 audio_module_handle_t aps_load_hw_module(void *service __unused,
                                              const char *name);
diff --git a/services/audiopolicy/service/AudioPolicyService.h b/services/audiopolicy/service/AudioPolicyService.h
index 189322f..6c19912 100644
--- a/services/audiopolicy/service/AudioPolicyService.h
+++ b/services/audiopolicy/service/AudioPolicyService.h
@@ -134,6 +134,7 @@
                                     int id);
     virtual status_t unregisterEffect(int id);
     virtual status_t setEffectEnabled(int id, bool enabled);
+    status_t moveEffectsToIo(const std::vector<int>& ids, audio_io_handle_t io) override;
     virtual bool isStreamActive(audio_stream_type_t stream, uint32_t inPastMs = 0) const;
     virtual bool isStreamActiveRemotely(audio_stream_type_t stream, uint32_t inPastMs = 0) const;
     virtual bool isSourceActive(audio_source_t source) const;
@@ -292,6 +293,9 @@
 
             void onAudioVolumeGroupChanged(volume_group_t group, int flags);
             void doOnAudioVolumeGroupChanged(volume_group_t group, int flags);
+            void setEffectSuspended(int effectId,
+                                    audio_session_t sessionId,
+                                    bool suspended);
 
 private:
                         AudioPolicyService() ANDROID_API;
@@ -426,7 +430,8 @@
             CHANGED_AUDIOVOLUMEGROUP,
             SET_AUDIOPORT_CONFIG,
             DYN_POLICY_MIX_STATE_UPDATE,
-            RECORDING_CONFIGURATION_UPDATE
+            RECORDING_CONFIGURATION_UPDATE,
+            SET_EFFECT_SUSPENDED,
         };
 
         AudioCommandThread (String8 name, const wp<AudioPolicyService>& service);
@@ -469,6 +474,9 @@
                                                     std::vector<effect_descriptor_t> effects,
                                                     audio_patch_handle_t patchHandle,
                                                     audio_source_t source);
+                    void        setEffectSuspendedCommand(int effectId,
+                                                          audio_session_t sessionId,
+                                                          bool suspended);
                     void        insertCommand_l(AudioCommand *command, int delayMs = 0);
     private:
         class AudioCommandData;
@@ -566,6 +574,13 @@
             audio_source_t mSource;
         };
 
+        class SetEffectSuspendedData : public AudioCommandData {
+        public:
+            int mEffectId;
+            audio_session_t mSessionId;
+            bool mSuspended;
+        };
+
         Mutex   mLock;
         Condition mWaitWorkCV;
         Vector < sp<AudioCommand> > mAudioCommands; // list of pending commands
@@ -651,6 +666,10 @@
                                          audio_io_handle_t srcOutput,
                                          audio_io_handle_t dstOutput);
 
+                void setEffectSuspended(int effectId,
+                                        audio_session_t sessionId,
+                                        bool suspended) override;
+
         /* Create a patch between several source and sink ports */
         virtual status_t createAudioPatch(const struct audio_patch *patch,
                                            audio_patch_handle_t *handle,
@@ -810,7 +829,6 @@
 
     mutable Mutex mLock;    // prevents concurrent access to AudioPolicy manager functions changing
                             // device connection state  or routing
-    mutable Mutex mEffectsLock; // serialize access to Effect state within APM.
     // Note: lock acquisition order is always mLock > mEffectsLock:
     // mLock protects AudioPolicyManager methods that can call into audio flinger
     // and possibly back in to audio policy service and acquire mEffectsLock.
@@ -824,6 +842,8 @@
     DefaultKeyedVector< int64_t, sp<NotificationClient> >    mNotificationClients;
     Mutex mNotificationClientsLock;  // protects mNotificationClients
     // Manage all effects configured in audio_effects.conf
+    // never hold AudioPolicyService::mLock when calling AudioPolicyEffects methods as
+    // those can call back into AudioPolicyService methods and try to acquire the mutex
     sp<AudioPolicyEffects> mAudioPolicyEffects;
     audio_mode_t mPhoneState;
 
diff --git a/services/audiopolicy/tests/AudioPolicyTestClient.h b/services/audiopolicy/tests/AudioPolicyTestClient.h
index 8854eb2..e4c64e5 100644
--- a/services/audiopolicy/tests/AudioPolicyTestClient.h
+++ b/services/audiopolicy/tests/AudioPolicyTestClient.h
@@ -84,6 +84,9 @@
                                         std::vector<effect_descriptor_t> effects __unused,
                                         audio_patch_handle_t patchHandle __unused,
                                         audio_source_t source __unused) override { }
+    void setEffectSuspended(int effectId __unused,
+                            audio_session_t sessionId __unused,
+                            bool suspended __unused) {}
 };
 
 } // namespace android
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index cca4049..a1cb8ee 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -973,11 +973,14 @@
 
     // Make sure the UID is in an active state to use the camera
     if (!mUidPolicy->isUidActive(callingUid, String16(clientName8))) {
+        int32_t procState = mUidPolicy->getProcState(callingUid);
         ALOGE("Access Denial: can't use the camera from an idle UID pid=%d, uid=%d",
             clientPid, clientUid);
         return STATUS_ERROR_FMT(ERROR_DISABLED,
-                "Caller \"%s\" (PID %d, UID %d) cannot open camera \"%s\" from background",
-                clientName8.string(), clientUid, clientPid, cameraId.string());
+                "Caller \"%s\" (PID %d, UID %d) cannot open camera \"%s\" from background ("
+                "calling UID %d proc state %" PRId32 ")",
+                clientName8.string(), clientUid, clientPid, cameraId.string(),
+                callingUid, procState);
     }
 
     // If sensor privacy is enabled then prevent access to the camera
@@ -2736,6 +2739,19 @@
     return active;
 }
 
+int32_t CameraService::UidPolicy::getProcState(uid_t uid) {
+    Mutex::Autolock _l(mUidLock);
+    return getProcStateLocked(uid);
+}
+
+int32_t CameraService::UidPolicy::getProcStateLocked(uid_t uid) {
+    int32_t procState = ActivityManager::PROCESS_STATE_UNKNOWN;
+    if (mMonitoredUids.find(uid) != mMonitoredUids.end()) {
+        procState = mMonitoredUids[uid].first;
+    }
+    return procState;
+}
+
 void CameraService::UidPolicy::UidPolicy::addOverrideUid(uid_t uid,
         String16 callingPackage, bool active) {
     updateOverrideUid(uid, callingPackage, active, true);
diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h
index 4bcdeb2..a8c2606 100644
--- a/services/camera/libcameraservice/CameraService.h
+++ b/services/camera/libcameraservice/CameraService.h
@@ -542,6 +542,7 @@
         void unregisterSelf();
 
         bool isUidActive(uid_t uid, String16 callingPackage);
+        int32_t getProcState(uid_t uid);
 
         void onUidGone(uid_t uid, bool disabled);
         void onUidActive(uid_t uid);
@@ -558,6 +559,7 @@
         virtual void binderDied(const wp<IBinder> &who);
     private:
         bool isUidActiveLocked(uid_t uid, String16 callingPackage);
+        int32_t getProcStateLocked(uid_t uid);
         void updateOverrideUid(uid_t uid, String16 callingPackage, bool active, bool insert);
 
         Mutex mUidLock;
diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp
index a0d0198..415b2d8 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Device.cpp
@@ -132,13 +132,24 @@
     bool isLogical = manager->isLogicalCamera(mId.string(), &physicalCameraIds);
     if (isLogical) {
         for (auto& physicalId : physicalCameraIds) {
-            res = manager->getCameraCharacteristics(physicalId, &mPhysicalDeviceInfoMap[physicalId]);
+            res = manager->getCameraCharacteristics(
+                    physicalId, &mPhysicalDeviceInfoMap[physicalId]);
             if (res != OK) {
                 SET_ERR_L("Could not retrieve camera %s characteristics: %s (%d)",
                         physicalId.c_str(), strerror(-res), res);
                 session->close();
                 return res;
             }
+
+            if (DistortionMapper::isDistortionSupported(mPhysicalDeviceInfoMap[physicalId])) {
+                mDistortionMappers[physicalId].setupStaticInfo(mPhysicalDeviceInfoMap[physicalId]);
+                if (res != OK) {
+                    SET_ERR_L("Unable to read camera %s's calibration fields for distortion "
+                            "correction", physicalId.c_str());
+                    session->close();
+                    return res;
+                }
+            }
         }
     }
 
@@ -308,7 +319,7 @@
     }
 
     if (DistortionMapper::isDistortionSupported(mDeviceInfo)) {
-        res = mDistortionMapper.setupStaticInfo(mDeviceInfo);
+        res = mDistortionMappers[mId.c_str()].setupStaticInfo(mDeviceInfo);
         if (res != OK) {
             SET_ERR_L("Unable to read necessary calibration fields for distortion correction");
             return res;
@@ -3503,12 +3514,27 @@
     }
 
     // Fix up some result metadata to account for HAL-level distortion correction
-    status_t res = mDistortionMapper.correctCaptureResult(&captureResult.mMetadata);
+    status_t res =
+            mDistortionMappers[mId.c_str()].correctCaptureResult(&captureResult.mMetadata);
     if (res != OK) {
         SET_ERR("Unable to correct capture result metadata for frame %d: %s (%d)",
                 frameNumber, strerror(res), res);
         return;
     }
+    for (auto& physicalMetadata : captureResult.mPhysicalMetadatas) {
+        String8 cameraId8(physicalMetadata.mPhysicalCameraId);
+        if (mDistortionMappers.find(cameraId8.c_str()) == mDistortionMappers.end()) {
+            continue;
+        }
+        res = mDistortionMappers[cameraId8.c_str()].correctCaptureResult(
+                &physicalMetadata.mPhysicalCameraMetadata);
+        if (res != OK) {
+            SET_ERR("Unable to correct physical capture result metadata for frame %d: %s (%d)",
+                    frameNumber, strerror(res), res);
+            return;
+        }
+    }
+
     // Fix up result metadata for monochrome camera.
     res = fixupMonochromeTags(mDeviceInfo, captureResult.mMetadata);
     if (res != OK) {
@@ -5482,13 +5508,21 @@
                 // Correct metadata regions for distortion correction if enabled
                 sp<Camera3Device> parent = mParent.promote();
                 if (parent != nullptr) {
-                    res = parent->mDistortionMapper.correctCaptureRequest(
-                        &(captureRequest->mSettingsList.begin()->metadata));
-                    if (res != OK) {
-                        SET_ERR("RequestThread: Unable to correct capture requests "
-                                "for lens distortion for request %d: %s (%d)",
-                                halRequest->frame_number, strerror(-res), res);
-                        return INVALID_OPERATION;
+                    List<PhysicalCameraSettings>::iterator it;
+                    for (it = captureRequest->mSettingsList.begin();
+                            it != captureRequest->mSettingsList.end(); it++) {
+                        if (parent->mDistortionMappers.find(it->cameraId) ==
+                                parent->mDistortionMappers.end()) {
+                            continue;
+                        }
+                        res = parent->mDistortionMappers[it->cameraId].correctCaptureRequest(
+                            &(it->metadata));
+                        if (res != OK) {
+                            SET_ERR("RequestThread: Unable to correct capture requests "
+                                    "for lens distortion for request %d: %s (%d)",
+                                    halRequest->frame_number, strerror(-res), res);
+                            return INVALID_OPERATION;
+                        }
                     }
                 }
             }
diff --git a/services/camera/libcameraservice/device3/Camera3Device.h b/services/camera/libcameraservice/device3/Camera3Device.h
index d3bb212..f8245df 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.h
+++ b/services/camera/libcameraservice/device3/Camera3Device.h
@@ -1250,8 +1250,10 @@
     /**
      * Distortion correction support
      */
-
-    camera3::DistortionMapper mDistortionMapper;
+    // Map from camera IDs to its corresponding distortion mapper. Only contains
+    // 1 ID if the device isn't a logical multi-camera. Otherwise contains both
+    // logical camera and its physical subcameras.
+    std::unordered_map<std::string, camera3::DistortionMapper> mDistortionMappers;
 
     // Debug tracker for metadata tag value changes
     // - Enabled with the -m <taglist> option to dumpsys, such as
diff --git a/services/camera/libcameraservice/device3/Camera3OutputStream.cpp b/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
index 1c77581..acb8b3c 100644
--- a/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
@@ -491,8 +491,11 @@
      * sets the mBufferManager if device version is > HAL3.2, which guarantees that the buffer
      * manager setup is skipped in below code. Note that HAL3.2 is also excluded here, as some
      * HAL3.2 devices may not support the dynamic buffer registeration.
+     * Also Camera3BufferManager does not support display/texture streams as they have its own
+     * buffer management logic.
      */
-    if (mBufferManager != 0 && mSetId > CAMERA3_STREAM_SET_ID_INVALID) {
+    if (mBufferManager != 0 && mSetId > CAMERA3_STREAM_SET_ID_INVALID &&
+            !(isConsumedByHWComposer() || isConsumedByHWTexture())) {
         uint64_t consumerUsage = 0;
         getEndpointUsage(&consumerUsage);
         StreamInfo streamInfo(
diff --git a/services/mediacodec/main_swcodecservice.cpp b/services/mediacodec/main_swcodecservice.cpp
index a5db031..d91b788 100644
--- a/services/mediacodec/main_swcodecservice.cpp
+++ b/services/mediacodec/main_swcodecservice.cpp
@@ -33,11 +33,12 @@
 
 extern "C" void RegisterCodecServices();
 
-int main(int argc __unused, char** /*argv*/)
+int main(int argc __unused, char** argv)
 {
     LOG(INFO) << "media swcodec service starting";
     signal(SIGPIPE, SIG_IGN);
     SetUpMinijail(kSystemSeccompPolicyPath, kVendorSeccompPolicyPath);
+    strcpy(argv[0], "media.swcodec");
 
     ::android::hardware::configureRpcThreadpool(64, false);
 
diff --git a/services/oboeservice/AAudioClientTracker.cpp b/services/oboeservice/AAudioClientTracker.cpp
index 7264a9b..83704ba 100644
--- a/services/oboeservice/AAudioClientTracker.cpp
+++ b/services/oboeservice/AAudioClientTracker.cpp
@@ -101,7 +101,7 @@
 aaudio_result_t
 AAudioClientTracker::registerClientStream(pid_t pid, sp<AAudioServiceStreamBase> serviceStream) {
     aaudio_result_t result = AAUDIO_OK;
-    ALOGV("registerClientStream(%d, %p)\n", pid, serviceStream.get());
+    ALOGV("registerClientStream(%d,)\n", pid);
     std::lock_guard<std::mutex> lock(mLock);
     sp<NotificationClient> notificationClient = mNotificationClients[pid];
     if (notificationClient == 0) {
@@ -118,27 +118,23 @@
 aaudio_result_t
 AAudioClientTracker::unregisterClientStream(pid_t pid,
                                             sp<AAudioServiceStreamBase> serviceStream) {
-    ALOGV("unregisterClientStream(%d, %p)\n", pid, serviceStream.get());
+    ALOGV("unregisterClientStream(%d,)\n", pid);
     std::lock_guard<std::mutex> lock(mLock);
     auto it = mNotificationClients.find(pid);
     if (it != mNotificationClients.end()) {
-        ALOGV("unregisterClientStream(%d, %p) found NotificationClient\n",
-              pid, serviceStream.get());
+        ALOGV("unregisterClientStream(%d,) found NotificationClient\n", pid);
         it->second->unregisterClientStream(serviceStream);
     } else {
-        ALOGE("unregisterClientStream(%d, %p) missing NotificationClient\n",
-              pid, serviceStream.get());
+        ALOGE("unregisterClientStream(%d,) missing NotificationClient\n", pid);
     }
     return AAUDIO_OK;
 }
 
 AAudioClientTracker::NotificationClient::NotificationClient(pid_t pid)
         : mProcessId(pid) {
-    //ALOGD("NotificationClient(%d) created %p\n", pid, this);
 }
 
 AAudioClientTracker::NotificationClient::~NotificationClient() {
-    //ALOGD("~NotificationClient() destroyed %p\n", this);
 }
 
 int32_t AAudioClientTracker::NotificationClient::getStreamCount() {
diff --git a/services/oboeservice/AAudioService.cpp b/services/oboeservice/AAudioService.cpp
index 2fbaeb4..e6a8375 100644
--- a/services/oboeservice/AAudioService.cpp
+++ b/services/oboeservice/AAudioService.cpp
@@ -132,11 +132,10 @@
 
     if (result != AAUDIO_OK) {
         serviceStream.clear();
-        ALOGW("openStream(): failed, return %d = %s", result, AAudio_convertResultToText(result));
         return result;
     } else {
         aaudio_handle_t handle = mStreamTracker.addStreamForHandle(serviceStream.get());
-        ALOGD("openStream(): handle = 0x%08X", handle);
+        ALOGV("openStream(): handle = 0x%08X", handle);
         serviceStream->setHandle(handle);
         pid_t pid = request.getProcessId();
         AAudioClientTracker::getInstance().registerClientStream(pid, serviceStream);
diff --git a/services/oboeservice/AAudioServiceEndpoint.cpp b/services/oboeservice/AAudioServiceEndpoint.cpp
index 4dfb62a..553754e 100644
--- a/services/oboeservice/AAudioServiceEndpoint.cpp
+++ b/services/oboeservice/AAudioServiceEndpoint.cpp
@@ -90,7 +90,8 @@
     std::lock_guard<std::mutex> lock(mLockStreams);
     mConnected.store(false);
     for (const auto& stream : mRegisteredStreams) {
-        ALOGD("disconnectRegisteredStreams() stop and disconnect %p", stream.get());
+        ALOGD("disconnectRegisteredStreams() stop and disconnect port %d",
+              stream->getPortHandle());
         stream->stop();
         stream->disconnect();
     }
diff --git a/services/oboeservice/AAudioServiceEndpoint.h b/services/oboeservice/AAudioServiceEndpoint.h
index 3616fa2..a2f66a5 100644
--- a/services/oboeservice/AAudioServiceEndpoint.h
+++ b/services/oboeservice/AAudioServiceEndpoint.h
@@ -61,7 +61,7 @@
 
     virtual aaudio_result_t startClient(const android::AudioClient& client,
                                         audio_port_handle_t *clientHandle) {
-        ALOGD("AAudioServiceEndpoint::startClient(%p, ...) AAUDIO_ERROR_UNAVAILABLE", &client);
+        ALOGD("AAudioServiceEndpoint::startClient(...) AAUDIO_ERROR_UNAVAILABLE");
         return AAUDIO_ERROR_UNAVAILABLE;
     }
 
diff --git a/services/oboeservice/AAudioServiceEndpointMMAP.cpp b/services/oboeservice/AAudioServiceEndpointMMAP.cpp
index fbf7d10..447f32c 100644
--- a/services/oboeservice/AAudioServiceEndpointMMAP.cpp
+++ b/services/oboeservice/AAudioServiceEndpointMMAP.cpp
@@ -163,7 +163,9 @@
     ALOGD("%s() mMapClient.uid = %d, pid = %d => portHandle = %d\n",
           __func__, mMmapClient.clientUid,  mMmapClient.clientPid, mPortHandle);
     if (status != OK) {
-        ALOGE("%s() - openMmapStream() returned status %d",  __func__, status);
+        // This can happen if the resource is busy or the config does
+        // not match the hardware.
+        ALOGD("%s() - openMmapStream() returned status %d",  __func__, status);
         return AAUDIO_ERROR_UNAVAILABLE;
     }
 
@@ -196,9 +198,9 @@
         result = AAUDIO_ERROR_UNAVAILABLE;
         goto error;
     } else {
-        ALOGD("%s() createMmapBuffer() returned = %d, buffer_size = %d, burst_size %d"
+        ALOGD("%s() createMmapBuffer() buffer_size = %d fr, burst_size %d fr"
                       ", Sharable FD: %s",
-              __func__, status,
+              __func__,
               mMmapBufferinfo.buffer_size_frames,
               mMmapBufferinfo.burst_size_frames,
               isBufferShareable ? "Yes" : "No");
@@ -243,14 +245,13 @@
         burstMicros = mFramesPerBurst * static_cast<int64_t>(1000000) / getSampleRate();
     } while (burstMicros < burstMinMicros);
 
-    ALOGD("%s() original burst = %d, minMicros = %d, to burst = %d\n",
+    ALOGD("%s() original burst = %d, minMicros = %d => burst = %d\n",
           __func__, mMmapBufferinfo.burst_size_frames, burstMinMicros, mFramesPerBurst);
 
-    ALOGD("%s() actual rate = %d, channels = %d"
-          ", deviceId = %d, capacity = %d\n",
-          __func__, getSampleRate(), getSamplesPerFrame(), deviceId, getBufferCapacity());
+    ALOGD("%s() actual rate = %d, channels = %d, deviceId = %d\n",
+          __func__, getSampleRate(), getSamplesPerFrame(), deviceId);
 
-    ALOGD("%s() format = =x%08x, frame size = %d",
+    ALOGD("%s() format = 0x%08x, frame size = %d",
           __func__, getFormat(), calculateBytesPerFrame());
 
     return result;
@@ -262,7 +263,6 @@
 
 aaudio_result_t AAudioServiceEndpointMMAP::close() {
     if (mMmapStream != 0) {
-        ALOGD("%s() clear() endpoint", __func__);
         // Needs to be explicitly cleared or CTS will fail but it is not clear why.
         mMmapStream.clear();
         // Apparently the above close is asynchronous. An attempt to open a new device
@@ -284,7 +284,7 @@
     LOG_ALWAYS_FATAL_IF(tempHandle != mPortHandle,
                         "%s() port handle not expected to change from %d to %d",
                         __func__, mPortHandle, tempHandle);
-    ALOGV("%s(%p) mPortHandle = %d", __func__, stream.get(), mPortHandle);
+    ALOGV("%s() mPortHandle = %d", __func__, mPortHandle);
     return result;
 }
 
@@ -299,26 +299,20 @@
     mFramesTransferred.roundUp64(getBufferCapacity());
 
     // Use the port handle that was provided by openMmapStream().
-    ALOGV("%s(%p) mPortHandle = %d", __func__, stream.get(), mPortHandle);
+    ALOGV("%s() mPortHandle = %d", __func__, mPortHandle);
     return stopClient(mPortHandle);
 }
 
 aaudio_result_t AAudioServiceEndpointMMAP::startClient(const android::AudioClient& client,
                                                        audio_port_handle_t *clientHandle) {
     if (mMmapStream == nullptr) return AAUDIO_ERROR_NULL;
-    ALOGD("%s(%p(uid=%d, pid=%d))", __func__, &client, client.clientUid, client.clientPid);
-    audio_port_handle_t originalHandle =  *clientHandle;
     status_t status = mMmapStream->start(client, clientHandle);
-    aaudio_result_t result = AAudioConvert_androidToAAudioResult(status);
-    ALOGD("%s() , portHandle %d => %d, returns %d", __func__, originalHandle, *clientHandle, result);
-    return result;
+    return AAudioConvert_androidToAAudioResult(status);
 }
 
 aaudio_result_t AAudioServiceEndpointMMAP::stopClient(audio_port_handle_t clientHandle) {
-    ALOGD("%s(portHandle = %d), called", __func__, clientHandle);
     if (mMmapStream == nullptr) return AAUDIO_ERROR_NULL;
     aaudio_result_t result = AAudioConvert_androidToAAudioResult(mMmapStream->stop(clientHandle));
-    ALOGD("%s(portHandle = %d), returns %d", __func__, clientHandle, result);
     return result;
 }
 
@@ -371,7 +365,7 @@
     // TODO Do we really need a different volume for each channel?
     // We get called with an array filled with a single value!
     float volume = values[0];
-    ALOGD("%s(%p) volume[0] = %f", __func__, this, volume);
+    ALOGD("%s() volume[0] = %f", __func__, volume);
     std::lock_guard<std::mutex> lock(mLockStreams);
     for(const auto& stream : mRegisteredStreams) {
         stream->onVolumeChanged(volume);
@@ -379,7 +373,7 @@
 };
 
 void AAudioServiceEndpointMMAP::onRoutingChanged(audio_port_handle_t deviceId) {
-    ALOGD("%s(%p) called with dev %d, old = %d", __func__, this, deviceId, getDeviceId());
+    ALOGD("%s() called with dev %d, old = %d", __func__, deviceId, getDeviceId());
     if (getDeviceId() != AUDIO_PORT_HANDLE_NONE  && getDeviceId() != deviceId) {
         disconnectRegisteredStreams();
     }
diff --git a/services/oboeservice/AAudioServiceEndpointPlay.cpp b/services/oboeservice/AAudioServiceEndpointPlay.cpp
index 1e1c552..bda4b90 100644
--- a/services/oboeservice/AAudioServiceEndpointPlay.cpp
+++ b/services/oboeservice/AAudioServiceEndpointPlay.cpp
@@ -43,7 +43,6 @@
 
 AAudioServiceEndpointPlay::AAudioServiceEndpointPlay(AAudioService &audioService)
         : mStreamInternalPlay(audioService, true) {
-    ALOGD("%s(%p) created", __func__, this);
     mStreamInternal = &mStreamInternalPlay;
 }
 
diff --git a/services/oboeservice/AAudioServiceStreamShared.cpp b/services/oboeservice/AAudioServiceStreamShared.cpp
index 14742dd..2ca847a 100644
--- a/services/oboeservice/AAudioServiceStreamShared.cpp
+++ b/services/oboeservice/AAudioServiceStreamShared.cpp
@@ -111,7 +111,7 @@
               capacityInFrames, MAX_FRAMES_PER_BUFFER);
         return AAUDIO_ERROR_OUT_OF_RANGE;
     }
-    ALOGD("calculateBufferCapacity() requested %d frames, actual = %d",
+    ALOGV("calculateBufferCapacity() requested %d frames, actual = %d",
           requestedCapacityFrames, capacityInFrames);
     return capacityInFrames;
 }
@@ -144,7 +144,7 @@
     if (getFormat() == AUDIO_FORMAT_DEFAULT) {
         setFormat(AUDIO_FORMAT_PCM_FLOAT);
     } else if (getFormat() != AUDIO_FORMAT_PCM_FLOAT) {
-        ALOGE("%s() audio_format_t mAudioFormat = %d, need FLOAT", __func__, getFormat());
+        ALOGD("%s() audio_format_t mAudioFormat = %d, need FLOAT", __func__, getFormat());
         result = AAUDIO_ERROR_INVALID_FORMAT;
         goto error;
     }
@@ -153,7 +153,7 @@
     if (getSampleRate() == AAUDIO_UNSPECIFIED) {
         setSampleRate(endpoint->getSampleRate());
     } else if (getSampleRate() != endpoint->getSampleRate()) {
-        ALOGE("%s() mSampleRate = %d, need %d",
+        ALOGD("%s() mSampleRate = %d, need %d",
               __func__, getSampleRate(), endpoint->getSampleRate());
         result = AAUDIO_ERROR_INVALID_RATE;
         goto error;
@@ -163,7 +163,7 @@
     if (getSamplesPerFrame() == AAUDIO_UNSPECIFIED) {
         setSamplesPerFrame(endpoint->getSamplesPerFrame());
     } else if (getSamplesPerFrame() != endpoint->getSamplesPerFrame()) {
-        ALOGE("%s() mSamplesPerFrame = %d, need %d",
+        ALOGD("%s() mSamplesPerFrame = %d, need %d",
               __func__, getSamplesPerFrame(), endpoint->getSamplesPerFrame());
         result = AAUDIO_ERROR_OUT_OF_RANGE;
         goto error;
@@ -190,9 +190,6 @@
         }
     }
 
-    ALOGD("%s() actual rate = %d, channels = %d, deviceId = %d",
-          __func__, getSampleRate(), getSamplesPerFrame(), endpoint->getDeviceId());
-
     result = endpoint->registerStream(keep);
     if (result != AAUDIO_OK) {
         goto error;
@@ -227,7 +224,7 @@
 {
     std::lock_guard<std::mutex> lock(mAudioDataQueueLock);
     if (mAudioDataQueue == nullptr) {
-        ALOGE("%s(): mUpMessageQueue null! - stream not open", __func__);
+        ALOGW("%s(): mUpMessageQueue null! - stream not open", __func__);
         return AAUDIO_ERROR_NULL;
     }
     // Gather information on the data queue.
@@ -262,7 +259,7 @@
     int64_t position = 0;
     sp<AAudioServiceEndpoint> endpoint = mServiceEndpointWeak.promote();
     if (endpoint == nullptr) {
-        ALOGE("%s() has no endpoint", __func__);
+        ALOGW("%s() has no endpoint", __func__);
         return AAUDIO_ERROR_INVALID_STATE;
     }