Merge "hal: spk_protection: fix crash due to invalid param sent"
diff --git a/hal/Android.mk b/hal/Android.mk
index 99b6b39..efdde67 100644
--- a/hal/Android.mk
+++ b/hal/Android.mk
@@ -199,6 +199,10 @@
     LOCAL_SRC_FILES += audio_extn/source_track.c
 endif
 
+ifeq ($(strip $(AUDIO_FEATURE_ENABLED_AUDIOSPHERE)),true)
+    LOCAL_CFLAGS += -DAUDIOSPHERE_ENABLED
+endif
+
 LOCAL_SHARED_LIBRARIES := \
 	liblog \
 	libcutils \
diff --git a/hal/audio_extn/audio_extn.c b/hal/audio_extn/audio_extn.c
index 688e265..c46c225 100644
--- a/hal/audio_extn/audio_extn.c
+++ b/hal/audio_extn/audio_extn.c
@@ -77,6 +77,8 @@
 /* Query offload playback instances count */
 #define AUDIO_PARAMETER_OFFLOAD_NUM_ACTIVE "offload_num_active"
 #define AUDIO_PARAMETER_HPX            "HPX"
+#define AUDIO_PARAMETER_KEY_ASPHERE_ENABLE   "asphere_enable"
+#define AUDIO_PARAMETER_KEY_ASPHERE_STRENGTH "asphere_strength"
 
 #ifndef FM_ENABLED
 #define audio_extn_fm_set_parameters(adev, parms) (0)
@@ -530,6 +532,103 @@
     return ret;
 }
 
