Merge "hal: Add support for LINE out device"
diff --git a/hal/Android.mk b/hal/Android.mk
index 72042d1..e457b83 100644
--- a/hal/Android.mk
+++ b/hal/Android.mk
@@ -161,10 +161,6 @@
 endif
 endif
 
-ifeq ($(strip $(AUDIO_FEATURE_ENABLED_MULTIPLE_TUNNEL)), true)
-    LOCAL_CFLAGS += -DMULTIPLE_OFFLOAD_ENABLED
-endif
-
 ifeq ($(strip $(AUDIO_FEATURE_ENABLED_EXTN_FLAC_DECODER)),true)
     LOCAL_CFLAGS += -DFLAC_OFFLOAD_ENABLED
     LOCAL_CFLAGS += -DCOMPRESS_METADATA_NEEDED
diff --git a/hal/audio_extn/hfp.c b/hal/audio_extn/hfp.c
index a73dfa1..3e09e55 100644
--- a/hal/audio_extn/hfp.c
+++ b/hal/audio_extn/hfp.c
@@ -47,6 +47,8 @@
 
 #ifdef PLATFORM_MSM8994
 #define HFP_RX_VOLUME     "SEC AUXPCM LOOPBACK Volume"
+#elif defined PLATFORM_MSM8996
+#define HFP_RX_VOLUME     "PRI AUXPCM LOOPBACK Volume"
 #else
 #define HFP_RX_VOLUME     "Internal HFP RX Volume"
 #endif
diff --git a/hal/audio_hw.c b/hal/audio_hw.c
index facb8d8..e6fbc5f 100644
--- a/hal/audio_hw.c
+++ b/hal/audio_hw.c
@@ -170,7 +170,6 @@
     [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
     //Enabled for Direct_PCM
     [USECASE_AUDIO_PLAYBACK_OFFLOAD2] = "compress-offload-playback2",
-#ifdef MULTIPLE_OFFLOAD_ENABLED
     [USECASE_AUDIO_PLAYBACK_OFFLOAD3] = "compress-offload-playback3",
     [USECASE_AUDIO_PLAYBACK_OFFLOAD4] = "compress-offload-playback4",
     [USECASE_AUDIO_PLAYBACK_OFFLOAD5] = "compress-offload-playback5",
@@ -178,7 +177,6 @@
     [USECASE_AUDIO_PLAYBACK_OFFLOAD7] = "compress-offload-playback7",
     [USECASE_AUDIO_PLAYBACK_OFFLOAD8] = "compress-offload-playback8",
     [USECASE_AUDIO_PLAYBACK_OFFLOAD9] = "compress-offload-playback9",
-#endif
 
     [USECASE_AUDIO_RECORD] = "audio-record",
     [USECASE_AUDIO_RECORD_COMPRESS] = "audio-record-compress",
@@ -215,7 +213,6 @@
 static const audio_usecase_t offload_usecases[] = {
     USECASE_AUDIO_PLAYBACK_OFFLOAD,
     USECASE_AUDIO_PLAYBACK_OFFLOAD2,
-#ifdef MULTIPLE_OFFLOAD_ENABLED
     USECASE_AUDIO_PLAYBACK_OFFLOAD3,
     USECASE_AUDIO_PLAYBACK_OFFLOAD4,
     USECASE_AUDIO_PLAYBACK_OFFLOAD5,
@@ -223,7 +220,6 @@
     USECASE_AUDIO_PLAYBACK_OFFLOAD7,
     USECASE_AUDIO_PLAYBACK_OFFLOAD8,
     USECASE_AUDIO_PLAYBACK_OFFLOAD9,
-#endif
 };
 
 #define STRING_TO_ENUM(string) { #string, string }
diff --git a/hal/audio_hw.h b/hal/audio_hw.h
index 4ab9e6e..fd19211 100644
--- a/hal/audio_hw.h
+++ b/hal/audio_hw.h
@@ -88,7 +88,6 @@
     USECASE_AUDIO_PLAYBACK_MULTI_CH,
     USECASE_AUDIO_PLAYBACK_OFFLOAD,
     USECASE_AUDIO_PLAYBACK_OFFLOAD2,
-#ifdef MULTIPLE_OFFLOAD_ENABLED
     USECASE_AUDIO_PLAYBACK_OFFLOAD3,
     USECASE_AUDIO_PLAYBACK_OFFLOAD4,
     USECASE_AUDIO_PLAYBACK_OFFLOAD5,
@@ -96,7 +95,6 @@
     USECASE_AUDIO_PLAYBACK_OFFLOAD7,
     USECASE_AUDIO_PLAYBACK_OFFLOAD8,
     USECASE_AUDIO_PLAYBACK_OFFLOAD9,
-#endif
     USECASE_AUDIO_PLAYBACK_ULL,
 
     /* FM usecase */
diff --git a/hal/msm8916/platform.c b/hal/msm8916/platform.c
index df81a68..a478f93 100644
--- a/hal/msm8916/platform.c
+++ b/hal/msm8916/platform.c
@@ -268,7 +268,6 @@
                                         MULTIMEDIA2_PCM_DEVICE},
     [USECASE_AUDIO_PLAYBACK_OFFLOAD] =
                      {PLAYBACK_OFFLOAD_DEVICE, PLAYBACK_OFFLOAD_DEVICE},
