audio: Propagate fatal error during offload to AF
Use offload callback thread to propagate fatal error
back to AF. AF can take action (invalidating tracks,
putting stream to standby) accordingly
Bug: 30075678
Change-Id: I426d6a7ff2a49cca7864ebea2c6be500bdb751b9
diff --git a/hal/audio_hw.c b/hal/audio_hw.c
index 1e185e5..e4cd2b9 100644
--- a/hal/audio_hw.c
+++ b/hal/audio_hw.c
@@ -1228,6 +1228,10 @@
send_callback = true;
event = STREAM_CBK_EVENT_DRAIN_READY;
break;
+ case OFFLOAD_CMD_ERROR:
+ send_callback = true;
+ event = STREAM_CBK_EVENT_ERROR;
+ break;
default:
ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
break;
@@ -1653,6 +1657,28 @@
return 0;
}
+static int out_on_error(struct audio_stream *stream)
+{
+ struct stream_out *out = (struct stream_out *)stream;
+ struct audio_device *adev = out->dev;
+ bool do_standby = false;
+
+ lock_output_stream(out);
+ if (!out->standby) {
+ if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
+ stop_compressed_output_l(out);
+ send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
+ } else
+ do_standby = true;
+ }
+ pthread_mutex_unlock(&out->lock);
+
+ if (do_standby)
+ return out_standby(&out->stream.common);
+
+ return 0;
+}
+
static int out_dump(const struct audio_stream *stream __unused, int fd __unused)
{
return 0;
@@ -1906,20 +1932,17 @@
if (!valid_cb)
return;
- ALOGV("out_snd_mon_cb for card %d usecase %s", card,
- use_case_table[out->usecase]);
-
lock_output_stream(out);
if (out->card_status != status)
out->card_status = status;
pthread_mutex_unlock(&out->lock);
- // a better solution would be to report error back to AF and let
- // it put the stream to standby
- if (status == CARD_STATUS_OFFLINE) {
- ALOGW("new state == offline, move stream to standby");
- out_standby(&out->stream.common);
- }
+ ALOGW("out_snd_mon_cb for card %d usecase %s, status %s", card,
+ use_case_table[out->usecase],
+ status == CARD_STATUS_OFFLINE ? "offline" : "online");
+
+ if (status == CARD_STATUS_OFFLINE)
+ out_on_error(stream);
return;
}
@@ -2024,11 +2047,12 @@
pthread_mutex_unlock(&out->lock);
if (ret != 0) {
+ out_on_error(&out->stream.common);
if (out->pcm)
ALOGE("%s: error %zu - %s", __func__, ret, pcm_get_error(out->pcm));
- out_standby(&out->stream.common);
- usleep(bytes * 1000000 / audio_stream_out_frame_size(stream) /
- out_get_sample_rate(&out->stream.common));
+ if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD)
+ usleep(bytes * 1000000 / audio_stream_out_frame_size(stream) /
+ out_get_sample_rate(&out->stream.common));
}
return bytes;
}
diff --git a/hal/audio_hw.h b/hal/audio_hw.h
index 55c3be4..5ce3018 100644
--- a/hal/audio_hw.h
+++ b/hal/audio_hw.h
@@ -133,6 +133,7 @@
OFFLOAD_CMD_DRAIN, /* send a full drain request to DSP */
OFFLOAD_CMD_PARTIAL_DRAIN, /* send a partial drain request to DSP */
OFFLOAD_CMD_WAIT_FOR_BUFFER, /* wait for buffer released by DSP */
+ OFFLOAD_CMD_ERROR, /* offload playback hit some error */
};
enum {