summaryrefslogtreecommitdiffstats
path: root/hal
diff options
context:
space:
mode:
authorNikolay Martyanov <nikolay.martyanov@opensynergy.com>2020-09-14 12:10:39 +0200
committerNikolay Martyanov <nikolay.martyanov@opensynergy.com>2020-09-17 14:55:30 +0200
commitb51d63ef1f1bfab616cd8946cfeba29643c38531 (patch)
treeacb7a3a88766183f12242caba20ceda79ee97ecb /hal
parentc330f6e26466b470e6ce6d4776a30fabdf849827 (diff)
downloaddevice_google_trout-b51d63ef1f1bfab616cd8946cfeba29643c38531.tar.gz
device_google_trout-b51d63ef1f1bfab616cd8946cfeba29643c38531.tar.bz2
device_google_trout-b51d63ef1f1bfab616cd8946cfeba29643c38531.zip
Audio HAL: Wait for available frames for the input stream.
Audio HAL in_read function does not wait for all required frames. And if there's not enough frames to fill application's input buffer, HAL just silences the rest. This patch adds polling for the required number of frames for the input stream. Bug: 167390806 Test: Build, boot, play an audio file Change-Id: I162672feba7414c7f93c9c3bf9493cacb4ce367a
Diffstat (limited to 'hal')
-rw-r--r--hal/audio/6.0/audio_hw.c39
1 files changed, 36 insertions, 3 deletions
diff --git a/hal/audio/6.0/audio_hw.c b/hal/audio/6.0/audio_hw.c
index 09ed827..317d77e 100644
--- a/hal/audio/6.0/audio_hw.c
+++ b/hal/audio/6.0/audio_hw.c
@@ -61,6 +61,11 @@
// Max tone frequency to auto assign, don't want to generate too high of a pitch
#define MAX_TONE_FREQUENCY 500
+// The average interval with which notifications come from the device (1 ms or 1000 us)
+#define NOTIFICATION_AVR_INTERVAL_US 1000
+// The amount of times we try to read a notification from the device
+#define MAX_READ_ATTEMPTS 100
+
#define _bool_str(x) ((x)?"true":"false")
static const char * const PROP_KEY_SIMULATE_MULTI_ZONE_AUDIO = "ro.aae.simulateMultiZoneAudio";
@@ -899,6 +904,25 @@ static bool is_tone_generator_device(struct generic_stream_in *in) {
address_has_tone_keyword(in->bus_address));
}
+static size_t read_frames_from_stream(void* dst, struct generic_stream_in* in, size_t frames_cnt) {
+ size_t frames_read = 0;
+ void *cur_dst = NULL;
+ audio_vbuffer_t *src = &in->buffer;
+ size_t frame_size = in->buffer.frame_size;
+ for (int attempt = 0; attempt < MAX_READ_ATTEMPTS; attempt++) {
+ cur_dst = &((uint8_t *)dst)[frames_read * frame_size];
+ frames_read += audio_vbuffer_read(src, cur_dst, frames_cnt - frames_read);
+ if (frames_read == frames_cnt)
+ break;
+ // The next notification from the device informs about new available frames.
+ // Wait for a time of the order of one notification interval.
+ pthread_mutex_unlock(&in->lock);
+ usleep(NOTIFICATION_AVR_INTERVAL_US / 2);
+ pthread_mutex_lock(&in->lock);
+ }
+ return frames_read;
+}
+
static ssize_t in_read(struct audio_stream_in *stream, void *buffer, size_t bytes) {
struct generic_stream_in *in = (struct generic_stream_in *)stream;
struct generic_audio_device *adev = in->dev;
@@ -945,7 +969,7 @@ static ssize_t in_read(struct audio_stream_in *stream, void *buffer, size_t byte
}
pthread_mutex_lock(&in->lock);
- int read_frames = 0;
+ size_t read_frames = 0;
if (in->standby) {
ALOGW("Input put to sleep while read in progress");
goto exit;
@@ -966,7 +990,12 @@ static ssize_t in_read(struct audio_stream_in *stream, void *buffer, size_t byte
}
}
- read_frames = audio_vbuffer_read(&in->buffer, in->stereo_to_mono_buf, frames);
+ read_frames = read_frames_from_stream(in->stereo_to_mono_buf, in, frames);
+ if (read_frames != frames) {
+ ALOGE("Failed to read all the frames! Is the device dead?");
+ goto exit;
+ }
+
// Currently only pcm 16 is supported.
uint16_t *src = (uint16_t *)in->stereo_to_mono_buf;
@@ -980,7 +1009,11 @@ static ssize_t in_read(struct audio_stream_in *stream, void *buffer, size_t byte
dst += 1;
}
} else {
- read_frames = audio_vbuffer_read(&in->buffer, buffer, frames);
+ read_frames = read_frames_from_stream(buffer, in, frames);
+ if (read_frames != frames) {
+ ALOGE("Failed to read all the frames! Is the device dead?");
+ goto exit;
+ }
}
exit: