audio: Fix out_get_presentation_position for ULL/MMAP streams
Fix the implementation of out_get_presentation_position
for ULL and MMAP streams taking into account their
data flow model
CRs-Fixed: 2108310
Change-Id: I9123178e000ac33304d9a93e617798471f8a95cd
diff --git a/hal/audio_hw.c b/hal/audio_hw.c
index 6097028..c1706c8 100644
--- a/hal/audio_hw.c
+++ b/hal/audio_hw.c
@@ -2992,7 +2992,7 @@
flags |= PCM_MMAP | PCM_NOIRQ;
pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
} else if (out->realtime) {
- flags |= PCM_MMAP | PCM_NOIRQ;
+ flags |= PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC;
} else
flags |= PCM_MONOTONIC;
@@ -4584,27 +4584,43 @@
clock_gettime(CLOCK_MONOTONIC, timestamp);
} else {
if (out->pcm) {
- unsigned int avail;
- if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
- size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
- int64_t signed_frames = out->written - kernel_buffer_size + avail;
- // This adjustment accounts for buffering after app processor.
- // It is based on estimated DSP latency per use case, rather than exact.
+ int64_t signed_frames = -1;
+ // XXX it might be better to identify these
+ // as realtime usecases?
+ if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP ||
+ out->usecase == USECASE_AUDIO_PLAYBACK_ULL) {
+ unsigned int hw_ptr;
+ if (pcm_mmap_get_hw_ptr(out->pcm, &hw_ptr, timestamp) == 0) {
+ signed_frames = hw_ptr;
+ }
+ ALOGV("%s frames %lld", __func__, (long long)signed_frames);
+ } else {
+ unsigned int avail;
+ if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
+ size_t kernel_buffer_size =
+ out->config.period_size * out->config.period_count;
+ signed_frames =
+ out->written - kernel_buffer_size + avail;
+ }
+ }
+
+ // This adjustment accounts for buffering after app processor.
+ // It is based on estimated DSP latency per use case, rather than exact.
+ signed_frames -=
+ (platform_render_latency(out->usecase) *
+ out->sample_rate / 1000000LL);
+
+ // Adjustment accounts for A2dp encoder latency with non offload usecases
+ // Note: Encoder latency is returned in ms, while platform_render_latency in us.
+ if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
signed_frames -=
- (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
-
- // Adjustment accounts for A2dp encoder latency with non offload usecases
- // Note: Encoder latency is returned in ms, while platform_render_latency in us.
- if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
- signed_frames -=
(audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
- }
+ }
- // It would be unusual for this value to be negative, but check just in case ...
- if (signed_frames >= 0) {
- *frames = signed_frames;
- ret = 0;
- }
+ // It would be unusual for this value to be negative, but check just in case ...
+ if (signed_frames >= 0) {
+ *frames = signed_frames;
+ ret = 0;
}
} else if (out->card_status == CARD_STATUS_OFFLINE) {
*frames = out->written;
@@ -4883,6 +4899,7 @@
return -EINVAL;
}
if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP) {
+ ALOGE("%s: called on %s", __func__, use_case_table[out->usecase]);
return -ENOSYS;
}
if (out->pcm == NULL) {