Merge "hal: fix klockwork failures in audio hal"
diff --git a/hal/Android.mk b/hal/Android.mk
index 38873cf..05d3e82 100644
--- a/hal/Android.mk
+++ b/hal/Android.mk
@@ -52,7 +52,7 @@
 LOCAL_C_INCLUDES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/include
 LOCAL_ADDITIONAL_DEPENDENCIES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr
 
-ifneq ($(filter msm8994 msm8992,$(TARGET_BOARD_PLATFORM)),)
+ifeq ($(strip $(AUDIO_FEATURE_ENABLED_HDMI_EDID)),true)
     LOCAL_SRC_FILES += edid.c
 endif
 
diff --git a/hal/audio_extn/dev_arbi.c b/hal/audio_extn/dev_arbi.c
index d3c01c5..d7ab5ff 100644
--- a/hal/audio_extn/dev_arbi.c
+++ b/hal/audio_extn/dev_arbi.c
@@ -128,7 +128,13 @@
 {
     static snd_aud_dev_mapping_t snd_aud_dev_map[] = {
         {SND_DEVICE_OUT_HANDSET, AUDIO_DEVICE_OUT_EARPIECE},
-        {SND_DEVICE_OUT_VOICE_HANDSET, AUDIO_DEVICE_OUT_EARPIECE}
+        {SND_DEVICE_OUT_VOICE_HANDSET, AUDIO_DEVICE_OUT_EARPIECE},
+        {SND_DEVICE_OUT_SPEAKER, AUDIO_DEVICE_OUT_SPEAKER},
+        {SND_DEVICE_OUT_VOICE_SPEAKER, AUDIO_DEVICE_OUT_SPEAKER},
+        {SND_DEVICE_OUT_HEADPHONES, AUDIO_DEVICE_OUT_WIRED_HEADPHONE},
+        {SND_DEVICE_OUT_VOICE_HEADPHONES, AUDIO_DEVICE_OUT_WIRED_HEADPHONE},
+        {SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES,
+            AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_WIRED_HEADPHONE}
     };
 
     audio_devices_t aud_device = AUDIO_DEVICE_NONE;
diff --git a/hal/audio_extn/dts_eagle.c b/hal/audio_extn/dts_eagle.c
index b4bbb9f..7fa2c9b 100644
--- a/hal/audio_extn/dts_eagle.c
+++ b/hal/audio_extn/dts_eagle.c
@@ -136,7 +136,19 @@
 }
 
 static void fade_node(bool need_data) {
-    int fd = creat(FADE_NOTIFY_FILE, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH), n = 0;
+    char prop[PROPERTY_VALUE_MAX];
+    property_get("use.dts_eagle", prop, "0");
+    if (strncmp("true", prop, sizeof("true")))
+        return;
+    int fd, n = 0;
+    if ((fd = open(FADE_NOTIFY_FILE, O_RDONLY)) < 0)
+        ALOGV("No fade node");
+    else {
+        ALOGV("fade node exists, remove it before creating it");
+        close(fd);
+        remove(FADE_NOTIFY_FILE);
+    }
+    fd = creat(FADE_NOTIFY_FILE, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
     char *str = need_data ? "need" : "have";
     if (fd < 0) {
         ALOGE("DTS_EAGLE_HAL (%s): opening fade notifier node failed", __func__);
@@ -301,7 +313,6 @@
         if (fade_in > 0 && fade_in_data && fade_out_data)
             fade_node(false);
     }
-
     ALOGV("DTS_EAGLE_HAL (%s): exit", __func__);
 }
 
@@ -427,10 +438,9 @@
         chmod(path, S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH);
         ALOGV("DTS_EAGLE_NODE_STREAM (%s): opening state notifier node successful", __func__);
         close(fd);
+        if (!fade_in_data || !fade_out_data)
+            fade_node(true);
     }
-
-    if (!fade_in_data || !fade_out_data)
-        fade_node(true);
 }
 
 void audio_extn_dts_notify_playback_state(int stream_out, int has_video, int sample_rate,
diff --git a/hal/audio_hw.c b/hal/audio_hw.c
index a72ae38..96f252c 100644
--- a/hal/audio_hw.c
+++ b/hal/audio_hw.c
@@ -75,7 +75,7 @@
 
 #define COMPRESS_OFFLOAD_NUM_FRAGMENTS 4
 /* ToDo: Check and update a proper value in msec */
-#define COMPRESS_OFFLOAD_PLAYBACK_LATENCY 96
+#define COMPRESS_OFFLOAD_PLAYBACK_LATENCY 50
 #define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
 
 #define PROXY_OPEN_RETRY_COUNT           100
@@ -465,8 +465,10 @@
            adev->snd_dev_ref_cnt[snd_device]--;
            return -EINVAL;
        }
