Merge "pal: move sco out device to the beginning of device disconnect list"
diff --git a/configs/crow/resourcemanager_crow_idp_wcd9395_aatc.xml b/configs/crow/resourcemanager_crow_idp_wcd9395_aatc.xml
index 459d534..4db17c2 100644
--- a/configs/crow/resourcemanager_crow_idp_wcd9395_aatc.xml
+++ b/configs/crow/resourcemanager_crow_idp_wcd9395_aatc.xml
@@ -561,10 +561,10 @@
             <id>PAL_DEVICE_IN_VI_FEEDBACK</id>
             <back_end_name>CODEC_DMA-LPAIF_WSA-TX-0</back_end_name>
             <max_channels>2</max_channels>
-            <channels>2</channels>
+            <channels>1</channels>
             <samplerate>48000</samplerate>
             <bit_width>32</bit_width>
-            <snd_device_name>vi-feedback</snd_device_name>
+            <snd_device_name>vi-feedback-mono-2</snd_device_name>
             <usecase>
                 <name>PAL_STREAM_VOICE_CALL</name>
                 <channels>1</channels>
@@ -575,10 +575,10 @@
             <id>PAL_DEVICE_IN_CPS_FEEDBACK</id>
             <back_end_name>CODEC_DMA-LPAIF_WSA-TX-2</back_end_name>
             <max_channels>2</max_channels>
-            <channels>2</channels>
+            <channels>1</channels>
             <samplerate>24000</samplerate>
             <bit_width>32</bit_width>
-            <snd_device_name>cps-feedback</snd_device_name>
+            <snd_device_name>cps-feedback-mono-2</snd_device_name>
             <usecase>
                 <name>PAL_STREAM_VOICE_CALL</name>
                 <channels>1</channels>
diff --git a/device/inc/USBAudio.h b/device/inc/USBAudio.h
index 4928838..c6d80cd 100644
--- a/device/inc/USBAudio.h
+++ b/device/inc/USBAudio.h
@@ -146,9 +146,9 @@
     int getMaxBitWidth(bool is_playback);
     int getMaxChannels(bool is_playback);
     unsigned int getFormatByBitWidth(int bitwidth);
