Merge "audio HAL: fix thread starvation"
diff --git a/hal/audio_hw.c b/hal/audio_hw.c
index de645bd..f969de2 100755
--- a/hal/audio_hw.c
+++ b/hal/audio_hw.c
@@ -1152,6 +1152,11 @@
 
 error_config:
     adev->active_input = NULL;
+    /*
+     * sleep 50ms to allow sufficient time for kernel
+     * drivers to recover incases like SSR.
+     */
+    usleep(50000);
     ALOGD("%s: exit: status(%d)", __func__, ret);
 
     return ret;
@@ -1689,6 +1694,11 @@
 error_open:
     stop_output_stream(out);
 error_config:
+    /*
+     * sleep 50ms to allow sufficient time for kernel
+     * drivers to recover incases like SSR.
+     */
+    usleep(50000);
     return ret;
 }
 
diff --git a/policy_hal/AudioPolicyManager.cpp b/policy_hal/AudioPolicyManager.cpp
index dfe379a..85a7393 100644
--- a/policy_hal/AudioPolicyManager.cpp
+++ b/policy_hal/AudioPolicyManager.cpp
@@ -954,6 +954,46 @@
 
 }
 
+status_t AudioPolicyManagerCustom::stopOutput(audio_io_handle_t output,
+                                            audio_stream_type_t stream,
+                                            audio_session_t session)
+{
+    ALOGV("stopOutput() output %d, stream %d, session %d", output, stream, session);
+    ssize_t index = mOutputs.indexOfKey(output);
+    if (index < 0) {
+        ALOGW("stopOutput() unknown output %d", output);
+        return BAD_VALUE;
+    }
+
+    sp<SwAudioOutputDescriptor> outputDesc = mOutputs.valueAt(index);
+
+    if (outputDesc->mRefCount[stream] == 1) {
+        // Automatically disable the remote submix input when output is stopped on a
+        // re routing mix of type MIX_TYPE_RECORDERS
+        if (audio_is_remote_submix_device(outputDesc->mDevice) &&
+                outputDesc->mPolicyMix != NULL &&
+                outputDesc->mPolicyMix->mMixType == MIX_TYPE_RECORDERS) {
+            setDeviceConnectionStateInt(AUDIO_DEVICE_IN_REMOTE_SUBMIX,
+                    AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE,
+                    outputDesc->mPolicyMix->mRegistrationId,
+                    "remote-submix");
+        }
+    }
+
+    // Routing?
+    bool forceDeviceUpdate = false;
+    if (outputDesc->mRefCount[stream] > 0) {
+        int activityCount = mOutputRoutes.decRouteActivity(session);
+        forceDeviceUpdate = (mOutputRoutes.hasRoute(session) && (activityCount == 0));
+
+        if (forceDeviceUpdate) {
+            checkStrategyRoute(getStrategy(stream), AUDIO_IO_HANDLE_NONE);
+        }
+    }
+
+    return stopSource(outputDesc, stream, forceDeviceUpdate);
+}
+
 status_t AudioPolicyManagerCustom::stopSource(sp<SwAudioOutputDescriptor> outputDesc,
                                             audio_stream_type_t stream,
                                             bool forceDeviceUpdate)
diff --git a/policy_hal/AudioPolicyManager.h b/policy_hal/AudioPolicyManager.h
index 66f9c38..69b2b1f 100644
--- a/policy_hal/AudioPolicyManager.h
+++ b/policy_hal/AudioPolicyManager.h
@@ -93,6 +93,9 @@
                                            bool fromCache);
         // returns true if given output is direct output
         bool isDirectOutput(audio_io_handle_t output);
+        status_t stopOutput(audio_io_handle_t output,
+                                    audio_stream_type_t stream,
+                                    audio_session_t session);
 
         // if argument "device" is different from AUDIO_DEVICE_NONE,  startSource() will force
         // the re-evaluation of the output device.