-#ifdef MULTIPLE_OFFLOAD_ENABLED
     /* Below entries are initialized with invalid values
      * Valid values should be updated from fnc platform_info_init()
      * based on pcm ids defined in audio_platform_info.xml.
@@ -281,7 +280,6 @@
     [USECASE_AUDIO_PLAYBACK_OFFLOAD7] = {-1, -1},
     [USECASE_AUDIO_PLAYBACK_OFFLOAD8] = {-1, -1},
     [USECASE_AUDIO_PLAYBACK_OFFLOAD9] = {-1, -1},
-#endif
     [USECASE_AUDIO_RECORD] = {AUDIO_RECORD_PCM_DEVICE, AUDIO_RECORD_PCM_DEVICE},
     [USECASE_AUDIO_RECORD_COMPRESS] = {COMPRESS_CAPTURE_DEVICE, COMPRESS_CAPTURE_DEVICE},
     [USECASE_AUDIO_RECORD_LOW_LATENCY] = {LOWLATENCY_PCM_DEVICE,
@@ -657,7 +655,6 @@
     {TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_LOW_LATENCY)},
     {TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_MULTI_CH)},
     {TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_OFFLOAD)},
-#ifdef MULTIPLE_OFFLOAD_ENABLED
     {TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_OFFLOAD2)},
     {TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_OFFLOAD3)},
     {TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_OFFLOAD4)},
@@ -666,7 +663,6 @@
     {TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_OFFLOAD7)},
     {TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_OFFLOAD8)},
     {TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_OFFLOAD9)},
-#endif
     {TO_NAME_INDEX(USECASE_AUDIO_RECORD)},
     {TO_NAME_INDEX(USECASE_AUDIO_RECORD_LOW_LATENCY)},
     {TO_NAME_INDEX(USECASE_VOICE_CALL)},
diff --git a/hal/msm8974/platform.c b/hal/msm8974/platform.c
index 6aa22cf..cc48b9e 100644
--- a/hal/msm8974/platform.c
+++ b/hal/msm8974/platform.c
@@ -260,7 +260,6 @@
                      {PLAYBACK_OFFLOAD_DEVICE, PLAYBACK_OFFLOAD_DEVICE},
     [USECASE_AUDIO_PLAYBACK_OFFLOAD2] =
                      {PLAYBACK_OFFLOAD_DEVICE2, PLAYBACK_OFFLOAD_DEVICE2},
-#ifdef MULTIPLE_OFFLOAD_ENABLED
     [USECASE_AUDIO_PLAYBACK_OFFLOAD3] =
                      {PLAYBACK_OFFLOAD_DEVICE3, PLAYBACK_OFFLOAD_DEVICE3},
     [USECASE_AUDIO_PLAYBACK_OFFLOAD4] =
@@ -275,7 +274,6 @@
                      {PLAYBACK_OFFLOAD_DEVICE8, PLAYBACK_OFFLOAD_DEVICE8},
     [USECASE_AUDIO_PLAYBACK_OFFLOAD9] =
                      {PLAYBACK_OFFLOAD_DEVICE9, PLAYBACK_OFFLOAD_DEVICE9},
-#endif
 
 
     [USECASE_AUDIO_RECORD] = {AUDIO_RECORD_PCM_DEVICE, AUDIO_RECORD_PCM_DEVICE},
@@ -642,7 +640,6 @@
     {TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_MULTI_CH)},
     {TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_OFFLOAD)},
     {TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_OFFLOAD2)},
-#ifdef MULTIPLE_OFFLOAD_ENABLED
     {TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_OFFLOAD3)},
     {TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_OFFLOAD4)},
     {TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_OFFLOAD5)},
@@ -650,7 +647,6 @@
     {TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_OFFLOAD7)},
     {TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_OFFLOAD8)},
     {TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_OFFLOAD9)},
-#endif
     {TO_NAME_INDEX(USECASE_AUDIO_RECORD)},
     {TO_NAME_INDEX(USECASE_AUDIO_RECORD_LOW_LATENCY)},
     {TO_NAME_INDEX(USECASE_VOICE_CALL)},
@@ -1274,7 +1270,7 @@
     char value[PROPERTY_VALUE_MAX];
     struct platform_data *my_data = NULL;
     int retry_num = 0, snd_card_num = 0, key = 0;
-    const char *snd_card_name;
+    const char *snd_card_name = NULL;
     char *cvd_version = NULL;
     char *snd_internal_name = NULL;
     char *tmp = NULL;
@@ -1386,7 +1382,8 @@
     if (snd_card_num >= MAX_SND_CARD) {
         ALOGE("%s: Unable to find correct sound card, aborting.", __func__);
         free(my_data);
-        free(snd_card_name);
+        if (snd_card_name)
+            free(snd_card_name);
         return NULL;
     }
 
diff --git a/hal/msm8974/platform.h b/hal/msm8974/platform.h
index 6db2905..a2c6304 100644
--- a/hal/msm8974/platform.h
+++ b/hal/msm8974/platform.h
@@ -257,7 +257,6 @@
 #define PLAYBACK_OFFLOAD_DEVICE2 17
 #endif
 
-#ifdef MULTIPLE_OFFLOAD_ENABLED
 #ifdef PLATFORM_APQ8084
 #define PLAYBACK_OFFLOAD_DEVICE3 18
 #define PLAYBACK_OFFLOAD_DEVICE4 34
@@ -276,7 +275,6 @@
 #define PLAYBACK_OFFLOAD_DEVICE8 41
 #define PLAYBACK_OFFLOAD_DEVICE9 42
 #endif
-#endif
 
 #define COMPRESS_VOIP_CALL_PCM_DEVICE 3
 
diff --git a/policy_hal/AudioPolicyManager.cpp b/policy_hal/AudioPolicyManager.cpp
index 900e6cc..46c58c5 100644
--- a/policy_hal/AudioPolicyManager.cpp
+++ b/policy_hal/AudioPolicyManager.cpp
@@ -962,18 +962,22 @@
 
 }
 
-status_t AudioPolicyManagerCustom::stopSource(sp<SwAudioOutputDescriptor> outputDesc,
+status_t AudioPolicyManagerCustom::stopSource(sp<AudioOutputDescriptor> outputDesc,
                                             audio_stream_type_t stream,
                                             bool forceDeviceUpdate)
 {
+    if (stream < 0 || stream >= AUDIO_STREAM_CNT) {
+        ALOGW("stopSource() invalid stream %d", stream);
+        return INVALID_OPERATION;
+    }
     // always handle stream stop, check which stream type is stopping
     handleEventForBeacon(stream == AUDIO_STREAM_TTS ? STOPPING_BEACON : STOPPING_OUTPUT);
 
     // handle special case for sonification while in call
     if (isInCall() && (outputDesc->mRefCount[stream] == 1)) {
         if (outputDesc->isDuplicated()) {
-            handleIncallSonification(stream, false, false, outputDesc->mOutput1->mIoHandle);
-            handleIncallSonification(stream, false, false, outputDesc->mOutput2->mIoHandle);
+            handleIncallSonification(stream, false, false, outputDesc->subOutput1()->mIoHandle);
+            handleIncallSonification(stream, false, false, outputDesc->subOutput2()->mIoHandle);
         }
         handleIncallSonification(stream, false, false, outputDesc->mIoHandle);
     }
@@ -1008,7 +1012,7 @@
                         if (dev == prevDevice) {
                             delayMs = 0;
                         } else {
-                            delayMs = outputDesc->mLatency*2;
+                            delayMs = outputDesc->latency()*2;
                         }
                         setOutputDevice(desc,
                                     dev,
@@ -1025,7 +1029,7 @@
         return INVALID_OPERATION;
     }
 }
-status_t AudioPolicyManagerCustom::startSource(sp<SwAudioOutputDescriptor> outputDesc,
+status_t AudioPolicyManagerCustom::startSource(sp<AudioOutputDescriptor> outputDesc,
                                              audio_stream_type_t stream,
                                              audio_devices_t device,
                                              uint32_t *delayMs)
@@ -1033,6 +1037,11 @@
     // cannot start playback of STREAM_TTS if any other output is being used
     uint32_t beaconMuteLatency = 0;
 
+    if (stream < 0 || stream >= AUDIO_STREAM_CNT) {
+        ALOGW("startSource() invalid stream %d", stream);
+        return INVALID_OPERATION;
+    }
+
     *delayMs = 0;
     if (stream == AUDIO_STREAM_TTS) {
         ALOGV("\t found BEACON stream");
@@ -1176,10 +1185,14 @@
 }
 status_t AudioPolicyManagerCustom::checkAndSetVolume(audio_stream_type_t stream,
                                                    int index,
-                                                   const sp<SwAudioOutputDescriptor>& outputDesc,
+                                                   const sp<AudioOutputDescriptor>& outputDesc,
                                                    audio_devices_t device,
                                                    int delayMs, bool force)
 {
+    if (stream < 0 || stream >= AUDIO_STREAM_CNT) {
+        ALOGW("checkAndSetVolume() invalid stream %d", stream);
+        return INVALID_OPERATION;
+    }
     // do not change actual stream volume if the stream is muted
     if (outputDesc->mMuteCount[stream] != 0) {
         ALOGVV("checkAndSetVolume() stream %d muted count %d",
@@ -1574,23 +1587,29 @@
     if (profile != 0) {
         sp<SwAudioOutputDescriptor> outputDesc = NULL;
 
-        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 and configured with same parameters
-                if ((samplingRate == outputDesc->mSamplingRate) &&
-                        (format == outputDesc->mFormat) &&
-                        (channelMask == outputDesc->mChannelMask)) {
-                    outputDesc->mDirectOpenCount++;
-                    ALOGV("getOutput() reusing direct output %d", mOutputs.keyAt(i));
-                    return mOutputs.keyAt(i);
+        // 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 (!(property_get_bool("audio.offload.multiple.enabled", false) &&
+                ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) != 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 and configured with same parameters
+                    if ((samplingRate == outputDesc->mSamplingRate) &&
+                            (format == outputDesc->mFormat) &&
+                            (channelMask == outputDesc->mChannelMask)) {
+                        outputDesc->mDirectOpenCount++;
+                        ALOGV("getOutput() reusing direct output %d", mOutputs.keyAt(i));
+                        return mOutputs.keyAt(i);
+                    }
                 }
             }
-        }
-        // close direct output if currently open and configured with different parameters
-        if (outputDesc != NULL) {
-            closeOutput(outputDesc->mIoHandle);
+            // close direct output if currently open and configured with different parameters
+            if (outputDesc != NULL) {
+                closeOutput(outputDesc->mIoHandle);
+            }
         }
 
         // if the selected profile is offloaded and no offload info was specified,
diff --git a/policy_hal/AudioPolicyManager.h b/policy_hal/AudioPolicyManager.h
index dfaad65..a7f88e4 100644
--- a/policy_hal/AudioPolicyManager.h
+++ b/policy_hal/AudioPolicyManager.h
@@ -79,7 +79,7 @@
 
          status_t checkAndSetVolume(audio_stream_type_t stream,
                                                    int index,
-                                                   const sp<SwAudioOutputDescriptor>& outputDesc,
+                                                   const sp<AudioOutputDescriptor>& outputDesc,
                                                    audio_devices_t device,
                                                    int delayMs = 0, bool force = false);
 
@@ -94,11 +94,11 @@
 
         // if argument "device" is different from AUDIO_DEVICE_NONE,  startSource() will force
         // the re-evaluation of the output device.
-        status_t startSource(sp<SwAudioOutputDescriptor> outputDesc,
+        status_t startSource(sp<AudioOutputDescriptor> outputDesc,
                              audio_stream_type_t stream,
                              audio_devices_t device,
                              uint32_t *delayMs);
-         status_t stopSource(sp<SwAudioOutputDescriptor> outputDesc,
+         status_t stopSource(sp<AudioOutputDescriptor> outputDesc,
                             audio_stream_type_t stream,
                             bool forceDeviceUpdate);
         // event is one of STARTING_OUTPUT, STARTING_BEACON, STOPPING_OUTPUT, STOPPING_BEACON
diff --git a/post_proc/volume_listener.c b/post_proc/volume_listener.c
index d540bf5..e1dd026 100644
--- a/post_proc/volume_listener.c
+++ b/post_proc/volume_listener.c
@@ -324,6 +324,13 @@
  * Effect Control Interface Implementation
  */
 
