merge in mnc-dr-release history after reset to mnc-dr-dev
diff --git a/alsa_utils/alsa_device_profile.c b/alsa_utils/alsa_device_profile.c
index c9f8f99..dd238e7 100644
--- a/alsa_utils/alsa_device_profile.c
+++ b/alsa_utils/alsa_device_profile.c
@@ -44,14 +44,6 @@
     "AUDIO_FORMAT_PCM_24_BIT_PACKED"/* "PCM_FORMAT_S24_3LE" */
 };
 
-static const unsigned const format_byte_size_map[] = {
-    2, /* PCM_FORMAT_S16_LE */
-    4, /* PCM_FORMAT_S32_LE */
-    1, /* PCM_FORMAT_S8 */
-    4, /* PCM_FORMAT_S24_LE */
-    3, /* PCM_FORMAT_S24_3LE */
-};
-
 extern int8_t const pcm_format_value_map[50];
 
 /* Sort these in terms of preference (best first).
diff --git a/alsa_utils/alsa_device_proxy.c b/alsa_utils/alsa_device_proxy.c
index d2d8b6f..ac948f1 100644
--- a/alsa_utils/alsa_device_proxy.c
+++ b/alsa_utils/alsa_device_proxy.c
@@ -29,6 +29,16 @@
 #define DEFAULT_PERIOD_SIZE     1024
 #define DEFAULT_PERIOD_COUNT    2
 
+#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
+
+static const unsigned format_byte_size_map[] = {
+    2, /* PCM_FORMAT_S16_LE */
+    4, /* PCM_FORMAT_S32_LE */
+    1, /* PCM_FORMAT_S8 */
+    4, /* PCM_FORMAT_S24_LE */
+    3, /* PCM_FORMAT_S24_3LE */
+};
+
 void proxy_prepare(alsa_device_proxy * proxy, alsa_device_profile* profile,
                    struct pcm_config * config)
 {
@@ -62,6 +72,12 @@
     }
 
     proxy->pcm = NULL;
+    // config format should be checked earlier against profile.
+    if (config->format >= 0 && (size_t)config->format < ARRAY_SIZE(format_byte_size_map)) {
+        proxy->frame_size = format_byte_size_map[config->format] * proxy->alsa_config.channels;
+    } else {
+        proxy->frame_size = 1;
+    }
 }
 
 int proxy_open(alsa_device_proxy * proxy)
@@ -74,7 +90,8 @@
         return -EINVAL;
     }
 
-    proxy->pcm = pcm_open(profile->card, profile->device, profile->direction, &proxy->alsa_config);
+    proxy->pcm = pcm_open(profile->card, profile->device,
+            profile->direction | PCM_MONOTONIC, &proxy->alsa_config);
     if (proxy->pcm == NULL) {
         return -ENOMEM;
     }
@@ -145,12 +162,41 @@
                / proxy_get_sample_rate(proxy);
 }
 
+int proxy_get_presentation_position(const alsa_device_proxy * proxy,
+        uint64_t *frames, struct timespec *timestamp)
+{
+    int ret = -EPERM; // -1
+    unsigned int avail;
+    if (proxy->pcm != NULL
+            && pcm_get_htimestamp(proxy->pcm, &avail, timestamp) == 0) {
+        const size_t kernel_buffer_size =
+                proxy->alsa_config.period_size * proxy->alsa_config.period_count;
+        if (avail > kernel_buffer_size) {
+            ALOGE("available frames(%u) > buffer size(%zu)", avail, kernel_buffer_size);
+        } else {
+            int64_t signed_frames = proxy->transferred - kernel_buffer_size + avail;
+            // It is possible to compensate for additional driver and device delay
+            // by changing signed_frames.  Example:
+            // signed_frames -= 20 /* ms */ * proxy->alsa_config.rate / 1000;
+            if (signed_frames >= 0) {
+                *frames = signed_frames;
+                ret = 0;
+            }
+        }
+    }
+    return ret;
+}
+
 /*
  * I/O
  */
-int proxy_write(const alsa_device_proxy * proxy, const void *data, unsigned int count)
+int proxy_write(alsa_device_proxy * proxy, const void *data, unsigned int count)
 {
-    return pcm_write(proxy->pcm, data, count);
+    int ret = pcm_write(proxy->pcm, data, count);
+    if (ret == 0) {
+        proxy->transferred += count / proxy->frame_size;
+    }
+    return ret;
 }
 
 int proxy_read(const alsa_device_proxy * proxy, void *data, unsigned int count)
diff --git a/alsa_utils/include/alsa_device_proxy.h b/alsa_utils/include/alsa_device_proxy.h
index add7315..e1ff8f5 100644
--- a/alsa_utils/include/alsa_device_proxy.h
+++ b/alsa_utils/include/alsa_device_proxy.h
@@ -27,6 +27,9 @@
     struct pcm_config alsa_config;
 
     struct pcm * pcm;
+
+    size_t frame_size;    /* valid after proxy_prepare(), the frame size in bytes */
+    uint64_t transferred; /* the total frames transferred, not cleared on standby */
 } alsa_device_proxy;
 
 void proxy_prepare(alsa_device_proxy * proxy, alsa_device_profile * profile,
@@ -40,10 +43,13 @@
 
 unsigned proxy_get_latency(const alsa_device_proxy * proxy);
 
+int proxy_get_presentation_position(const alsa_device_proxy * proxy,
+        uint64_t *frames, struct timespec *timestamp);
+
 int proxy_open(alsa_device_proxy * proxy);
 void proxy_close(alsa_device_proxy * proxy);
 
-int proxy_write(const alsa_device_proxy * proxy, const void *data, unsigned int count);
+int proxy_write(alsa_device_proxy * proxy, const void *data, unsigned int count);
 int proxy_read(const alsa_device_proxy * proxy, void *data, unsigned int count);
 
 #endif /* ANDROID_SYSTEM_MEDIA_ALSA_UTILS_ALSA_DEVICE_PROXY_H */