+#ifndef AUDIOSPHERE_ENABLED
+#define audio_extn_asphere_set_parameters(adev, parms)  (0)
+#define audio_extn_asphere_get_parameters(adev, query, reply) (0)
+#else
+int32_t audio_extn_asphere_set_parameters(const struct audio_device *adev,
+                                     struct str_parms *parms)
+{
+    int ret = 0, val[2];
+    char value[32] = {0};
+    int set_enable, set_strength;
+    int enable = -1, strength = -1;
+    struct mixer_ctl *ctl = NULL;
+    const char *mixer_ctl_name = "MSM ASphere Set Param";
+    char propValue[PROPERTY_VALUE_MAX] = {0};
+    bool asphere_prop_enabled = false;
+
+    if (property_get("audio.pp.asphere.enabled", propValue, "false")) {
+        if (!strncmp("true", propValue, 4))
+            asphere_prop_enabled = true;
+    }
+
+    if (!asphere_prop_enabled) {
+        ALOGV("%s: property not set!!! not doing anything", __func__);
+        return ret;
+    }
+
+    set_enable = str_parms_get_str(parms,
+                            AUDIO_PARAMETER_KEY_ASPHERE_ENABLE,
+                            value, sizeof(value));
+    if (set_enable > 0)
+        enable = atoi(value);
+
+    set_strength = str_parms_get_str(parms,
+                            AUDIO_PARAMETER_KEY_ASPHERE_STRENGTH,
+                            value, sizeof(value));
+    if (set_strength > 0)
+        strength = atoi(value);
+
+    if (set_enable >= 0 || set_strength >= 0) {
+        ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
+        if (!ctl) {
+            ALOGE("%s: could not get ctl for mixer cmd - %s",
+                  __func__, mixer_ctl_name);
+            return -EINVAL;
+        }
+        ALOGD("%s: set ctl \"%s:%d,%d\"",
+              __func__, mixer_ctl_name, enable, strength);
+        val[0] = enable;
+        val[1] = strength;
+        ret = mixer_ctl_set_array(ctl, val, sizeof(val)/sizeof(val[0]));
+        if (ret)
+            ALOGE("%s: set ctl failed!!!\"%s:%d,%d\"",
+                  __func__, mixer_ctl_name, enable, strength);
+    }
+    ALOGV("%s: exit ret %d", __func__, ret);
+    return ret;
+}
+
+int32_t audio_extn_asphere_get_parameters(const struct audio_device *adev,
+                                          struct str_parms *query,
+                                          struct str_parms *reply)
+{
+    int ret = 0, val[2] = {-1, -1};
+    char value[32] = {0};
+    int get_enable, get_strength;
+    struct mixer_ctl *ctl = NULL;
+    const char *mixer_ctl_name = "MSM ASphere Set Param";
+
+    get_enable = str_parms_get_str(query,
+                                   AUDIO_PARAMETER_KEY_ASPHERE_ENABLE,
+                                   value, sizeof(value));
+    get_strength = str_parms_get_str(query,
+                                     AUDIO_PARAMETER_KEY_ASPHERE_STRENGTH,
+                                     value, sizeof(value));
+    if (get_enable > 0 || get_strength > 0) {
+        ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
+        if (!ctl) {
+            ALOGE("%s: could not get ctl for mixer cmd - %s",
+                  __func__, mixer_ctl_name);
+            return -EINVAL;
+        }
+        ret = mixer_ctl_get_array(ctl, val, sizeof(val)/sizeof(val[0]));
+        if (ret)
+            ALOGE("%s: got ctl failed!!! \"%s:%d,%d\"",
+                   __func__, mixer_ctl_name, val[0], val[1]);
+        if (get_enable > 0)
+            str_parms_add_int(reply,
+                              AUDIO_PARAMETER_KEY_ASPHERE_ENABLE, val[0]);
+        if (get_strength > 0)
+            str_parms_add_int(reply,
+                              AUDIO_PARAMETER_KEY_ASPHERE_STRENGTH, val[1]);
+    }
+    ALOGV("%s: exit ret %d", __func__, ret);
+    return ret;
+}
+#endif
+
 void audio_extn_set_parameters(struct audio_device *adev,
                                struct str_parms *parms)
 {
@@ -547,6 +646,7 @@
    audio_extn_hpx_set_parameters(adev, parms);
    audio_extn_pm_set_parameters(parms);
    audio_extn_source_track_set_parameters(adev, parms);
+   audio_extn_asphere_set_parameters(adev, parms);
 }
 
 void audio_extn_get_parameters(const struct audio_device *adev,
@@ -560,6 +660,7 @@
     audio_extn_dts_eagle_get_parameters(adev, query, reply);
     audio_extn_hpx_get_parameters(query, reply);
     audio_extn_source_track_get_parameters(adev, query, reply);
+    audio_extn_asphere_get_parameters(adev, query, reply);
 
     kv_pairs = str_parms_to_str(reply);
     ALOGD_IF(kv_pairs != NULL, "%s: returns %s", __func__, kv_pairs);
diff --git a/hal/audio_hw.c b/hal/audio_hw.c
index 138bd3c..4f69bd5 100644
--- a/hal/audio_hw.c
+++ b/hal/audio_hw.c
@@ -2246,9 +2246,13 @@
 {
     struct stream_out *out = (struct stream_out *)stream;
     struct audio_device *adev = out->dev;
-    if (is_offload_usecase(out->usecase) && (dsp_frames != NULL)) {
+
+    if (dsp_frames == NULL)
+        return -EINVAL;
+
+    *dsp_frames = 0;
+    if (is_offload_usecase(out->usecase)) {
         ssize_t ret = 0;
-        *dsp_frames = 0;
         pthread_mutex_lock(&out->lock);
         if (out->compr != NULL) {
             ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
@@ -2276,6 +2280,9 @@
         } else {
             return 0;
         }
+    } else if (audio_is_linear_pcm(out->format)) {
+        *dsp_frames = out->written;
+        return 0;
     } else
         return -EINVAL;
 }
@@ -2807,6 +2814,9 @@
         return -ENOMEM;
     }
 
+    pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
+    pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
+
     if (devices == AUDIO_DEVICE_NONE)
         devices = AUDIO_DEVICE_OUT_SPEAKER;
 
@@ -3078,9 +3088,6 @@
     /* out->muted = false; by calloc() */
     /* out->written = 0; by calloc() */
 
-    pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
-    pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
-
     config->format = out->stream.common.get_format(&out->stream.common);
     config->channel_mask = out->stream.common.get_channels(&out->stream.common);
     config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
diff --git a/hal/msm8916/platform.c b/hal/msm8916/platform.c
index e061fdc..e9780bc 100644
--- a/hal/msm8916/platform.c
+++ b/hal/msm8916/platform.c
@@ -86,7 +86,8 @@
 #define MIN_COMPRESS_PASSTHROUGH_FRAGMENT_SIZE (2 * 1024)
 #define MAX_COMPRESS_PASSTHROUGH_FRAGMENT_SIZE (8 * 1024)
 
-#define ALIGN( num, to ) (((num) + (to-1)) & (~(to-1)))
+#define DIV_ROUND_UP(x, y) (((x) + (y) - 1)/(y))
+#define ALIGN(x, y) ((y) * DIV_ROUND_UP((x), (y)))
 /*
  * This file will have a maximum of 38 bytes:
  *
@@ -3273,12 +3274,15 @@
                      * info->sample_rate
                      * (bits_per_sample >> 3)
                      * popcount(info->channel_mask))/1000;
-    // align with LCM of 2, 4, 6, 8
-    fragment_size = ALIGN( fragment_size, 24 );
     if(fragment_size < MIN_PCM_OFFLOAD_FRAGMENT_SIZE)
         fragment_size = MIN_PCM_OFFLOAD_FRAGMENT_SIZE;
     else if(fragment_size > MAX_PCM_OFFLOAD_FRAGMENT_SIZE)
         fragment_size = MAX_PCM_OFFLOAD_FRAGMENT_SIZE;
+    // To have same PCM samples for all channels, the buffer size requires to
+    // be multiple of (number of channels * bytes per sample)
+    // For writes to succeed, the buffer must be written at address which is multiple of 32
+    // Alignment of 96 satsfies both of the above requirements
+    fragment_size = ALIGN(fragment_size, 96);
 
     ALOGI("PCM offload Fragment size to %d bytes", fragment_size);
     return fragment_size;
@@ -3290,8 +3294,15 @@
     ALOGV("%s bit width: %d, sample rate: %d", __func__, bit_width, sample_rate);
 
     int ret = 0;
+    const char *snd_card_name = mixer_get_name(adev->mixer);
     if (bit_width != adev->cur_codec_backend_bit_width) {
-        const char * mixer_ctl_name = "SLIM_0_RX Format";
+        const char * mixer_ctl_name;
+        if (!strncmp(snd_card_name, "msm8952-tomtom-snd-card",
+                 sizeof("msm8952-tomtom-snd-card"))) {
+            mixer_ctl_name = "SLIM_0_RX Format";
+        }
+        else
+            mixer_ctl_name = "MI2S_RX Format";
         struct  mixer_ctl *ctl;
         ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
         if (!ctl) {
diff --git a/hal/msm8974/platform.c b/hal/msm8974/platform.c
index 8debc0a..24e23e6 100644
--- a/hal/msm8974/platform.c
+++ b/hal/msm8974/platform.c
@@ -380,13 +380,13 @@
     [SND_DEVICE_NONE] = -1,
     [SND_DEVICE_OUT_HANDSET] = 7,
     [SND_DEVICE_OUT_SPEAKER] = 14,
-    [SND_DEVICE_OUT_SPEAKER_EXTERNAL_1] = 14,
-    [SND_DEVICE_OUT_SPEAKER_EXTERNAL_2] = 14,
+    [SND_DEVICE_OUT_SPEAKER_EXTERNAL_1] = 130,
+    [SND_DEVICE_OUT_SPEAKER_EXTERNAL_2] = 130,
     [SND_DEVICE_OUT_SPEAKER_REVERSE] = 14,
     [SND_DEVICE_OUT_HEADPHONES] = 10,
     [SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES] = 10,
-    [SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES_EXTERNAL_1] = 10,
-    [SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES_EXTERNAL_2] = 10,
+    [SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES_EXTERNAL_1] = 130,
+    [SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES_EXTERNAL_2] = 130,
     [SND_DEVICE_OUT_VOICE_HANDSET] = 7,
     [SND_DEVICE_OUT_VOICE_SPEAKER] = 14,
     [SND_DEVICE_OUT_VOICE_HEADPHONES] = 10,
diff --git a/policy_hal/AudioPolicyManager.cpp b/policy_hal/AudioPolicyManager.cpp
index ec48a71..76128e5 100644
--- a/policy_hal/AudioPolicyManager.cpp
+++ b/policy_hal/AudioPolicyManager.cpp
@@ -1605,11 +1605,13 @@
         }
     } else if (offloadInfo.duration_us < OFFLOAD_DEFAULT_MIN_DURATION_SECS * 1000000) {
         ALOGD("copl: Offload denied by duration < default min(=%u)", OFFLOAD_DEFAULT_MIN_DURATION_SECS);
-        //duration checks only valid for MP3/AAC formats,
+        //duration checks only valid for MP3/AAC/WMA formats,
         //do not check duration for other audio formats, e.g. dolby AAC/AC3 and amrwb+ formats
         if ((offloadInfo.format == AUDIO_FORMAT_MP3) ||
             ((offloadInfo.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC) ||
             ((offloadInfo.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_FLAC) ||
+            ((offloadInfo.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_WMA) ||
+            ((offloadInfo.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_WMA_PRO) ||
             pcmOffload)
             return false;
     }