audio: Move frame counter to StreamContext
Moving frame counter to the StreamContext class enables
switching stream drivers on the fly while keeping the frame
count monotonically increasing.
StreamWorkerCommonLogic now holds a pointer to StreamContext,
which makes redundant storing copies of the fields of the latter.
Bug: 264712385
Test: atest VtsHalAudioCoreTargetTest
Change-Id: If6716f4051c484b52927cbfe4032df7c907eb3a5
(cherry picked from commit 1eedc130e8
)
Merged-In: If6716f4051c484b52927cbfe4032df7c907eb3a5
This commit is contained in:
parent
2e3b3e4c17
commit
a5e3154024
10 changed files with 93 additions and 89 deletions
|
@ -91,17 +91,18 @@ void StreamContext::reset() {
|
|||
}
|
||||
|
||||
std::string StreamWorkerCommonLogic::init() {
|
||||
if (mCommandMQ == nullptr) return "Command MQ is null";
|
||||
if (mReplyMQ == nullptr) return "Reply MQ is null";
|
||||
if (mDataMQ == nullptr) return "Data MQ is null";
|
||||
if (sizeof(DataBufferElement) != mDataMQ->getQuantumSize()) {
|
||||
return "Unexpected Data MQ quantum size: " + std::to_string(mDataMQ->getQuantumSize());
|
||||
if (mContext->getCommandMQ() == nullptr) return "Command MQ is null";
|
||||
if (mContext->getReplyMQ() == nullptr) return "Reply MQ is null";
|
||||
StreamContext::DataMQ* const dataMQ = mContext->getDataMQ();
|
||||
if (dataMQ == nullptr) return "Data MQ is null";
|
||||
if (sizeof(DataBufferElement) != dataMQ->getQuantumSize()) {
|
||||
return "Unexpected Data MQ quantum size: " + std::to_string(dataMQ->getQuantumSize());
|
||||
}
|
||||
mDataBufferSize = mDataMQ->getQuantumCount() * mDataMQ->getQuantumSize();
|
||||
mDataBufferSize = dataMQ->getQuantumCount() * dataMQ->getQuantumSize();
|
||||
mDataBuffer.reset(new (std::nothrow) DataBufferElement[mDataBufferSize]);
|
||||
if (mDataBuffer == nullptr) {
|
||||
return "Failed to allocate data buffer for element count " +
|
||||
std::to_string(mDataMQ->getQuantumCount()) +
|
||||
std::to_string(dataMQ->getQuantumCount()) +
|
||||
", size in bytes: " + std::to_string(mDataBufferSize);
|
||||
}
|
||||
if (::android::status_t status = mDriver->init(); status != STATUS_OK) {
|
||||
|
@ -114,7 +115,7 @@ void StreamWorkerCommonLogic::populateReply(StreamDescriptor::Reply* reply,
|
|||
bool isConnected) const {
|
||||
reply->status = STATUS_OK;
|
||||
if (isConnected) {
|
||||
reply->observable.frames = mFrameCount;
|
||||
reply->observable.frames = mContext->getFrameCount();
|
||||
reply->observable.timeNs = ::android::elapsedRealtimeNano();
|
||||
if (auto status = mDriver->getPosition(&reply->observable); status == ::android::OK) {
|
||||
return;
|
||||
|
@ -141,7 +142,7 @@ StreamInWorkerLogic::Status StreamInWorkerLogic::cycle() {
|
|||
// TODO: Add a delay for transitions of async operations when/if they added.
|
||||
|
||||
StreamDescriptor::Command command{};
|
||||
if (!mCommandMQ->readBlocking(&command, 1)) {
|
||||
if (!mContext->getCommandMQ()->readBlocking(&command, 1)) {
|
||||
LOG(ERROR) << __func__ << ": reading of command from MQ failed";
|
||||
mState = StreamDescriptor::State::ERROR;
|
||||
return Status::ABORT;
|
||||
|
@ -159,7 +160,7 @@ StreamInWorkerLogic::Status StreamInWorkerLogic::cycle() {
|
|||
switch (command.getTag()) {
|
||||
case Tag::halReservedExit:
|
||||
if (const int32_t cookie = command.get<Tag::halReservedExit>();
|
||||
cookie == mInternalCommandCookie) {
|
||||
cookie == mContext->getInternalCommandCookie()) {
|
||||
mDriver->shutdown();
|
||||
setClosed();
|
||||
// This is an internal command, no need to reply.
|
||||
|
@ -277,7 +278,7 @@ StreamInWorkerLogic::Status StreamInWorkerLogic::cycle() {
|
|||
}
|
||||
reply.state = mState;
|
||||
LOG(severity) << __func__ << ": writing reply " << reply.toString();
|
||||
if (!mReplyMQ->writeBlocking(&reply, 1)) {
|
||||
if (!mContext->getReplyMQ()->writeBlocking(&reply, 1)) {
|
||||
LOG(ERROR) << __func__ << ": writing of reply " << reply.toString() << " to MQ failed";
|
||||
mState = StreamDescriptor::State::ERROR;
|
||||
return Status::ABORT;
|
||||
|
@ -286,14 +287,16 @@ StreamInWorkerLogic::Status StreamInWorkerLogic::cycle() {
|
|||
}
|
||||
|
||||
bool StreamInWorkerLogic::read(size_t clientSize, StreamDescriptor::Reply* reply) {
|
||||
const size_t byteCount = std::min({clientSize, mDataMQ->availableToWrite(), mDataBufferSize});
|
||||
StreamContext::DataMQ* const dataMQ = mContext->getDataMQ();
|
||||
const size_t byteCount = std::min({clientSize, dataMQ->availableToWrite(), mDataBufferSize});
|
||||
const bool isConnected = mIsConnected;
|
||||
const size_t frameSize = mContext->getFrameSize();
|
||||
size_t actualFrameCount = 0;
|
||||
bool fatal = false;
|
||||
int32_t latency = Module::kLatencyMs;
|
||||
if (isConnected) {
|
||||
if (::android::status_t status = mDriver->transfer(
|
||||
mDataBuffer.get(), byteCount / mFrameSize, &actualFrameCount, &latency);
|
||||
if (::android::status_t status = mDriver->transfer(mDataBuffer.get(), byteCount / frameSize,
|
||||
&actualFrameCount, &latency);
|
||||
status != ::android::OK) {
|
||||
fatal = true;
|
||||
LOG(ERROR) << __func__ << ": read failed: " << status;
|
||||
|
@ -301,17 +304,16 @@ bool StreamInWorkerLogic::read(size_t clientSize, StreamDescriptor::Reply* reply
|
|||
} else {
|
||||
usleep(3000); // Simulate blocking transfer delay.
|
||||
for (size_t i = 0; i < byteCount; ++i) mDataBuffer[i] = 0;
|
||||
actualFrameCount = byteCount / mFrameSize;
|
||||
actualFrameCount = byteCount / frameSize;
|
||||
}
|
||||
const size_t actualByteCount = actualFrameCount * mFrameSize;
|
||||
if (bool success =
|
||||
actualByteCount > 0 ? mDataMQ->write(&mDataBuffer[0], actualByteCount) : true;
|
||||
const size_t actualByteCount = actualFrameCount * frameSize;
|
||||
if (bool success = actualByteCount > 0 ? dataMQ->write(&mDataBuffer[0], actualByteCount) : true;
|
||||
success) {
|
||||
LOG(VERBOSE) << __func__ << ": writing of " << actualByteCount << " bytes into data MQ"
|
||||
<< " succeeded; connected? " << isConnected;
|
||||
// Frames are provided and counted regardless of connection status.
|
||||
reply->fmqByteCount += actualByteCount;
|
||||
mFrameCount += actualFrameCount;
|
||||
mContext->advanceFrameCount(actualFrameCount);
|
||||
populateReply(reply, isConnected);
|
||||
} else {
|
||||
LOG(WARNING) << __func__ << ": writing of " << actualByteCount
|
||||
|
@ -330,7 +332,8 @@ StreamOutWorkerLogic::Status StreamOutWorkerLogic::cycle() {
|
|||
if (auto stateDurationMs = std::chrono::duration_cast<std::chrono::milliseconds>(
|
||||
std::chrono::steady_clock::now() - mTransientStateStart);
|
||||
stateDurationMs >= mTransientStateDelayMs) {
|
||||
if (mAsyncCallback == nullptr) {
|
||||
std::shared_ptr<IStreamCallback> asyncCallback = mContext->getAsyncCallback();
|
||||
if (asyncCallback == nullptr) {
|
||||
// In blocking mode, mState can only be DRAINING.
|
||||
mState = StreamDescriptor::State::IDLE;
|
||||
} else {
|
||||
|
@ -338,13 +341,13 @@ StreamOutWorkerLogic::Status StreamOutWorkerLogic::cycle() {
|
|||
// drain or transfer completion. In the stub, we switch unconditionally.
|
||||
if (mState == StreamDescriptor::State::DRAINING) {
|
||||
mState = StreamDescriptor::State::IDLE;
|
||||
ndk::ScopedAStatus status = mAsyncCallback->onDrainReady();
|
||||
ndk::ScopedAStatus status = asyncCallback->onDrainReady();
|
||||
if (!status.isOk()) {
|
||||
LOG(ERROR) << __func__ << ": error from onDrainReady: " << status;
|
||||
}
|
||||
} else {
|
||||
mState = StreamDescriptor::State::ACTIVE;
|
||||
ndk::ScopedAStatus status = mAsyncCallback->onTransferReady();
|
||||
ndk::ScopedAStatus status = asyncCallback->onTransferReady();
|
||||
if (!status.isOk()) {
|
||||
LOG(ERROR) << __func__ << ": error from onTransferReady: " << status;
|
||||
}
|
||||
|
@ -358,7 +361,7 @@ StreamOutWorkerLogic::Status StreamOutWorkerLogic::cycle() {
|
|||
}
|
||||
|
||||
StreamDescriptor::Command command{};
|
||||
if (!mCommandMQ->readBlocking(&command, 1)) {
|
||||
if (!mContext->getCommandMQ()->readBlocking(&command, 1)) {
|
||||
LOG(ERROR) << __func__ << ": reading of command from MQ failed";
|
||||
mState = StreamDescriptor::State::ERROR;
|
||||
return Status::ABORT;
|
||||
|
@ -377,7 +380,7 @@ StreamOutWorkerLogic::Status StreamOutWorkerLogic::cycle() {
|
|||
switch (command.getTag()) {
|
||||
case Tag::halReservedExit:
|
||||
if (const int32_t cookie = command.get<Tag::halReservedExit>();
|
||||
cookie == mInternalCommandCookie) {
|
||||
cookie == mContext->getInternalCommandCookie()) {
|
||||
mDriver->shutdown();
|
||||
setClosed();
|
||||
// This is an internal command, no need to reply.
|
||||
|
@ -432,10 +435,11 @@ StreamOutWorkerLogic::Status StreamOutWorkerLogic::cycle() {
|
|||
if (!write(fmqByteCount, &reply)) {
|
||||
mState = StreamDescriptor::State::ERROR;
|
||||
}
|
||||
std::shared_ptr<IStreamCallback> asyncCallback = mContext->getAsyncCallback();
|
||||
if (mState == StreamDescriptor::State::STANDBY ||
|
||||
mState == StreamDescriptor::State::DRAIN_PAUSED ||
|
||||
mState == StreamDescriptor::State::PAUSED) {
|
||||
if (mAsyncCallback == nullptr ||
|
||||
if (asyncCallback == nullptr ||
|
||||
mState != StreamDescriptor::State::DRAIN_PAUSED) {
|
||||
mState = StreamDescriptor::State::PAUSED;
|
||||
} else {
|
||||
|
@ -444,7 +448,7 @@ StreamOutWorkerLogic::Status StreamOutWorkerLogic::cycle() {
|
|||
} else if (mState == StreamDescriptor::State::IDLE ||
|
||||
mState == StreamDescriptor::State::DRAINING ||
|
||||
mState == StreamDescriptor::State::ACTIVE) {
|
||||
if (mAsyncCallback == nullptr || reply.fmqByteCount == fmqByteCount) {
|
||||
if (asyncCallback == nullptr || reply.fmqByteCount == fmqByteCount) {
|
||||
mState = StreamDescriptor::State::ACTIVE;
|
||||
} else {
|
||||
switchToTransientState(StreamDescriptor::State::TRANSFERRING);
|
||||
|
@ -466,7 +470,8 @@ StreamOutWorkerLogic::Status StreamOutWorkerLogic::cycle() {
|
|||
if (::android::status_t status = mDriver->drain(mode);
|
||||
status == ::android::OK) {
|
||||
populateReply(&reply, mIsConnected);
|
||||
if (mState == StreamDescriptor::State::ACTIVE && mForceSynchronousDrain) {
|
||||
if (mState == StreamDescriptor::State::ACTIVE &&
|
||||
mContext->getForceSynchronousDrain()) {
|
||||
mState = StreamDescriptor::State::IDLE;
|
||||
} else {
|
||||
switchToTransientState(StreamDescriptor::State::DRAINING);
|
||||
|
@ -541,7 +546,7 @@ StreamOutWorkerLogic::Status StreamOutWorkerLogic::cycle() {
|
|||
}
|
||||
reply.state = mState;
|
||||
LOG(severity) << __func__ << ": writing reply " << reply.toString();
|
||||
if (!mReplyMQ->writeBlocking(&reply, 1)) {
|
||||
if (!mContext->getReplyMQ()->writeBlocking(&reply, 1)) {
|
||||
LOG(ERROR) << __func__ << ": writing of reply " << reply.toString() << " to MQ failed";
|
||||
mState = StreamDescriptor::State::ERROR;
|
||||
return Status::ABORT;
|
||||
|
@ -550,38 +555,40 @@ StreamOutWorkerLogic::Status StreamOutWorkerLogic::cycle() {
|
|||
}
|
||||
|
||||
bool StreamOutWorkerLogic::write(size_t clientSize, StreamDescriptor::Reply* reply) {
|
||||
const size_t readByteCount = mDataMQ->availableToRead();
|
||||
StreamContext::DataMQ* const dataMQ = mContext->getDataMQ();
|
||||
const size_t readByteCount = dataMQ->availableToRead();
|
||||
const size_t frameSize = mContext->getFrameSize();
|
||||
bool fatal = false;
|
||||
int32_t latency = Module::kLatencyMs;
|
||||
if (bool success = readByteCount > 0 ? mDataMQ->read(&mDataBuffer[0], readByteCount) : true) {
|
||||
if (bool success = readByteCount > 0 ? dataMQ->read(&mDataBuffer[0], readByteCount) : true) {
|
||||
const bool isConnected = mIsConnected;
|
||||
LOG(VERBOSE) << __func__ << ": reading of " << readByteCount << " bytes from data MQ"
|
||||
<< " succeeded; connected? " << isConnected;
|
||||
// Amount of data that the HAL module is going to actually use.
|
||||
size_t byteCount = std::min({clientSize, readByteCount, mDataBufferSize});
|
||||
if (byteCount >= mFrameSize && mForceTransientBurst) {
|
||||
if (byteCount >= frameSize && mContext->getForceTransientBurst()) {
|
||||
// In order to prevent the state machine from going to ACTIVE state,
|
||||
// simulate partial write.
|
||||
byteCount -= mFrameSize;
|
||||
byteCount -= frameSize;
|
||||
}
|
||||
size_t actualFrameCount = 0;
|
||||
if (isConnected) {
|
||||
if (::android::status_t status = mDriver->transfer(
|
||||
mDataBuffer.get(), byteCount / mFrameSize, &actualFrameCount, &latency);
|
||||
mDataBuffer.get(), byteCount / frameSize, &actualFrameCount, &latency);
|
||||
status != ::android::OK) {
|
||||
fatal = true;
|
||||
LOG(ERROR) << __func__ << ": write failed: " << status;
|
||||
}
|
||||
} else {
|
||||
if (mAsyncCallback == nullptr) {
|
||||
if (mContext->getAsyncCallback() == nullptr) {
|
||||
usleep(3000); // Simulate blocking transfer delay.
|
||||
}
|
||||
actualFrameCount = byteCount / mFrameSize;
|
||||
actualFrameCount = byteCount / frameSize;
|
||||
}
|
||||
const size_t actualByteCount = actualFrameCount * mFrameSize;
|
||||
const size_t actualByteCount = actualFrameCount * frameSize;
|
||||
// Frames are consumed and counted regardless of the connection status.
|
||||
reply->fmqByteCount += actualByteCount;
|
||||
mFrameCount += actualFrameCount;
|
||||
mContext->advanceFrameCount(actualFrameCount);
|
||||
populateReply(reply, isConnected);
|
||||
} else {
|
||||
LOG(WARNING) << __func__ << ": reading of " << readByteCount
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
|
||||
namespace aidl::android::hardware::audio::core {
|
||||
|
||||
StreamAlsa::StreamAlsa(const StreamContext& context, const Metadata& metadata, int readWriteRetries)
|
||||
StreamAlsa::StreamAlsa(StreamContext* context, const Metadata& metadata, int readWriteRetries)
|
||||
: StreamCommonImpl(context, metadata),
|
||||
mFrameSizeBytes(getContext().getFrameSize()),
|
||||
mIsInput(isInput(metadata)),
|
||||
|
|
|
@ -113,7 +113,8 @@ class StreamContext {
|
|||
mDataMQ(std::move(other.mDataMQ)),
|
||||
mAsyncCallback(std::move(other.mAsyncCallback)),
|
||||
mOutEventCallback(std::move(other.mOutEventCallback)),
|
||||
mDebugParameters(std::move(other.mDebugParameters)) {}
|
||||
mDebugParameters(std::move(other.mDebugParameters)),
|
||||
mFrameCount(other.mFrameCount) {}
|
||||
StreamContext& operator=(StreamContext&& other) {
|
||||
mCommandMQ = std::move(other.mCommandMQ);
|
||||
mInternalCommandCookie = other.mInternalCommandCookie;
|
||||
|
@ -128,6 +129,7 @@ class StreamContext {
|
|||
mAsyncCallback = std::move(other.mAsyncCallback);
|
||||
mOutEventCallback = std::move(other.mOutEventCallback);
|
||||
mDebugParameters = std::move(other.mDebugParameters);
|
||||
mFrameCount = other.mFrameCount;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
@ -156,7 +158,12 @@ class StreamContext {
|
|||
int getTransientStateDelayMs() const { return mDebugParameters.transientStateDelayMs; }
|
||||
int getSampleRate() const { return mSampleRate; }
|
||||
bool isValid() const;
|
||||
// 'reset' is called on a Binder thread when closing the stream. Does not use
|
||||
// locking because it only cleans MQ pointers which were also set on the Binder thread.
|
||||
void reset();
|
||||
// 'advanceFrameCount' and 'getFrameCount' are only called on the worker thread.
|
||||
long advanceFrameCount(size_t increase) { return mFrameCount += increase; }
|
||||
long getFrameCount() const { return mFrameCount; }
|
||||
|
||||
private:
|
||||
std::unique_ptr<CommandMQ> mCommandMQ;
|
||||
|
@ -172,6 +179,7 @@ class StreamContext {
|
|||
std::shared_ptr<IStreamCallback> mAsyncCallback;
|
||||
std::shared_ptr<IStreamOutEventCallback> mOutEventCallback; // Only used by output streams
|
||||
DebugParameters mDebugParameters;
|
||||
long mFrameCount = 0;
|
||||
};
|
||||
|
||||
// This interface provides operations of the stream which are executed on the worker thread.
|
||||
|
@ -206,17 +214,10 @@ class StreamWorkerCommonLogic : public ::android::hardware::audio::common::Strea
|
|||
protected:
|
||||
using DataBufferElement = int8_t;
|
||||
|
||||
StreamWorkerCommonLogic(const StreamContext& context, DriverInterface* driver)
|
||||
: mDriver(driver),
|
||||
mInternalCommandCookie(context.getInternalCommandCookie()),
|
||||
mFrameSize(context.getFrameSize()),
|
||||
mCommandMQ(context.getCommandMQ()),
|
||||
mReplyMQ(context.getReplyMQ()),
|
||||
mDataMQ(context.getDataMQ()),
|
||||
mAsyncCallback(context.getAsyncCallback()),
|
||||
mTransientStateDelayMs(context.getTransientStateDelayMs()),
|
||||
mForceTransientBurst(context.getForceTransientBurst()),
|
||||
mForceSynchronousDrain(context.getForceSynchronousDrain()) {}
|
||||
StreamWorkerCommonLogic(StreamContext* context, DriverInterface* driver)
|
||||
: mContext(context),
|
||||
mDriver(driver),
|
||||
mTransientStateDelayMs(context->getTransientStateDelayMs()) {}
|
||||
std::string init() override;
|
||||
void populateReply(StreamDescriptor::Reply* reply, bool isConnected) const;
|
||||
void populateReplyWrongState(StreamDescriptor::Reply* reply,
|
||||
|
@ -226,34 +227,28 @@ class StreamWorkerCommonLogic : public ::android::hardware::audio::common::Strea
|
|||
mTransientStateStart = std::chrono::steady_clock::now();
|
||||
}
|
||||
|
||||
// The context is only used for reading, except for updating the frame count,
|
||||
// which happens on the worker thread only.
|
||||
StreamContext* const mContext;
|
||||
DriverInterface* const mDriver;
|
||||
// Atomic fields are used both by the main and worker threads.
|
||||
std::atomic<bool> mIsConnected = false;
|
||||
static_assert(std::atomic<StreamDescriptor::State>::is_always_lock_free);
|
||||
std::atomic<StreamDescriptor::State> mState = StreamDescriptor::State::STANDBY;
|
||||
// All fields are used on the worker thread only.
|
||||
const int mInternalCommandCookie;
|
||||
const size_t mFrameSize;
|
||||
StreamContext::CommandMQ* const mCommandMQ;
|
||||
StreamContext::ReplyMQ* const mReplyMQ;
|
||||
StreamContext::DataMQ* const mDataMQ;
|
||||
std::shared_ptr<IStreamCallback> mAsyncCallback;
|
||||
// All fields below are used on the worker thread only.
|
||||
const std::chrono::duration<int, std::milli> mTransientStateDelayMs;
|
||||
std::chrono::time_point<std::chrono::steady_clock> mTransientStateStart;
|
||||
const bool mForceTransientBurst;
|
||||
const bool mForceSynchronousDrain;
|
||||
// We use an array and the "size" field instead of a vector to be able to detect
|
||||
// memory allocation issues.
|
||||
std::unique_ptr<DataBufferElement[]> mDataBuffer;
|
||||
size_t mDataBufferSize;
|
||||
long mFrameCount = 0;
|
||||
};
|
||||
|
||||
// This interface is used to decouple stream implementations from a concrete StreamWorker
|
||||
// implementation.
|
||||
struct StreamWorkerInterface {
|
||||
using CreateInstance = std::function<StreamWorkerInterface*(const StreamContext& context,
|
||||
DriverInterface* driver)>;
|
||||
using CreateInstance =
|
||||
std::function<StreamWorkerInterface*(StreamContext* context, DriverInterface* driver)>;
|
||||
virtual ~StreamWorkerInterface() = default;
|
||||
virtual bool isClosed() const = 0;
|
||||
virtual void setIsConnected(bool isConnected) = 0;
|
||||
|
@ -268,7 +263,7 @@ class StreamWorkerImpl : public StreamWorkerInterface,
|
|||
using WorkerImpl = ::android::hardware::audio::common::StreamWorker<WorkerLogic>;
|
||||
|
||||
public:
|
||||
StreamWorkerImpl(const StreamContext& context, DriverInterface* driver)
|
||||
StreamWorkerImpl(StreamContext* context, DriverInterface* driver)
|
||||
: WorkerImpl(context, driver) {}
|
||||
bool isClosed() const override { return WorkerImpl::isClosed(); }
|
||||
void setIsConnected(bool isConnected) override { WorkerImpl::setIsConnected(isConnected); }
|
||||
|
@ -282,7 +277,7 @@ class StreamWorkerImpl : public StreamWorkerInterface,
|
|||
class StreamInWorkerLogic : public StreamWorkerCommonLogic {
|
||||
public:
|
||||
static const std::string kThreadName;
|
||||
StreamInWorkerLogic(const StreamContext& context, DriverInterface* driver)
|
||||
StreamInWorkerLogic(StreamContext* context, DriverInterface* driver)
|
||||
: StreamWorkerCommonLogic(context, driver) {}
|
||||
|
||||
protected:
|
||||
|
@ -296,8 +291,9 @@ using StreamInWorker = StreamWorkerImpl<StreamInWorkerLogic>;
|
|||
class StreamOutWorkerLogic : public StreamWorkerCommonLogic {
|
||||
public:
|
||||
static const std::string kThreadName;
|
||||
StreamOutWorkerLogic(const StreamContext& context, DriverInterface* driver)
|
||||
: StreamWorkerCommonLogic(context, driver), mEventCallback(context.getOutEventCallback()) {}
|
||||
StreamOutWorkerLogic(StreamContext* context, DriverInterface* driver)
|
||||
: StreamWorkerCommonLogic(context, driver),
|
||||
mEventCallback(context->getOutEventCallback()) {}
|
||||
|
||||
protected:
|
||||
Status cycle() override;
|
||||
|
@ -416,10 +412,10 @@ class StreamCommonDelegator : public BnStreamCommon {
|
|||
// who must be owner of the context.
|
||||
class StreamCommonImpl : virtual public StreamCommonInterface, virtual public DriverInterface {
|
||||
public:
|
||||
StreamCommonImpl(const StreamContext& context, const Metadata& metadata,
|
||||
StreamCommonImpl(StreamContext* context, const Metadata& metadata,
|
||||
const StreamWorkerInterface::CreateInstance& createWorker)
|
||||
: mContext(context), mMetadata(metadata), mWorker(createWorker(mContext, this)) {}
|
||||
StreamCommonImpl(const StreamContext& context, const Metadata& metadata)
|
||||
: mContext(*context), mMetadata(metadata), mWorker(createWorker(context, this)) {}
|
||||
StreamCommonImpl(StreamContext* context, const Metadata& metadata)
|
||||
: StreamCommonImpl(
|
||||
context, metadata,
|
||||
isInput(metadata) ? getDefaultInWorkerCreator() : getDefaultOutWorkerCreator()) {}
|
||||
|
@ -453,12 +449,12 @@ class StreamCommonImpl : virtual public StreamCommonInterface, virtual public Dr
|
|||
|
||||
protected:
|
||||
static StreamWorkerInterface::CreateInstance getDefaultInWorkerCreator() {
|
||||
return [](const StreamContext& ctx, DriverInterface* driver) -> StreamWorkerInterface* {
|
||||
return [](StreamContext* ctx, DriverInterface* driver) -> StreamWorkerInterface* {
|
||||
return new StreamInWorker(ctx, driver);
|
||||
};
|
||||
}
|
||||
static StreamWorkerInterface::CreateInstance getDefaultOutWorkerCreator() {
|
||||
return [](const StreamContext& ctx, DriverInterface* driver) -> StreamWorkerInterface* {
|
||||
return [](StreamContext* ctx, DriverInterface* driver) -> StreamWorkerInterface* {
|
||||
return new StreamOutWorker(ctx, driver);
|
||||
};
|
||||
}
|
||||
|
|
|
@ -31,7 +31,7 @@ namespace aidl::android::hardware::audio::core {
|
|||
// provide necessary overrides for all interface methods omitted here.
|
||||
class StreamAlsa : public StreamCommonImpl {
|
||||
public:
|
||||
StreamAlsa(const StreamContext& context, const Metadata& metadata, int readWriteRetries);
|
||||
StreamAlsa(StreamContext* context, const Metadata& metadata, int readWriteRetries);
|
||||
// Methods of 'DriverInterface'.
|
||||
::android::status_t init() override;
|
||||
::android::status_t drain(StreamDescriptor::DrainMode) override;
|
||||
|
|
|
@ -29,7 +29,7 @@ using aidl::android::hardware::audio::core::r_submix::SubmixRoute;
|
|||
|
||||
class StreamRemoteSubmix : public StreamCommonImpl {
|
||||
public:
|
||||
StreamRemoteSubmix(const StreamContext& context, const Metadata& metadata);
|
||||
StreamRemoteSubmix(StreamContext* context, const Metadata& metadata);
|
||||
|
||||
::android::status_t init() override;
|
||||
::android::status_t drain(StreamDescriptor::DrainMode) override;
|
||||
|
|
|
@ -22,7 +22,7 @@ namespace aidl::android::hardware::audio::core {
|
|||
|
||||
class StreamStub : public StreamCommonImpl {
|
||||
public:
|
||||
StreamStub(const StreamContext& context, const Metadata& metadata);
|
||||
StreamStub(StreamContext* context, const Metadata& metadata);
|
||||
// Methods of 'DriverInterface'.
|
||||
::android::status_t init() override;
|
||||
::android::status_t drain(StreamDescriptor::DrainMode) override;
|
||||
|
|
|
@ -28,7 +28,7 @@ namespace aidl::android::hardware::audio::core {
|
|||
|
||||
class StreamUsb : public StreamAlsa {
|
||||
public:
|
||||
StreamUsb(const StreamContext& context, const Metadata& metadata);
|
||||
StreamUsb(StreamContext* context, const Metadata& metadata);
|
||||
// Methods of 'DriverInterface'.
|
||||
::android::status_t transfer(void* buffer, size_t frameCount, size_t* actualFrameCount,
|
||||
int32_t* latencyMs) override;
|
||||
|
|
|
@ -29,14 +29,14 @@ using aidl::android::media::audio::common::MicrophoneInfo;
|
|||
|
||||
namespace aidl::android::hardware::audio::core {
|
||||
|
||||
StreamRemoteSubmix::StreamRemoteSubmix(const StreamContext& context, const Metadata& metadata)
|
||||
StreamRemoteSubmix::StreamRemoteSubmix(StreamContext* context, const Metadata& metadata)
|
||||
: StreamCommonImpl(context, metadata),
|
||||
mPortId(context.getPortId()),
|
||||
mPortId(context->getPortId()),
|
||||
mIsInput(isInput(metadata)) {
|
||||
mStreamConfig.frameSize = context.getFrameSize();
|
||||
mStreamConfig.format = context.getFormat();
|
||||
mStreamConfig.channelLayout = context.getChannelLayout();
|
||||
mStreamConfig.sampleRate = context.getSampleRate();
|
||||
mStreamConfig.frameSize = context->getFrameSize();
|
||||
mStreamConfig.format = context->getFormat();
|
||||
mStreamConfig.channelLayout = context->getChannelLayout();
|
||||
mStreamConfig.sampleRate = context->getSampleRate();
|
||||
}
|
||||
|
||||
std::mutex StreamRemoteSubmix::sSubmixRoutesLock;
|
||||
|
@ -357,7 +357,7 @@ StreamInRemoteSubmix::StreamInRemoteSubmix(StreamContext&& context,
|
|||
const SinkMetadata& sinkMetadata,
|
||||
const std::vector<MicrophoneInfo>& microphones)
|
||||
: StreamIn(std::move(context), microphones),
|
||||
StreamRemoteSubmix(StreamIn::mContext, sinkMetadata) {}
|
||||
StreamRemoteSubmix(&(StreamIn::mContext), sinkMetadata) {}
|
||||
|
||||
ndk::ScopedAStatus StreamInRemoteSubmix::getActiveMicrophones(
|
||||
std::vector<MicrophoneDynamicInfo>* _aidl_return) {
|
||||
|
@ -370,6 +370,6 @@ StreamOutRemoteSubmix::StreamOutRemoteSubmix(StreamContext&& context,
|
|||
const SourceMetadata& sourceMetadata,
|
||||
const std::optional<AudioOffloadInfo>& offloadInfo)
|
||||
: StreamOut(std::move(context), offloadInfo),
|
||||
StreamRemoteSubmix(StreamOut::mContext, sourceMetadata) {}
|
||||
StreamRemoteSubmix(&(StreamOut::mContext), sourceMetadata) {}
|
||||
|
||||
} // namespace aidl::android::hardware::audio::core
|
||||
|
|
|
@ -31,7 +31,7 @@ using aidl::android::media::audio::common::MicrophoneInfo;
|
|||
|
||||
namespace aidl::android::hardware::audio::core {
|
||||
|
||||
StreamStub::StreamStub(const StreamContext& context, const Metadata& metadata)
|
||||
StreamStub::StreamStub(StreamContext* context, const Metadata& metadata)
|
||||
: StreamCommonImpl(context, metadata),
|
||||
mFrameSizeBytes(getContext().getFrameSize()),
|
||||
mSampleRate(getContext().getSampleRate()),
|
||||
|
@ -120,10 +120,11 @@ void StreamStub::shutdown() {
|
|||
|
||||
StreamInStub::StreamInStub(StreamContext&& context, const SinkMetadata& sinkMetadata,
|
||||
const std::vector<MicrophoneInfo>& microphones)
|
||||
: StreamIn(std::move(context), microphones), StreamStub(StreamIn::mContext, sinkMetadata) {}
|
||||
: StreamIn(std::move(context), microphones), StreamStub(&(StreamIn::mContext), sinkMetadata) {}
|
||||
|
||||
StreamOutStub::StreamOutStub(StreamContext&& context, const SourceMetadata& sourceMetadata,
|
||||
const std::optional<AudioOffloadInfo>& offloadInfo)
|
||||
: StreamOut(std::move(context), offloadInfo), StreamStub(StreamOut::mContext, sourceMetadata) {}
|
||||
: StreamOut(std::move(context), offloadInfo),
|
||||
StreamStub(&(StreamOut::mContext), sourceMetadata) {}
|
||||
|
||||
} // namespace aidl::android::hardware::audio::core
|
||||
|
|
|
@ -35,7 +35,7 @@ using aidl::android::media::audio::common::MicrophoneInfo;
|
|||
|
||||
namespace aidl::android::hardware::audio::core {
|
||||
|
||||
StreamUsb::StreamUsb(const StreamContext& context, const Metadata& metadata)
|
||||
StreamUsb::StreamUsb(StreamContext* context, const Metadata& metadata)
|
||||
: StreamAlsa(context, metadata, 1 /*readWriteRetries*/) {}
|
||||
|
||||
ndk::ScopedAStatus StreamUsb::setConnectedDevices(
|
||||
|
@ -85,7 +85,7 @@ std::vector<alsa::DeviceProfile> StreamUsb::getDeviceProfiles() {
|
|||
|
||||
StreamInUsb::StreamInUsb(StreamContext&& context, const SinkMetadata& sinkMetadata,
|
||||
const std::vector<MicrophoneInfo>& microphones)
|
||||
: StreamIn(std::move(context), microphones), StreamUsb(StreamIn::mContext, sinkMetadata) {}
|
||||
: StreamIn(std::move(context), microphones), StreamUsb(&(StreamIn::mContext), sinkMetadata) {}
|
||||
|
||||
ndk::ScopedAStatus StreamInUsb::getActiveMicrophones(
|
||||
std::vector<MicrophoneDynamicInfo>* _aidl_return __unused) {
|
||||
|
@ -96,7 +96,7 @@ ndk::ScopedAStatus StreamInUsb::getActiveMicrophones(
|
|||
StreamOutUsb::StreamOutUsb(StreamContext&& context, const SourceMetadata& sourceMetadata,
|
||||
const std::optional<AudioOffloadInfo>& offloadInfo)
|
||||
: StreamOut(std::move(context), offloadInfo),
|
||||
StreamUsb(StreamOut::mContext, sourceMetadata),
|
||||
StreamUsb(&(StreamOut::mContext), sourceMetadata),
|
||||
mChannelCount(getChannelCount(getContext().getChannelLayout())) {}
|
||||
|
||||
ndk::ScopedAStatus StreamOutUsb::getHwVolume(std::vector<float>* _aidl_return) {
|
||||
|
|
Loading…
Reference in a new issue