Merge "C2Decoder: Remove hardcoded PAGE_SIZE usage" into main
diff --git a/media/libaudiohal/impl/DeviceHalAidl.cpp b/media/libaudiohal/impl/DeviceHalAidl.cpp
index f865603..2447b18 100644
--- a/media/libaudiohal/impl/DeviceHalAidl.cpp
+++ b/media/libaudiohal/impl/DeviceHalAidl.cpp
@@ -478,15 +478,21 @@
__func__, ret.desc.toString().c_str());
return NO_INIT;
}
- *outStream = sp<StreamOutHalAidl>::make(*config, std::move(context), aidlPatch.latenciesMs[0],
+ auto stream = sp<StreamOutHalAidl>::make(*config, std::move(context), aidlPatch.latenciesMs[0],
std::move(ret.stream), mVendorExt, this /*callbackBroker*/);
- void* cbCookie = (*outStream).get();
+ *outStream = stream;
+ /* StreamOutHalInterface* */ void* cbCookie = (*outStream).get();
{
std::lock_guard l(mLock);
mCallbacks.emplace(cbCookie, Callbacks{});
mMapper.addStream(*outStream, mixPortConfig.id, aidlPatch.id);
}
- if (streamCb) streamCb->setCookie(cbCookie);
+ if (streamCb) {
+ streamCb->setCookie(cbCookie);
+ // Although StreamOutHalAidl implements StreamOutHalInterfaceCallback,
+ // we always go via the CallbackBroker for consistency.
+ setStreamOutCallback(cbCookie, stream);
+ }
eventCb->setCookie(cbCookie);
cleanups.disarmAll();
return OK;
diff --git a/media/libaudiohal/impl/StreamHalAidl.cpp b/media/libaudiohal/impl/StreamHalAidl.cpp
index ce56d87..3fd0911 100644
--- a/media/libaudiohal/impl/StreamHalAidl.cpp
+++ b/media/libaudiohal/impl/StreamHalAidl.cpp
@@ -82,7 +82,12 @@
mConfig(configToBase(config)),
mContext(std::move(context)),
mStream(stream),
- mVendorExt(vext) {
+ mVendorExt(vext),
+ mLastReplyLifeTimeNs(
+ std::min(static_cast<size_t>(100),
+ 2 * mContext.getBufferDurationMs(mConfig.sample_rate))
+ * NANOS_PER_MILLISECOND)
+{
ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
{
std::lock_guard l(mLock);
@@ -285,8 +290,7 @@
ALOGV("%p %s::%s", this, getClassName().c_str(), __func__);
if (!mStream) return NO_INIT;
StreamDescriptor::Reply reply;
- // TODO: switch to updateCountersIfNeeded once we sort out mWorkerTid initialization
- RETURN_STATUS_IF_ERROR(sendCommand(makeHalCommand<HalCommand::Tag::getStatus>(), &reply, true));
+ RETURN_STATUS_IF_ERROR(updateCountersIfNeeded(&reply));
*frames = std::max<int64_t>(0, reply.hardware.frames);
*timestamp = std::max<int64_t>(0, reply.hardware.timeNs);
return OK;
@@ -409,6 +413,37 @@
return statusTFromBinderStatus(mStream->prepareToClose());
}
+void StreamHalAidl::onAsyncTransferReady() {
+ if (auto state = getState(); state == StreamDescriptor::State::TRANSFERRING) {
+ // Retrieve the current state together with position counters.
+ updateCountersIfNeeded();
+ } else {
+ ALOGW("%s: unexpected onTransferReady in the state %s", __func__, toString(state).c_str());
+ }
+}
+
+void StreamHalAidl::onAsyncDrainReady() {
+ if (auto state = getState(); state == StreamDescriptor::State::DRAINING) {
+ // Retrieve the current state together with position counters.
+ updateCountersIfNeeded();
+ } else {
+ ALOGW("%s: unexpected onDrainReady in the state %s", __func__, toString(state).c_str());
+ }
+}
+
+void StreamHalAidl::onAsyncError() {
+ std::lock_guard l(mLock);
+ if (mLastReply.state == StreamDescriptor::State::IDLE ||
+ mLastReply.state == StreamDescriptor::State::DRAINING ||
+ mLastReply.state == StreamDescriptor::State::TRANSFERRING) {
+ mLastReply.state = StreamDescriptor::State::ERROR;
+ ALOGW("%s: onError received", __func__);
+ } else {
+ ALOGW("%s: unexpected onError in the state %s", __func__,
+ toString(mLastReply.state).c_str());
+ }
+}
+
status_t StreamHalAidl::createMmapBuffer(int32_t minSizeFrames __unused,
struct audio_mmap_buffer_info *info) {
ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
@@ -487,6 +522,7 @@
reply->latencyMs = mLastReply.latencyMs;
}
mLastReply = *reply;
+ mLastReplyExpirationNs = uptimeNanos() + mLastReplyLifeTimeNs;
}
switch (reply->status) {
case STATUS_OK: return OK;
@@ -502,14 +538,17 @@
status_t StreamHalAidl::updateCountersIfNeeded(
::aidl::android::hardware::audio::core::StreamDescriptor::Reply* reply) {
- if (mWorkerTid.load(std::memory_order_acquire) == gettid()) {
- if (const auto state = getState(); state != StreamDescriptor::State::ACTIVE &&
- state != StreamDescriptor::State::DRAINING &&
- state != StreamDescriptor::State::TRANSFERRING) {
- return sendCommand(makeHalCommand<HalCommand::Tag::getStatus>(), reply);
- }
+ bool doUpdate = false;
+ {
+ std::lock_guard l(mLock);
+ doUpdate = uptimeNanos() > mLastReplyExpirationNs;
}
- if (reply != nullptr) {
+ if (doUpdate) {
+ // Since updates are paced, it is OK to perform them from any thread, they should
+ // not interfere with I/O operations of the worker.
+ return sendCommand(makeHalCommand<HalCommand::Tag::getStatus>(),
+ reply, true /*safeFromNonWorkerThread */);
+ } else if (reply != nullptr) { // provide cached reply
std::lock_guard l(mLock);
*reply = mLastReply;
}
@@ -545,7 +584,7 @@
StreamOutHalAidl::~StreamOutHalAidl() {
if (auto broker = mCallbackBroker.promote(); broker != nullptr) {
- broker->clearCallbacks(this);
+ broker->clearCallbacks(static_cast<StreamOutHalInterface*>(this));
}
}
@@ -614,21 +653,14 @@
}
status_t StreamOutHalAidl::setCallback(wp<StreamOutHalInterfaceCallback> callback) {
+ ALOGD("%p %s", this, __func__);
TIME_CHECK();
if (!mStream) return NO_INIT;
if (!mContext.isAsynchronous()) {
ALOGE("%s: the callback is intended for asynchronous streams only", __func__);
return INVALID_OPERATION;
}
- if (auto broker = mCallbackBroker.promote(); broker != nullptr) {
- if (auto cb = callback.promote(); cb != nullptr) {
- broker->setStreamOutCallback(this, cb);
- } else {
- // It is expected that the framework never passes a null pointer.
- // In the AIDL model callbacks can't be "unregistered".
- LOG_ALWAYS_FATAL("%s: received an expired or null callback pointer", __func__);
- }
- }
+ mClientCallback = callback;
return OK;
}
@@ -751,7 +783,7 @@
TIME_CHECK();
if (!mStream) return NO_INIT;
if (auto broker = mCallbackBroker.promote(); broker != nullptr) {
- broker->setStreamOutEventCallback(this, callback);
+ broker->setStreamOutEventCallback(static_cast<StreamOutHalInterface*>(this), callback);
}
return OK;
}
@@ -785,7 +817,8 @@
TIME_CHECK();
if (!mStream) return NO_INIT;
if (auto broker = mCallbackBroker.promote(); broker != nullptr) {
- broker->setStreamOutLatencyModeCallback(this, callback);
+ broker->setStreamOutLatencyModeCallback(
+ static_cast<StreamOutHalInterface*>(this), callback);
}
return OK;
};
@@ -794,6 +827,27 @@
return StreamHalAidl::exit();
}
+void StreamOutHalAidl::onWriteReady() {
+ onAsyncTransferReady();
+ if (auto clientCb = mClientCallback.load().promote(); clientCb != nullptr) {
+ clientCb->onWriteReady();
+ }
+}
+
+void StreamOutHalAidl::onDrainReady() {
+ onAsyncDrainReady();
+ if (auto clientCb = mClientCallback.load().promote(); clientCb != nullptr) {
+ clientCb->onDrainReady();
+ }
+}
+
+void StreamOutHalAidl::onError() {
+ onAsyncError();
+ if (auto clientCb = mClientCallback.load().promote(); clientCb != nullptr) {
+ clientCb->onError();
+ }
+}
+
status_t StreamOutHalAidl::filterAndUpdateOffloadMetadata(AudioParameter ¶meters) {
TIME_CHECK();
bool updateMetadata = false;
diff --git a/media/libaudiohal/impl/StreamHalAidl.h b/media/libaudiohal/impl/StreamHalAidl.h
index 4acc6ac..53d46e5 100644
--- a/media/libaudiohal/impl/StreamHalAidl.h
+++ b/media/libaudiohal/impl/StreamHalAidl.h
@@ -32,6 +32,7 @@
#include <media/audiohal/StreamHalInterface.h>
#include <media/AidlConversionUtil.h>
#include <media/AudioParameter.h>
+#include <mediautils/Synchronization.h>
#include "ConversionHelperAidl.h"
#include "StreamPowerLog.h"
@@ -93,6 +94,9 @@
}
size_t getBufferSizeBytes() const { return mFrameSizeBytes * mBufferSizeFrames; }
size_t getBufferSizeFrames() const { return mBufferSizeFrames; }
+ size_t getBufferDurationMs(int32_t sampleRate) const {
+ return sampleRate != 0 ? mBufferSizeFrames * MILLIS_PER_SECOND / sampleRate : 0;
+ }
CommandMQ* getCommandMQ() const { return mCommandMQ.get(); }
DataMQ* getDataMQ() const { return mDataMQ.get(); }
size_t getFrameSizeBytes() const { return mFrameSizeBytes; }
@@ -232,6 +236,10 @@
status_t exit();
+ void onAsyncTransferReady();
+ void onAsyncDrainReady();
+ void onAsyncError();
+
const bool mIsInput;
const audio_config_base_t mConfig;
const StreamContextAidl mContext;
@@ -257,8 +265,10 @@
const std::shared_ptr<::aidl::android::hardware::audio::core::IStreamCommon> mStream;
const std::shared_ptr<::aidl::android::media::audio::IHalAdapterVendorExtension> mVendorExt;
+ const int64_t mLastReplyLifeTimeNs;
std::mutex mLock;
::aidl::android::hardware::audio::core::StreamDescriptor::Reply mLastReply GUARDED_BY(mLock);
+ int64_t mLastReplyExpirationNs GUARDED_BY(mLock) = 0;
// mStreamPowerLog is used for audio signal power logging.
StreamPowerLog mStreamPowerLog;
std::atomic<pid_t> mWorkerTid = -1;
@@ -266,7 +276,9 @@
class CallbackBroker;
-class StreamOutHalAidl : public StreamOutHalInterface, public StreamHalAidl {
+class StreamOutHalAidl : public virtual StreamOutHalInterface,
+ public virtual StreamOutHalInterfaceCallback,
+ public StreamHalAidl {
public:
// Extract the output stream parameters and set by AIDL APIs.
status_t setParameters(const String8& kvPairs) override;
@@ -344,6 +356,11 @@
status_t exit() override;
+ // StreamOutHalInterfaceCallback
+ void onWriteReady() override;
+ void onDrainReady() override;
+ void onError() override;
+
private:
friend class sp<StreamOutHalAidl>;
@@ -352,6 +369,7 @@
const std::shared_ptr<::aidl::android::hardware::audio::core::IStreamOut> mStream;
const wp<CallbackBroker> mCallbackBroker;
+ mediautils::atomic_wp<StreamOutHalInterfaceCallback> mClientCallback;
AudioOffloadMetadata mOffloadMetadata;