Snap for 10453563 from a5afe506835ea6acd809320c55c578a6292f9d61 to mainline-adservices-release

Change-Id: I62cd4dac09fb0b4a877046fcf49bbf5ac4140969
diff --git a/mixer.c b/mixer.c
index fd0ad8d..506e0ef 100644
--- a/mixer.c
+++ b/mixer.c
@@ -388,7 +388,7 @@
     unsigned int n;
     int hw_ctl_count;
 
-    if (!mixer)
+    if (!mixer || !name)
         return NULL;
 
     hw_ctl_count = mixer_grp_get_count(mixer->hw_grp);
diff --git a/pcm.c b/pcm.c
index 1709be9..6d7dc29 100644
--- a/pcm.c
+++ b/pcm.c
@@ -26,6 +26,7 @@
 ** DAMAGE.
 */
 
+#include <stdbool.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <fcntl.h>
@@ -253,11 +254,11 @@
 struct pcm {
     int fd;
     unsigned int flags;
-    int running:1;
-    int prepared:1;
+    bool running:1;
+    bool prepared:1;
     int underruns;
     unsigned int buffer_size;
-    unsigned int boundary;
+    unsigned long boundary;
     char error[PCM_ERROR_MAX];
     struct pcm_config config;
     struct snd_pcm_mmap_status *mmap_status;
@@ -465,7 +466,7 @@
 int pcm_get_htimestamp(struct pcm *pcm, unsigned int *avail,
                        struct timespec *tstamp)
 {
-    int frames;
+    snd_pcm_sframes_t frames;
     int rc;
     snd_pcm_uframes_t hw_ptr;
 
@@ -488,11 +489,12 @@
     if (pcm->flags & PCM_IN)
         frames = hw_ptr - pcm->mmap_control->appl_ptr;
     else
-        frames = hw_ptr + pcm->buffer_size - pcm->mmap_control->appl_ptr;
+        frames = hw_ptr + (snd_pcm_uframes_t) pcm->buffer_size -
+                pcm->mmap_control->appl_ptr;
 
     if (frames < 0)
         frames += pcm->boundary;
-    else if (frames > (int)pcm->boundary)
+    else if (frames >= (snd_pcm_sframes_t) pcm->boundary)
         frames -= pcm->boundary;
 
     *avail = (unsigned int)frames;
@@ -549,12 +551,12 @@
                 return prepare_error;
             if (pcm->ops->ioctl(pcm->data, SNDRV_PCM_IOCTL_WRITEI_FRAMES, &x))
                 return oops(pcm, errno, "cannot write initial data");
-            pcm->running = 1;
+            pcm->running = true;
             return 0;
         }
         if (pcm->ops->ioctl(pcm->data, SNDRV_PCM_IOCTL_WRITEI_FRAMES, &x)) {
-            pcm->prepared = 0;
-            pcm->running = 0;
+            pcm->prepared = false;
+            pcm->running = false;
             if (errno == EPIPE) {
                 /* we failed to make our window -- try to restart if we are
                  * allowed to do so.  Otherwise, simply allow the EPIPE error to
@@ -589,8 +591,8 @@
             }
         }
         if (pcm->ops->ioctl(pcm->data, SNDRV_PCM_IOCTL_READI_FRAMES, &x)) {
-            pcm->prepared = 0;
-            pcm->running = 0;
+            pcm->prepared = false;
+            pcm->running = false;
             if (errno == EPIPE) {
                     /* we failed to make our window -- try to restart */
                 pcm->underruns++;
@@ -891,8 +893,8 @@
     if (pcm->snd_node)
         snd_utils_put_dev_node(pcm->snd_node);
 
-    pcm->prepared = 0;
-    pcm->running = 0;
+    pcm->prepared = false;
+    pcm->running = false;
     pcm->buffer_size = 0;
     pcm->fd = -1;
     free(pcm);
@@ -1029,15 +1031,12 @@
     sparams.xfer_align = config->period_size / 2; /* needed for old kernels */
     sparams.silence_threshold = config->silence_threshold;
     sparams.silence_size = config->silence_size;
-    pcm->boundary = sparams.boundary = pcm->buffer_size;
-
-    while (pcm->boundary * 2 <= INT_MAX - pcm->buffer_size)
-        pcm->boundary *= 2;
 
     if (pcm->ops->ioctl(pcm->data, SNDRV_PCM_IOCTL_SW_PARAMS, &sparams)) {
         oops(&bad_pcm, errno, "cannot set sw params");
         goto fail;
     }
+    pcm->boundary = sparams.boundary;
 
     rc = pcm_hw_mmap_status(pcm);
     if (rc < 0) {
@@ -1084,7 +1083,7 @@
     if (pcm->ops->ioctl(pcm->data, SNDRV_PCM_IOCTL_PREPARE) < 0)
         return oops(pcm, errno, "cannot prepare channel");
 
-    pcm->prepared = 1;
+    pcm->prepared = true;
     return 0;
 }
 
@@ -1100,7 +1099,7 @@
     if (pcm->ops->ioctl(pcm->data, SNDRV_PCM_IOCTL_START) < 0)
         return oops(pcm, errno, "cannot start channel");
 
-    pcm->running = 1;
+    pcm->running = true;
     return 0;
 }
 
@@ -1109,50 +1108,53 @@
     if (pcm->ops->ioctl(pcm->data, SNDRV_PCM_IOCTL_DROP) < 0)
         return oops(pcm, errno, "cannot stop channel");
 
-    pcm->prepared = 0;
-    pcm->running = 0;
+    pcm->prepared = false;
+    pcm->running = false;
     return 0;
 }
 
-static inline int pcm_mmap_playback_avail(struct pcm *pcm)
+static inline long pcm_mmap_playback_avail(struct pcm *pcm)
 {
-    int avail;
+    long avail = pcm->mmap_status->hw_ptr + (unsigned long) pcm->buffer_size -
+            pcm->mmap_control->appl_ptr;
 
-    avail = pcm->mmap_status->hw_ptr + pcm->buffer_size - pcm->mmap_control->appl_ptr;
-
-    if (avail < 0)
+    if (avail < 0) {
         avail += pcm->boundary;
-    else if (avail > (int)pcm->boundary)
+    } else if ((unsigned long) avail >= pcm->boundary) {
         avail -= pcm->boundary;
+    }
 
     return avail;
 }
 
-static inline int pcm_mmap_capture_avail(struct pcm *pcm)
+static inline long pcm_mmap_capture_avail(struct pcm *pcm)
 {
-    int avail = pcm->mmap_status->hw_ptr - pcm->mmap_control->appl_ptr;
-    if (avail < 0)
+    long avail = pcm->mmap_status->hw_ptr - pcm->mmap_control->appl_ptr;
+    if (avail < 0) {
         avail += pcm->boundary;
+    }
     return avail;
 }
 
 int pcm_mmap_avail(struct pcm *pcm)
 {
     pcm_sync_ptr(pcm, SNDRV_PCM_SYNC_PTR_HWSYNC);
-    if (pcm->flags & PCM_IN)
-        return pcm_mmap_capture_avail(pcm);
-    else
-        return pcm_mmap_playback_avail(pcm);
+    if (pcm->flags & PCM_IN) {
+        return (int) pcm_mmap_capture_avail(pcm);
+    } else {
+        return (int) pcm_mmap_playback_avail(pcm);
+    }
 }
 
 static void pcm_mmap_appl_forward(struct pcm *pcm, int frames)
 {
-    unsigned int appl_ptr = pcm->mmap_control->appl_ptr;
+    unsigned long appl_ptr = pcm->mmap_control->appl_ptr;
     appl_ptr += frames;
 
     /* check for boundary wrap */
-    if (appl_ptr > pcm->boundary)
+    if (appl_ptr >= pcm->boundary) {
          appl_ptr -= pcm->boundary;
+    }
     pcm->mmap_control->appl_ptr = appl_ptr;
 }
 
@@ -1313,8 +1315,8 @@
 
                 err = pcm_wait(pcm, time);
                 if (err < 0) {
-                    pcm->prepared = 0;
-                    pcm->running = 0;
+                    pcm->prepared = false;
+                    pcm->running = false;
                     oops(pcm, errno, "wait error: hw 0x%x app 0x%x avail 0x%x\n",
                         (unsigned int)pcm->mmap_status->hw_ptr,
                         (unsigned int)pcm->mmap_control->appl_ptr,
diff --git a/tinyplay.c b/tinyplay.c
index 8928d92..c5bb71f 100644
--- a/tinyplay.c
+++ b/tinyplay.c
@@ -33,6 +33,7 @@
 #include <string.h>
 #include <signal.h>
 #include <endian.h>
+#include <unistd.h>
 
 #define ID_RIFF 0x46464952
 #define ID_WAVE 0x45564157
@@ -59,7 +60,7 @@
     uint16_t bits_per_sample;
 };
 
-static int close = 0;
+static int closing = 0;
 
 void play_sample(FILE *file, unsigned int card, unsigned int device, unsigned int channels,
                  unsigned int rate, unsigned int bits, unsigned int period_size,
@@ -69,7 +70,7 @@
 {
     /* allow the stream to be closed gracefully */
     signal(sig, SIG_IGN);
-    close = 1;
+    closing = 1;
 }
 
 int main(int argc, char **argv)
@@ -270,7 +271,15 @@
             }
             data_sz -= num_read;
         }
-    } while (!close && num_read > 0 && data_sz > 0);
+    } while (!closing && num_read > 0 && data_sz > 0);
+
+    if (!closing) {
+        // drain the data in the ALSA ring buffer before closing the PCM device
+        unsigned long sleep_time_in_us =
+                (unsigned long) pcm_get_buffer_size(pcm) * 1000UL / ((unsigned long) rate / 1000UL);
+        printf("Draining... Wait %lu us\n", sleep_time_in_us);
+        usleep(sleep_time_in_us);
+    }
 
     free(buffer);
     pcm_close(pcm);