-    unsigned int readSupportedFormat(bool is_playback, uint32_t *format);
-    unsigned int readSupportedSampleRate(bool is_playback, uint32_t *sample_rate);
-    unsigned int readSupportedChannelMask(bool is_playback, uint32_t *channel);
+    void readSupportedFormat(bool is_playback, uint32_t *format);
+    void readSupportedSampleRate(bool is_playback, uint32_t *sample_rate);
+    void readSupportedChannelMask(bool is_playback, uint32_t *channel);
     int readSupportedConfig(dynamic_media_config_t *config, bool is_playback, int usb_card);
     int readBestConfig(struct pal_media_config *config,
                                     struct pal_stream_attributes *sattr,
diff --git a/device/src/Bluetooth.cpp b/device/src/Bluetooth.cpp
index a448e47..1d2a2fa 100644
--- a/device/src/Bluetooth.cpp
+++ b/device/src/Bluetooth.cpp
@@ -1738,7 +1738,10 @@
 
     if (a2dpState != A2DP_STATE_STARTED && !totalActiveSessionRequests) {
         codecFormat = CODEC_TYPE_INVALID;
-        isAbrEnabled = false;
+
+        if (!isConfigured)
+            isAbrEnabled = false;
+
         PAL_DBG(LOG_TAG, "calling BT module stream start");
         /* This call indicates BT IPC lib to start playback */
         if (audio_source_start_api) {
diff --git a/device/src/Device.cpp b/device/src/Device.cpp
index 5a75d7c..076a8a5 100644
--- a/device/src/Device.cpp
+++ b/device/src/Device.cpp
@@ -493,6 +493,8 @@
            disableDevice(audioRoute, mSndDeviceName);
            mCurrentPriority = MIN_USECASE_PRIORITY;
            deviceStartStopCount = 0;
+           if(rm->num_proxy_channels != 0)
+               rm->num_proxy_channels = 0;
        }
     }
     PAL_INFO(LOG_TAG, "Exit. deviceCount %d for device id %d (%s), exit status %d", deviceCount,
diff --git a/device/src/USBAudio.cpp b/device/src/USBAudio.cpp
index 5c40793..718ceb6 100644
--- a/device/src/USBAudio.cpp
+++ b/device/src/USBAudio.cpp
@@ -686,7 +686,7 @@
     return default_format;
 }
 
-unsigned int USBCardConfig::readSupportedFormat(bool is_playback, uint32_t *format) {
+void USBCardConfig::readSupportedFormat(bool is_playback, uint32_t *format) {
     int i = 0;
     unsigned int bw;
     unsigned int bitWidth[MAX_SUPPORTED_FORMATS + 1];
@@ -729,11 +729,9 @@
     /* convert bw to format */
     for (int j = 0; j < i; j++)
         format[j] = getFormatByBitWidth(bitWidth[j]);
-
-    return 0;
 }
 
-unsigned int USBCardConfig::readSupportedSampleRate(bool is_playback, uint32_t *sample_rate) {
+void USBCardConfig::readSupportedSampleRate(bool is_playback, uint32_t *sample_rate) {
     usb_usecase_type_t type = is_playback ? USB_PLAYBACK : USB_CAPTURE;
 
     typename std::vector<std::shared_ptr<USBDeviceConfig>>::iterator iter;
@@ -760,50 +758,34 @@
 
     for (int j = 0; j < i; j++)
         PAL_DBG(LOG_TAG, "%s %d", is_playback ? "P" : "C", sample_rate[j]);
-
-    return 0;
 }
 
-unsigned int USBCardConfig::readSupportedChannelMask(bool is_playback, uint32_t *channel) {
+void USBCardConfig::readSupportedChannelMask(bool is_playback, uint32_t *channel) {
 
     int channels = getMaxChannels(is_playback);
     int channel_count;
-    uint32_t num_masks = 0;
 
     if (channels > MAX_HIFI_CHANNEL_COUNT)
         channels = MAX_HIFI_CHANNEL_COUNT;
-
+     /* need to calculate the mask from channel count either because this is
+      * the query case or the specified mask isn't valid for this device,
+      * or is more than the FW can handle
+      */
     if (is_playback) {
-        channel[num_masks++] = channels <= 2
+        channel[0] = channels <= 2
                      /* position mask for mono and stereo*/
                      ? audio_channel_out_mask_from_count(channels)
                      /* otherwise indexed */
                      : audio_channel_mask_for_index_assignment_from_count(channels);
-        // TODO: needs to figure out the accurate match of channel mask
     } else {
-        // For capture we report all supported channel masks from 1 channel up.
-        channel_count = MIN_CHANNEL_COUNT;
-        // audio_channel_in_mask_from_count() does the right conversion to either positional or
-        // indexed mask
-        for ( ; channel_count <= channels && num_masks < MAX_SUPPORTED_CHANNEL_MASKS; channel_count++) {
-            audio_channel_mask_t mask = AUDIO_CHANNEL_NONE;
-            if (channel_count <= 2) {
-                mask = audio_channel_in_mask_from_count(channel_count);
-                channel[num_masks++] = mask;
-            }
-            const audio_channel_mask_t index_mask =
-                    audio_channel_mask_for_index_assignment_from_count(channel_count);
-            if (mask != index_mask && num_masks < MAX_SUPPORTED_CHANNEL_MASKS) { // ensure index mask added.
-                channel[num_masks++] = index_mask;
-            }
-        }
+        channel[0] = channels <= 2
+             /* position mask for mono & stereo */
+             ? audio_channel_in_mask_from_count(channels)
+             /* otherwise indexed */
+             : audio_channel_mask_for_index_assignment_from_count(channels);
     }
-
-    for (size_t i = 0; i < num_masks; ++i) {
-        PAL_DBG(LOG_TAG, "%s supported ch %d channel[%zu] %08x num_masks %d",
-              is_playback ? "P" : "C", channels, i, channel[i], num_masks);
-    }
-    return num_masks;
+    PAL_DBG(LOG_TAG, "%s supported ch %d, channel mask: %08x ",
+            is_playback ? "P" : "C", channels, channel[0]);
 }
 
 bool USBCardConfig::readDefaultJackStatus(bool is_playback) {
diff --git a/resource_manager/src/ResourceManager.cpp b/resource_manager/src/ResourceManager.cpp
index 5cc7969..eac4624 100644
--- a/resource_manager/src/ResourceManager.cpp
+++ b/resource_manager/src/ResourceManager.cpp
@@ -2685,8 +2685,8 @@
             {
                 PAL_INFO(LOG_TAG, "wfd TX is not in progress");
                 if (rm->num_proxy_channels) {
+                    PAL_INFO(LOG_TAG, "proxy device channel number: %d", rm->num_proxy_channels);
                     deviceattr->config.ch_info.channels = rm->num_proxy_channels;
-                    rm->num_proxy_channels = 0;
                 }
             }
             PAL_INFO(LOG_TAG, "PAL_DEVICE_OUT_PROXY sample rate %d bitwidth %d ch:%d",
@@ -5001,7 +5001,7 @@
                 in_type != PAL_STREAM_CONTEXT_PROXY  &&
                 in_type != PAL_STREAM_VOICE_UI)) {
         *tx_conc = true;
-        if (!audio_capture_conc_enable) {
+        if (!audio_capture_conc_enable && in_type != PAL_STREAM_PROXY) {
             PAL_DBG(LOG_TAG, "pause on audio capture concurrency");
             *conc_en = false;
         }
diff --git a/session/src/SessionAlsaCompress.cpp b/session/src/SessionAlsaCompress.cpp
index 25648a9..5778888 100644
--- a/session/src/SessionAlsaCompress.cpp
+++ b/session/src/SessionAlsaCompress.cpp
@@ -1707,6 +1707,9 @@
 
     switch (sAttr.direction) {
         case PAL_AUDIO_OUTPUT:
+            if (compress && playback_started) {
+                status = compress_stop(compress);
+            }
             // Deregister for callback for Soft Pause
             if (isPauseRegistrationDone) {
                 payload_size = sizeof(struct agm_event_reg_cfg);
@@ -1735,10 +1738,6 @@
                     status = 0;
                 }
             }
-
-            if (compress && playback_started) {
-                status = compress_stop(compress);
-            }
             break;
         case PAL_AUDIO_INPUT:
             if (compress) {
diff --git a/session/src/SessionAlsaPcm.cpp b/session/src/SessionAlsaPcm.cpp
index f3516e9..2adcfcc 100644
--- a/session/src/SessionAlsaPcm.cpp
+++ b/session/src/SessionAlsaPcm.cpp
@@ -2741,6 +2741,8 @@
             }
 
 skip_ultrasound_gain:
+            if (tagConfig)
+                free(tagConfig);
             if (status)
                 PAL_ERR(LOG_TAG, "Failed to set Ultrasound Gain %d", status);
             return 0;
diff --git a/stream/src/Stream.cpp b/stream/src/Stream.cpp
index 1f8f2c0..2637c53 100644
--- a/stream/src/Stream.cpp
+++ b/stream/src/Stream.cpp
@@ -904,8 +904,8 @@
                     rm->unlockGraph();
                     goto exit;
                 }
-                rm->unlockGraph();
                 iter = mDevices.erase(iter);
+                rm->unlockGraph();
             }
         } else {
             PAL_ERR(LOG_TAG, "BT SCO output device is not ready");
@@ -972,8 +972,8 @@
                     rm->unlockGraph();
                     goto exit;
                 }
-                rm->unlockGraph();
                 iter = mDevices.erase(iter);
+                rm->unlockGraph();
             }
         } else {
             // For non-combo device, mute the stream and route to speaker or handset
@@ -984,8 +984,8 @@
             suspendedDevIds.clear();
             suspendedDevIds.push_back(dattr.id);
 
+            rm->lockGraph();
             for (int i = 0; i < mDevices.size(); i++) {
-                rm->lockGraph();
                 status = session->disconnectSessionDevice(this, mStreamAttr->type, mDevices[i]);
                 if (0 != status) {
                     PAL_ERR(LOG_TAG, "disconnectSessionDevice failed:%d", status);
@@ -1009,9 +1009,9 @@
                     rm->unlockGraph();
                     goto exit;
                 }
-                rm->unlockGraph();
             }
             mDevices.clear();
+            rm->unlockGraph();
             clearOutPalDevices(this);
 
             /* Check whether there's active stream associated with handset or speaker
@@ -1141,14 +1141,15 @@
                     goto exit;
                 }
             }
-            rm->unlockGraph();
 
             status = mDevices[i]->close();
             if (0 != status) {
                 PAL_ERR(LOG_TAG, "device close failed with status %d", status);
+                rm->unlockGraph();
                 goto exit;
             }
             mDevices.erase(mDevices.begin() + i);
+            rm->unlockGraph();
             break;
         }
     }
diff --git a/stream/src/StreamCommon.cpp b/stream/src/StreamCommon.cpp
index 3c8c7e1..d9cf880 100644
--- a/stream/src/StreamCommon.cpp
+++ b/stream/src/StreamCommon.cpp
@@ -274,7 +274,6 @@
 
     rm->lockGraph();
     status = session->close(this);
-    rm->unlockGraph();
     if (0 != status) {
         PAL_ERR(LOG_TAG, "Error:session close failed with status %d", status);
     }
@@ -287,6 +286,7 @@
     }
     PAL_VERBOSE(LOG_TAG, "closed the devices successfully");
     currentState = STREAM_IDLE;
+    rm->unlockGraph();
     rm->checkAndSetDutyCycleParam();
 
     mStreamMutex.unlock();
diff --git a/stream/src/StreamCompress.cpp b/stream/src/StreamCompress.cpp
index 9fe128e..72a7ce1 100644
--- a/stream/src/StreamCompress.cpp
+++ b/stream/src/StreamCompress.cpp
@@ -238,7 +238,6 @@
     }
     rm->lockGraph();
     status = session->close(this);
-    rm->unlockGraph();
     if (0 != status) {
         PAL_ERR(LOG_TAG,"session close failed with status %d", status);
     }
@@ -254,6 +253,7 @@
     }
     PAL_VERBOSE(LOG_TAG,"closed the devices successfully");
     currentState = STREAM_IDLE;
+    rm->unlockGraph();
     rm->checkAndSetDutyCycleParam();
     mStreamMutex.unlock();
 
diff --git a/stream/src/StreamPCM.cpp b/stream/src/StreamPCM.cpp
index 5f2c5a3..4bb80b2 100644
--- a/stream/src/StreamPCM.cpp
+++ b/stream/src/StreamPCM.cpp
@@ -312,7 +312,6 @@
 
     rm->lockGraph();
     status = session->close(this);
-    rm->unlockGraph();
     if (0 != status) {
         PAL_ERR(LOG_TAG, "session close failed with status %d", status);
     }
@@ -325,6 +324,7 @@
     }
     PAL_VERBOSE(LOG_TAG, "closed the devices successfully");
     currentState = STREAM_IDLE;
+    rm->unlockGraph();
     rm->checkAndSetDutyCycleParam();
     mStreamMutex.unlock();
 
diff --git a/stream/src/StreamSoundTrigger.cpp b/stream/src/StreamSoundTrigger.cpp
index 2014c1d..fc32972 100644
--- a/stream/src/StreamSoundTrigger.cpp
+++ b/stream/src/StreamSoundTrigger.cpp
@@ -389,6 +389,21 @@
     }
 
     std::lock_guard<std::mutex> lck(mStreamMutex);
+    if (cur_state_ == st_buffering_) {
+        if (!this->force_nlpi_vote) {
+            rm->voteSleepMonitor(this, true, true);
+            this->force_nlpi_vote = true;
+
+            offset = vui_intf_->GetReadOffset();
+            if (offset) {
+                reader_->advanceReadOffset(offset);
+                vui_intf_->SetReadOffset(0);
+            }
+        }
+    } else {
+        PAL_ERR(LOG_TAG, "Invalid Stream Current State %d", GetCurrentStateId());
+        return size;
+    }
     if (vui_ptfm_info_->GetEnableDebugDumps() && !lab_fd_) {
         ST_DBG_FILE_OPEN_WR(lab_fd_, ST_DEBUG_DUMP_LOCATION,
             "lab_reading", "bin", lab_cnt);
@@ -396,16 +411,6 @@
             lab_cnt);
         lab_cnt++;
     }
-    if (cur_state_ == st_buffering_ && !this->force_nlpi_vote) {
-        rm->voteSleepMonitor(this, true, true);
-        this->force_nlpi_vote = true;
-
-        offset = vui_intf_->GetReadOffset();
-        if (offset) {
-            reader_->advanceReadOffset(offset);
-            vui_intf_->SetReadOffset(0);
-        }
-    }
 
     std::shared_ptr<StEventConfig> ev_cfg(
         new StReadBufferEventConfig((void *)buf));
@@ -1139,6 +1144,11 @@
         engine = HandleEngineLoad((uint8_t *)iter.second.first,
                                   iter.second.second,
                                   iter.first, model_type_);
+        if (!engine) {
+            PAL_ERR(LOG_TAG, "Failed to create engine");
+            status = -EINVAL;
+            goto error_exit;
+        }
         std::shared_ptr<EngineCfg> engine_cfg(new EngineCfg(
             engine_id, engine, (void *)iter.second.first, iter.second.second));
 
@@ -1173,6 +1183,7 @@
     }
     engines_.clear();
     gsl_engine_.reset();
+    rm->resetStreamInstanceID(this, mInstanceID);
     if (sm_config_) {
         free(sm_config_);
         sm_config_ = nullptr;