+       audio_extn_dev_arbi_acquire(snd_device);
         if (audio_extn_spkr_prot_start_processing(snd_device)) {
             ALOGE("%s: spkr_start_processing failed", __func__);
+            audio_extn_dev_arbi_release(snd_device);
             return -EINVAL;
         }
     } else {
@@ -532,9 +534,9 @@
             audio_extn_spkr_prot_stop_processing(snd_device);
         } else {
             audio_route_reset_and_update_path(adev->audio_route, device_name);
-            audio_extn_dev_arbi_release(snd_device);
         }
 
+        audio_extn_dev_arbi_release(snd_device);
         audio_extn_sound_trigger_update_device_status(snd_device,
                                         ST_EVENT_SND_DEVICE_FREE);
         audio_extn_listen_update_device_status(snd_device,
@@ -1546,6 +1548,14 @@
         if (out->offload_callback)
             compress_nonblock(out->compr, out->non_blocking);
 
+        /* Since small bufs uses blocking writes, a write will be blocked
+           for the default max poll time (20s) in the event of an SSR.
+           Reduce the poll time to observe and deal with SSR faster.
+        */
+        if (out->use_small_bufs) {
+            compress_set_max_poll_wait(out->compr, 1000);
+        }
+
         audio_extn_dts_create_state_notifier_node(out->usecase);
         audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
                                              popcount(out->channel_mask),
@@ -1995,13 +2005,7 @@
     uint32_t latency = 0;
 
     if (is_offload_usecase(out->usecase)) {
-        if (out->use_small_bufs == true)
-            latency = ((out->compr_config.fragments *
-                   out->compr_config.fragment_size * 1000) /
-                   (out->sample_rate * out->compr_config.codec->ch_in *
-                   audio_bytes_per_sample(out->format)));
-        else
-            latency = COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
+        latency = COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
     } else {
         latency = (out->config.period_count * out->config.period_size * 1000) /
            (out->config.rate);
@@ -2093,7 +2097,7 @@
     }
 
     if (is_offload_usecase(out->usecase)) {
-        ALOGD("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
+        ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
         if (out->send_new_metadata) {
             ALOGD("copl(%p):send new gapless metadata", out);
             compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
diff --git a/hal/msm8974/platform.c b/hal/msm8974/platform.c
index 3286ca5..d6261c1 100644
--- a/hal/msm8974/platform.c
+++ b/hal/msm8974/platform.c
@@ -79,7 +79,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:
  *
@@ -2942,8 +2943,11 @@
                      * 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 );
+    // 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);
     if(fragment_size < MIN_PCM_OFFLOAD_FRAGMENT_SIZE)
         fragment_size = MIN_PCM_OFFLOAD_FRAGMENT_SIZE;
     else if(fragment_size > MAX_PCM_OFFLOAD_FRAGMENT_SIZE)
diff --git a/hal/voice_extn/compress_voip.c b/hal/voice_extn/compress_voip.c
index 26636db..e8ba1f9 100644
--- a/hal/voice_extn/compress_voip.c
+++ b/hal/voice_extn/compress_voip.c
@@ -328,6 +328,7 @@
     int i, ret = 0;
     struct audio_usecase *uc_info;
     int pcm_dev_rx_id, pcm_dev_tx_id;
+    unsigned int flags = PCM_OUT | PCM_MONOTONIC;
 
     ALOGD("%s: enter", __func__);
 
@@ -368,7 +369,7 @@
               __func__, adev->snd_card, pcm_dev_rx_id);
         voip_data.pcm_rx = pcm_open(adev->snd_card,
                                     pcm_dev_rx_id,
-                                    PCM_OUT, voip_config);
+                                    flags, voip_config);
         if (voip_data.pcm_rx && !pcm_is_ready(voip_data.pcm_rx)) {
             ALOGE("%s: %s", __func__, pcm_get_error(voip_data.pcm_rx));
             pcm_close(voip_data.pcm_rx);