Merge "policy_hal: fix CTS concurrent audio playback"
diff --git a/policy_hal/AudioPolicyManager.cpp b/policy_hal/AudioPolicyManager.cpp
index 26064c9..8e0d401 100644
--- a/policy_hal/AudioPolicyManager.cpp
+++ b/policy_hal/AudioPolicyManager.cpp
@@ -331,8 +331,6 @@
 
     // handle input devices
     if (audio_is_input_device(deviceType)) {
-        SortedVector <audio_io_handle_t> inputs;
-
         ssize_t index = mAvailableInputDevices.indexOf(device);
         switch (state)
         {
@@ -353,7 +351,7 @@
             // parameters on newly connected devices (instead of opening the inputs...)
             broadcastDeviceConnectionState(device, state);
 
-            if (checkInputsForDevice(device, state, inputs) != NO_ERROR) {
+            if (checkInputsForDevice(device, state) != NO_ERROR) {
                 broadcastDeviceConnectionState(device, AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE);
 
                 mHwModules.cleanUpForDevice(device);
@@ -382,7 +380,7 @@
             // Set Disconnect to HALs
             broadcastDeviceConnectionState(device, state);
 
-            checkInputsForDevice(device, state, inputs);
+            checkInputsForDevice(device, state);
             mAvailableInputDevices.remove(device);
 
         } break;
@@ -395,7 +393,7 @@
         // Propagate device availability to Engine
         setEngineDeviceConnectionState(device, state);
 
-        closeAllInputs();
+        checkCloseInputs();
         /*audio policy: fix call volume over USB*/
         // As the input device list can impact the output device selection, update
         // getDeviceForStrategy() cache
@@ -1745,82 +1743,80 @@
             goto non_direct_output;
         }
 
-        if ((*flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) == 0 || output != AUDIO_IO_HANDLE_NONE) {
-            sp<SwAudioOutputDescriptor> outputDesc = NULL;
-            // if multiple concurrent offload decode is supported
-            // do no check for reuse and also don't close previous output if its offload
-            // previous output will be closed during track destruction
-            if (!mApmConfigs->isAudioMultipleOffloadEnable() &&
-                    ((*flags & AUDIO_OUTPUT_FLAG_DIRECT) != 0)) {
-                for (size_t i = 0; i < mOutputs.size(); i++) {
-                    sp<SwAudioOutputDescriptor> desc = mOutputs.valueAt(i);
-                    if (!desc->isDuplicated() && (profile == desc->mProfile)) {
-                        outputDesc = desc;
-                        // reuse direct output if currently open by the same client
-                        // and configured with same parameters
-                        if ((config->sample_rate == desc->mSamplingRate) &&
-                            audio_formats_match(config->format, desc->mFormat) &&
-                            (channelMask == desc->mChannelMask) &&
-                            (session == desc->mDirectClientSession)) {
-                            desc->mDirectOpenCount++;
-                            ALOGV("getOutputForDevice() reusing direct output %d for session %d",
-                                mOutputs.keyAt(i), session);
-                            return mOutputs.keyAt(i);
-                        }
-                    }
-                    if (outputDesc != NULL) {
-                        if ((((*flags == AUDIO_OUTPUT_FLAG_DIRECT) && direct_pcm_already_in_use) ||
-                            ((*flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
-                             compress_offload_already_in_use)) &&
-                             session != outputDesc->mDirectClientSession) {
-                             ALOGV("getOutput() do not reuse direct pcm output because current client (%d) "
-                                   "is not the same as requesting client (%d) for different output conf",
-                             outputDesc->mDirectClientSession, session);
-                             goto non_direct_output;
-                        }
-                        closeOutput(outputDesc->mIoHandle);
+        sp<SwAudioOutputDescriptor> outputDesc = NULL;
+        // if multiple concurrent offload decode is supported
+        // do no check for reuse and also don't close previous output if its offload
+        // previous output will be closed during track destruction
+        if (!mApmConfigs->isAudioMultipleOffloadEnable() &&
+                ((*flags & AUDIO_OUTPUT_FLAG_DIRECT) != 0)) {
+            for (size_t i = 0; i < mOutputs.size(); i++) {
+                sp<SwAudioOutputDescriptor> desc = mOutputs.valueAt(i);
+                if (!desc->isDuplicated() && (profile == desc->mProfile)) {
+                    outputDesc = desc;
+                    // reuse direct output if currently open by the same client
+                    // and configured with same parameters
+                    if ((config->sample_rate == desc->mSamplingRate) &&
+                        audio_formats_match(config->format, desc->mFormat) &&
+                        (channelMask == desc->mChannelMask) &&
+                        (session == desc->mDirectClientSession)) {
+                        desc->mDirectOpenCount++;
+                        ALOGV("getOutputForDevice() reusing direct output %d for session %d",
+                            mOutputs.keyAt(i), session);
+                        return mOutputs.keyAt(i);
                     }
                 }
-                if (!profile->canOpenNewIo()) {
-                    goto non_direct_output;
+            }
+            if (outputDesc != NULL) {
+                if ((((*flags == AUDIO_OUTPUT_FLAG_DIRECT) && direct_pcm_already_in_use) ||
+                    ((*flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
+                     compress_offload_already_in_use)) &&
+                     session != outputDesc->mDirectClientSession) {
+                     ALOGV("getOutput() do not reuse direct pcm output because current client (%d) "
+                           "is not the same as requesting client (%d) for different output conf",
+                     outputDesc->mDirectClientSession, session);
+                     goto non_direct_output;
                 }
-
-                outputDesc =
-                        new SwAudioOutputDescriptor(profile, mpClientInterface);
-                DeviceVector outputDevices = mAvailableOutputDevices.getDevicesFromTypeMask(devices.types());
-                String8 address = outputDevices.size() > 0 ? outputDevices.itemAt(0)->address()
-                        : String8("");
-                status = outputDesc->open(config, devices, stream, *flags, &output);
-
-                // only accept an output with the requested parameters
-                if (status != NO_ERROR ||
-                    (config->sample_rate != 0 && config->sample_rate != outputDesc->mSamplingRate) ||
-                    (config->format != AUDIO_FORMAT_DEFAULT &&
-                             !audio_formats_match(config->format, outputDesc->mFormat)) ||
-                    (channelMask != 0 && channelMask != outputDesc->mChannelMask)) {
-                    ALOGV("getOutputForDevice() failed opening direct output: output %d sample rate %d %d,"
-                            "format %d %d, channel mask %04x %04x", output, config->sample_rate,
-                            outputDesc->mSamplingRate, config->format, outputDesc->mFormat,
-                            channelMask, outputDesc->mChannelMask);
-                    if (output != AUDIO_IO_HANDLE_NONE) {
-                        outputDesc->close();
-                    }
-                    // fall back to mixer output if possible when the direct output could not be open
-                    if (audio_is_linear_pcm(config->format) && config->sample_rate <= SAMPLE_RATE_HZ_MAX) {
-                        goto non_direct_output;
-                    }
-                    return AUDIO_IO_HANDLE_NONE;
-                }
-                outputDesc->mDirectOpenCount = 1;
-                outputDesc->mDirectClientSession = session;
-
-                addOutput(output, outputDesc);
-                mPreviousOutputs = mOutputs;
-                ALOGV("getOutputForDevice() returns new direct output %d", output);
-                mpClientInterface->onAudioPortListUpdate();
-                return output;
+                closeOutput(outputDesc->mIoHandle);
             }
         }
+        if (!profile->canOpenNewIo()) {
+            goto non_direct_output;
+        }
+
+        outputDesc =
+                new SwAudioOutputDescriptor(profile, mpClientInterface);
+        DeviceVector outputDevices = mAvailableOutputDevices.getDevicesFromTypeMask(devices.types());
+        String8 address = outputDevices.size() > 0 ? outputDevices.itemAt(0)->address()
+                : String8("");
+        status = outputDesc->open(config, devices, stream, *flags, &output);
+
+        // only accept an output with the requested parameters
+        if (status != NO_ERROR ||
+            (config->sample_rate != 0 && config->sample_rate != outputDesc->mSamplingRate) ||
+            (config->format != AUDIO_FORMAT_DEFAULT &&
+                     !audio_formats_match(config->format, outputDesc->mFormat)) ||
+            (channelMask != 0 && channelMask != outputDesc->mChannelMask)) {
+            ALOGV("getOutputForDevice() failed opening direct output: output %d sample rate %d %d,"
+                    "format %d %d, channel mask %04x %04x", output, config->sample_rate,
+                    outputDesc->mSamplingRate, config->format, outputDesc->mFormat,
+                    channelMask, outputDesc->mChannelMask);
+            if (output != AUDIO_IO_HANDLE_NONE) {
+                outputDesc->close();
+            }
+            // fall back to mixer output if possible when the direct output could not be open
+            if (audio_is_linear_pcm(config->format) && config->sample_rate <= SAMPLE_RATE_HZ_MAX) {
+                goto non_direct_output;
+            }
+            return AUDIO_IO_HANDLE_NONE;
+        }
+        outputDesc->mDirectOpenCount = 1;
+        outputDesc->mDirectClientSession = session;
+
+        addOutput(output, outputDesc);
+        mPreviousOutputs = mOutputs;
+        ALOGV("getOutputForDevice() returns new direct output %d", output);
+        mpClientInterface->onAudioPortListUpdate();
+        return output;
     }
 
 non_direct_output:
@@ -1867,6 +1863,7 @@
 
 status_t AudioPolicyManagerCustom::getInputForAttr(const audio_attributes_t *attr,
                                          audio_io_handle_t *input,
+                                         audio_unique_id_t riid,
                                          audio_session_t session,
                                          uid_t uid,
                                          const audio_config_base_t *config,
@@ -1932,6 +1929,7 @@
 
     return AudioPolicyManager::getInputForAttr(attr,
                                                input,
+                                               riid,
                                                session,
                                                uid,
                                                config,
@@ -1967,6 +1965,11 @@
 
     audio_io_handle_t input = inputDesc->mIoHandle;
     sp<RecordClientDescriptor> client = inputDesc->getClient(portId);
+    if (client == NULL) {
+        ALOGW("%s invalid client desc for %d", __FUNCTION__, portId);
+        return BAD_VALUE;
+    }
+
     if (client->active()) {
         ALOGW("%s input %d client %d already started", __FUNCTION__, input, client->portId());
         return INVALID_OPERATION;
diff --git a/policy_hal/AudioPolicyManager.h b/policy_hal/AudioPolicyManager.h
index 5a8a907..61f9821 100644
--- a/policy_hal/AudioPolicyManager.h
+++ b/policy_hal/AudioPolicyManager.h
@@ -96,6 +96,7 @@
 
         virtual status_t getInputForAttr(const audio_attributes_t *attr,
                                          audio_io_handle_t *input,
+                                         audio_unique_id_t riid,
                                          audio_session_t session,
                                          uid_t uid,
                                          const audio_config_base_t *config,