Add callback for codec format change.
When creating native audio track, a IAudioTrackCallback will be created
systematically. All callbacks will be cached in Threads and protected by
a lock. Whenever there is a callback event from audio HAL, it will
finally trigger callback to native audio track. Currently, there is only
one callback event, which is codec format change.
Bug: 150301890
Test: manual
Change-Id: I32293627ed923b17dd25f11f0ee0a0c35cd7c01f
diff --git a/media/libaudiohal/impl/StreamHalHidl.cpp b/media/libaudiohal/impl/StreamHalHidl.cpp
index c08dddb..2726e36 100644
--- a/media/libaudiohal/impl/StreamHalHidl.cpp
+++ b/media/libaudiohal/impl/StreamHalHidl.cpp
@@ -299,10 +299,17 @@
if (mCallback.unsafe_get()) {
processReturn("clearCallback", mStream->clearCallback());
}
+#if MAJOR_VERSION >= 6
+ if (mEventCallback.unsafe_get() != nullptr) {
+ processReturn("setEventCallback",
+ mStream->setEventCallback(nullptr));
+ }
+#endif
processReturn("close", mStream->close());
mStream.clear();
}
mCallback.clear();
+ mEventCallback.clear();
hardware::IPCThreadState::self()->flushCommands();
if (mEfGroup) {
EventFlag::deleteEventFlag(&mEfGroup);
@@ -614,6 +621,50 @@
}
#endif
+#if MAJOR_VERSION < 6
+status_t StreamOutHalHidl::setEventCallback(
+ const sp<StreamOutHalInterfaceEventCallback>& callback __unused) {
+ // Codec format callback is supported starting from audio HAL V6.0
+ return INVALID_OPERATION;
+}
+#else
+
+#include PATH(android/hardware/audio/FILE_VERSION/IStreamOutEventCallback.h)
+
+namespace {
+
+struct StreamOutEventCallback : public IStreamOutEventCallback {
+ StreamOutEventCallback(const wp<StreamOutHalHidl>& stream) : mStream(stream) {}
+
+ // IStreamOutEventCallback implementation
+ Return<void> onCodecFormatChanged(
+ const android::hardware::hidl_vec<uint8_t>& audioMetadata) override {
+ sp<StreamOutHalHidl> stream = mStream.promote();
+ if (stream != nullptr) {
+ std::basic_string<uint8_t> metadataBs(audioMetadata.begin(), audioMetadata.end());
+ stream->onCodecFormatChanged(metadataBs);
+ }
+ return Void();
+ }
+
+ private:
+ wp<StreamOutHalHidl> mStream;
+};
+
+} // namespace
+
+status_t StreamOutHalHidl::setEventCallback(
+ const sp<StreamOutHalInterfaceEventCallback>& callback) {
+ if (mStream == nullptr) return NO_INIT;
+ mEventCallback = callback;
+ status_t status = processReturn(
+ "setEventCallback",
+ mStream->setEventCallback(
+ callback.get() == nullptr ? nullptr : new StreamOutEventCallback(this)));
+ return status;
+}
+#endif
+
void StreamOutHalHidl::onWriteReady() {
sp<StreamOutHalInterfaceCallback> callback = mCallback.promote();
if (callback == 0) return;
@@ -635,6 +686,13 @@
callback->onError();
}
+void StreamOutHalHidl::onCodecFormatChanged(const std::basic_string<uint8_t>& metadataBs) {
+ sp<StreamOutHalInterfaceEventCallback> callback = mEventCallback.promote();
+ if (callback == nullptr) return;
+ ALOGV("asyncCodecFormatCallback %s", __func__);
+ callback->onCodecFormatChanged(metadataBs);
+}
+
StreamInHalHidl::StreamInHalHidl(const sp<IStreamIn>& stream)
: StreamHalHidl(stream.get()), mStream(stream), mReaderClient(0), mEfGroup(nullptr) {
diff --git a/media/libaudiohal/impl/StreamHalHidl.h b/media/libaudiohal/impl/StreamHalHidl.h
index f587889..88f8587 100644
--- a/media/libaudiohal/impl/StreamHalHidl.h
+++ b/media/libaudiohal/impl/StreamHalHidl.h
@@ -173,6 +173,11 @@
void onDrainReady();
void onError();
+ status_t setEventCallback(const sp<StreamOutHalInterfaceEventCallback>& callback) override;
+
+ // Methods used by StreamCodecFormatCallback (HIDL).
+ void onCodecFormatChanged(const std::basic_string<uint8_t>& metadataBs);
+
private:
friend class DeviceHalHidl;
typedef MessageQueue<WriteCommand, hardware::kSynchronizedReadWrite> CommandMQ;
@@ -180,6 +185,7 @@
typedef MessageQueue<WriteStatus, hardware::kSynchronizedReadWrite> StatusMQ;
wp<StreamOutHalInterfaceCallback> mCallback;
+ wp<StreamOutHalInterfaceEventCallback> mEventCallback;
sp<IStreamOut> mStream;
std::unique_ptr<CommandMQ> mCommandMQ;
std::unique_ptr<DataMQ> mDataMQ;
diff --git a/media/libaudiohal/impl/StreamHalLocal.cpp b/media/libaudiohal/impl/StreamHalLocal.cpp
index 4818fd8..69be303 100644
--- a/media/libaudiohal/impl/StreamHalLocal.cpp
+++ b/media/libaudiohal/impl/StreamHalLocal.cpp
@@ -275,6 +275,43 @@
return mStream->get_mmap_position(mStream, position);
}
+status_t StreamOutHalLocal::setEventCallback(
+ const sp<StreamOutHalInterfaceEventCallback>& callback) {
+ if (mStream->set_event_callback == nullptr) {
+ return INVALID_OPERATION;
+ }
+ stream_event_callback_t asyncCallback =
+ callback == nullptr ? nullptr : StreamOutHalLocal::asyncEventCallback;
+ status_t result = mStream->set_event_callback(mStream, asyncCallback, this);
+ if (result == OK) {
+ mEventCallback = callback;
+ }
+ return result;
+}
+
+// static
+int StreamOutHalLocal::asyncEventCallback(
+ stream_event_callback_type_t event, void *param, void *cookie) {
+ // We act as if we gave a wp<StreamOutHalLocal> to HAL. This way we should handle
+ // correctly the case when the callback is invoked while StreamOutHalLocal's destructor is
+ // already running, because the destructor is invoked after the refcount has been atomically
+ // decremented.
+ wp<StreamOutHalLocal> weakSelf(static_cast<StreamOutHalLocal*>(cookie));
+ sp<StreamOutHalLocal> self = weakSelf.promote();
+ if (self == nullptr) return 0;
+ sp<StreamOutHalInterfaceEventCallback> callback = self->mEventCallback.promote();
+ if (callback.get() == nullptr) return 0;
+ switch (event) {
+ case STREAM_EVENT_CBK_TYPE_CODEC_FORMAT_CHANGED:
+ callback->onCodecFormatChanged(std::basic_string<uint8_t>((uint8_t*)param));
+ break;
+ default:
+ ALOGW("%s unknown event %d", __func__, event);
+ break;
+ }
+ return 0;
+}
+
StreamInHalLocal::StreamInHalLocal(audio_stream_in_t *stream, sp<DeviceHalLocal> device)
: StreamHalLocal(&stream->common, device), mStream(stream) {
}
diff --git a/media/libaudiohal/impl/StreamHalLocal.h b/media/libaudiohal/impl/StreamHalLocal.h
index 34f2bd8..d17f9f3 100644
--- a/media/libaudiohal/impl/StreamHalLocal.h
+++ b/media/libaudiohal/impl/StreamHalLocal.h
@@ -156,9 +156,12 @@
// Called when the metadata of the stream's source has been changed.
status_t updateSourceMetadata(const SourceMetadata& sourceMetadata) override;
+ status_t setEventCallback(const sp<StreamOutHalInterfaceEventCallback>& callback) override;
+
private:
audio_stream_out_t *mStream;
wp<StreamOutHalInterfaceCallback> mCallback;
+ wp<StreamOutHalInterfaceEventCallback> mEventCallback;
friend class DeviceHalLocal;
@@ -168,6 +171,8 @@
virtual ~StreamOutHalLocal();
static int asyncCallback(stream_callback_event_t event, void *param, void *cookie);
+
+ static int asyncEventCallback(stream_event_callback_type_t event, void *param, void *cookie);
};
class StreamInHalLocal : public StreamInHalInterface, public StreamHalLocal {