+static inline int16_t clamp16(int32_t sample)
+{
+    if ((sample>>15) ^ (sample>>31))
+        sample = 0x7FFF ^ (sample>>31);
+    return sample;
+}
+
 static int vol_effect_process(effect_handle_t self,
                               audio_buffer_t *in_buffer,
                               audio_buffer_t *out_buffer)
@@ -342,7 +349,14 @@
 
     // calculation based on channel count 2
     if (in_buffer->raw != out_buffer->raw) {
-        memcpy(out_buffer->raw, in_buffer->raw, out_buffer->frameCount * 2 * sizeof(int16_t));
+        if (context->config.outputCfg.accessMode == EFFECT_BUFFER_ACCESS_ACCUMULATE) {
+            size_t i;
+            for (i = 0; i < out_buffer->frameCount*2; i++) {
+                out_buffer->s16[i] = clamp16(out_buffer->s16[i] + in_buffer->s16[i]);
+            }
+        } else {
+            memcpy(out_buffer->raw, in_buffer->raw, out_buffer->frameCount * 2 * sizeof(int16_t));
+        }
     } else {
         ALOGV("%s: something wrong, didn't handle in_buffer and out_buffer same address case",
               __func__);
@@ -386,6 +400,12 @@
 
     case EFFECT_CMD_SET_CONFIG:
         ALOGV("%s :: cmd called EFFECT_CMD_SET_CONFIG", __func__);
+        if (p_cmd_data == NULL || cmd_size != sizeof(effect_config_t)
+                || p_reply_data == NULL || reply_size == NULL || *reply_size != sizeof(int)) {
+            return -EINVAL;
+        }
+        context->config = *(effect_config_t *)p_cmd_data;
+        *(int *)p_reply_data = 0;
         break;
 
     case EFFECT_CMD_GET_CONFIG:
@@ -612,7 +632,7 @@
 
 static int vol_prc_lib_create(const effect_uuid_t *uuid,
                               int32_t session_id,
-                              int32_t io_id,
+                              int32_t io_id __unused,
                               effect_handle_t *p_handle)
 {
     int itt = 0;