summaryrefslogtreecommitdiffstats
path: root/hal
diff options
context:
space:
mode:
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: