Implement HAL API get_presentation_position
This does _not_ address bug 10551158 (to include DSP buffering)
Change-Id: Ifbc5ca21c46eced3f93a891200c763a062625dd9
diff --git a/hal/audio_hw.c b/hal/audio_hw.c
index 852ddf6..404f17c 100644
--- a/hal/audio_hw.c
+++ b/hal/audio_hw.c
@@ -841,7 +841,7 @@
__func__, 0, out->pcm_device_id);
if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
out->pcm = pcm_open(SOUND_CARD, out->pcm_device_id,
- PCM_OUT, &out->config);
+ PCM_OUT | PCM_MONOTONIC, &out->config);
if (out->pcm && !pcm_is_ready(out->pcm)) {
ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
pcm_close(out->pcm);
@@ -946,7 +946,7 @@
__func__, SOUND_CARD, pcm_dev_rx_id);
adev->voice_call_rx = pcm_open(SOUND_CARD,
pcm_dev_rx_id,
- PCM_OUT, &pcm_config_voice_call);
+ PCM_OUT | PCM_MONOTONIC, &pcm_config_voice_call);
if (adev->voice_call_rx && !pcm_is_ready(adev->voice_call_rx)) {
ALOGE("%s: %s", __func__, pcm_get_error(adev->voice_call_rx));
ret = -EIO;
@@ -1305,6 +1305,8 @@
memset((void *)buffer, 0, bytes);
ALOGVV("%s: writing buffer (%d bytes) to pcm device", __func__, bytes);
ret = pcm_write(out->pcm, (void *)buffer, bytes);
+ if (ret == 0)
+ out->written += bytes / (out->config.channels * sizeof(short));
}
}
@@ -1356,6 +1358,33 @@
return -EINVAL;
}
+static int out_get_presentation_position(const struct audio_stream_out *stream,
+ uint64_t *frames, struct timespec *timestamp)
+{
+ struct stream_out *out = (struct stream_out *)stream;
+ int ret = -1;
+
+ pthread_mutex_lock(&out->lock);
+
+ if (out->pcm) {
+ size_t avail;
+ if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
+ size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
+ // FIXME This calculation is incorrect if there is buffering after app processor
+ int64_t signed_frames = out->written - kernel_buffer_size + avail;
+ // It would be unusual for this value to be negative, but check just in case ...
+ if (signed_frames >= 0) {
+ *frames = signed_frames;
+ ret = 0;
+ }
+ }
+ }
+
+ pthread_mutex_unlock(&out->lock);
+
+ return ret;
+}
+
static int out_set_callback(struct audio_stream_out *stream,
stream_callback_t callback, void *cookie)
{
@@ -1784,9 +1813,11 @@
out->stream.write = out_write;
out->stream.get_render_position = out_get_render_position;
out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
+ out->stream.get_presentation_position = out_get_presentation_position;
out->standby = 1;
/* 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);
diff --git a/hal/audio_hw.h b/hal/audio_hw.h
index b61bcd4..03f276f 100644
--- a/hal/audio_hw.h
+++ b/hal/audio_hw.h
@@ -109,6 +109,7 @@
/* Array of supported channel mask configurations. +1 so that the last entry is always 0 */
audio_channel_mask_t supported_channel_masks[MAX_SUPPORTED_CHANNEL_MASKS + 1];
bool muted;
+ uint64_t written; /* total frames written, not cleared when entering standby */
int non_blocking;
int playback_started;