Merge "audio: Do not use StreamSwitcher for StreamPrimary" into main

This commit is contained in:
Treehugger Robot
2024-10-03 21:48:38 +00:00
committed by Gerrit Code Review
9 changed files with 317 additions and 256 deletions

View File

@@ -77,6 +77,7 @@ cc_library {
"r_submix/ModuleRemoteSubmix.cpp",
"r_submix/SubmixRoute.cpp",
"r_submix/StreamRemoteSubmix.cpp",
"stub/DriverStubImpl.cpp",
"stub/ModuleStub.cpp",
"stub/StreamStub.cpp",
"usb/ModuleUsb.cpp",

View File

@@ -0,0 +1,49 @@
/*
* Copyright (C) 2024 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include "core-impl/Stream.h"
namespace aidl::android::hardware::audio::core {
class DriverStubImpl : virtual public DriverInterface {
public:
explicit DriverStubImpl(const StreamContext& context);
::android::status_t init() override;
::android::status_t drain(StreamDescriptor::DrainMode) override;
::android::status_t flush() override;
::android::status_t pause() override;
::android::status_t standby() override;
::android::status_t start() override;
::android::status_t transfer(void* buffer, size_t frameCount, size_t* actualFrameCount,
int32_t* latencyMs) override;
void shutdown() override;
private:
const size_t mBufferSizeFrames;
const size_t mFrameSizeBytes;
const int mSampleRate;
const bool mIsAsynchronous;
const bool mIsInput;
bool mIsInitialized = false; // Used for validating the state machine logic.
bool mIsStandby = true; // Used for validating the state machine logic.
int64_t mStartTimeNs = 0;
long mFramesSinceStart = 0;
};
} // namespace aidl::android::hardware::audio::core

View File

@@ -133,6 +133,9 @@ class StreamContext {
ReplyMQ* getReplyMQ() const { return mReplyMQ.get(); }
int getTransientStateDelayMs() const { return mDebugParameters.transientStateDelayMs; }
int getSampleRate() const { return mSampleRate; }
bool isInput() const {
return mFlags.getTag() == ::aidl::android::media::audio::common::AudioIoFlags::input;
}
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.

View File

@@ -16,25 +16,39 @@
#pragma once
#include <mutex>
#include <vector>
#include <android-base/thread_annotations.h>
#include "DriverStubImpl.h"
#include "StreamAlsa.h"
#include "StreamSwitcher.h"
#include "primary/PrimaryMixer.h"
namespace aidl::android::hardware::audio::core {
class StreamPrimary : public StreamAlsa {
public:
StreamPrimary(StreamContext* context, const Metadata& metadata,
const std::vector<::aidl::android::media::audio::common::AudioDevice>& devices);
StreamPrimary(StreamContext* context, const Metadata& metadata);
// Methods of 'DriverInterface'.
::android::status_t init() override;
::android::status_t drain(StreamDescriptor::DrainMode mode) override;
::android::status_t flush() override;
::android::status_t pause() override;
::android::status_t standby() override;
::android::status_t start() override;
::android::status_t transfer(void* buffer, size_t frameCount, size_t* actualFrameCount,
int32_t* latencyMs) override;
::android::status_t refinePosition(StreamDescriptor::Position* position) override;
void shutdown() override;
// Overridden methods of 'StreamCommonImpl', called on a Binder thread.
ndk::ScopedAStatus setConnectedDevices(const ConnectedDevices& devices) override;
protected:
std::vector<alsa::DeviceProfile> getDeviceProfiles() override;
bool isStubStream();
const bool mIsAsynchronous;
int64_t mStartTimeNs = 0;
@@ -42,12 +56,29 @@ class StreamPrimary : public StreamAlsa {
bool mSkipNextTransfer = false;
private:
static std::pair<int, int> getCardAndDeviceId(
using AlsaDeviceId = std::pair<int, int>;
static constexpr StreamPrimary::AlsaDeviceId kDefaultCardAndDeviceId{
primary::PrimaryMixer::kAlsaCard, primary::PrimaryMixer::kAlsaDevice};
static constexpr StreamPrimary::AlsaDeviceId kStubDeviceId{
primary::PrimaryMixer::kInvalidAlsaCard, primary::PrimaryMixer::kInvalidAlsaDevice};
static AlsaDeviceId getCardAndDeviceId(
const std::vector<::aidl::android::media::audio::common::AudioDevice>& devices);
const std::pair<int, int> mCardAndDeviceId;
static bool useStubStream(bool isInput,
const ::aidl::android::media::audio::common::AudioDevice& device);
bool isStubStreamOnWorker() const { return mCurrAlsaDeviceId == kStubDeviceId; }
DriverStubImpl mStubDriver;
mutable std::mutex mLock;
AlsaDeviceId mAlsaDeviceId GUARDED_BY(mLock) = kStubDeviceId;
// Used by the worker thread only.
AlsaDeviceId mCurrAlsaDeviceId = kStubDeviceId;
};
class StreamInPrimary final : public StreamIn, public StreamSwitcher, public StreamInHwGainHelper {
class StreamInPrimary final : public StreamIn, public StreamPrimary, public StreamInHwGainHelper {
public:
friend class ndk::SharedRefBase;
StreamInPrimary(
@@ -56,14 +87,6 @@ class StreamInPrimary final : public StreamIn, public StreamSwitcher, public Str
const std::vector<::aidl::android::media::audio::common::MicrophoneInfo>& microphones);
private:
static bool useStubStream(const ::aidl::android::media::audio::common::AudioDevice& device);
DeviceSwitchBehavior switchCurrentStream(
const std::vector<::aidl::android::media::audio::common::AudioDevice>& devices)
override;
std::unique_ptr<StreamCommonInterfaceEx> createNewStream(
const std::vector<::aidl::android::media::audio::common::AudioDevice>& devices,
StreamContext* context, const Metadata& metadata) override;
void onClose(StreamDescriptor::State) override { defaultOnClose(); }
ndk::ScopedAStatus getHwGain(std::vector<float>* _aidl_return) override;
@@ -71,7 +94,7 @@ class StreamInPrimary final : public StreamIn, public StreamSwitcher, public Str
};
class StreamOutPrimary final : public StreamOut,
public StreamSwitcher,
public StreamPrimary,
public StreamOutHwVolumeHelper {
public:
friend class ndk::SharedRefBase;
@@ -81,22 +104,10 @@ class StreamOutPrimary final : public StreamOut,
offloadInfo);
private:
static bool useStubStream(const ::aidl::android::media::audio::common::AudioDevice& device);
DeviceSwitchBehavior switchCurrentStream(
const std::vector<::aidl::android::media::audio::common::AudioDevice>& devices)
override;
std::unique_ptr<StreamCommonInterfaceEx> createNewStream(
const std::vector<::aidl::android::media::audio::common::AudioDevice>& devices,
StreamContext* context, const Metadata& metadata) override;
void onClose(StreamDescriptor::State) override { defaultOnClose(); }
ndk::ScopedAStatus getHwVolume(std::vector<float>* _aidl_return) override;
ndk::ScopedAStatus setHwVolume(const std::vector<float>& in_channelVolumes) override;
ndk::ScopedAStatus setConnectedDevices(
const std::vector<::aidl::android::media::audio::common::AudioDevice>& devices)
override;
};
} // namespace aidl::android::hardware::audio::core

View File

@@ -16,38 +16,15 @@
#pragma once
#include "core-impl/DriverStubImpl.h"
#include "core-impl/Stream.h"
namespace aidl::android::hardware::audio::core {
class StreamStub : public StreamCommonImpl {
class StreamStub : public StreamCommonImpl, public DriverStubImpl {
public:
StreamStub(StreamContext* context, const Metadata& metadata);
~StreamStub();
// Methods of 'DriverInterface'.
::android::status_t init() override;
::android::status_t drain(StreamDescriptor::DrainMode) override;
::android::status_t flush() override;
::android::status_t pause() override;
::android::status_t standby() override;
::android::status_t start() override;
::android::status_t transfer(void* buffer, size_t frameCount, size_t* actualFrameCount,
int32_t* latencyMs) override;
void shutdown() override;
private:
const size_t mBufferSizeFrames;
const size_t mFrameSizeBytes;
const int mSampleRate;
const bool mIsAsynchronous;
const bool mIsInput;
bool mIsInitialized = false; // Used for validating the state machine logic.
bool mIsStandby = true; // Used for validating the state machine logic.
// Used by the worker thread.
int64_t mStartTimeNs = 0;
long mFramesSinceStart = 0;
};
class StreamInStub final : public StreamIn, public StreamStub {

View File

@@ -16,20 +16,14 @@
#pragma once
#include <map>
#include <memory>
#include <mutex>
#include <vector>
#include <android-base/thread_annotations.h>
#include <android/binder_auto_utils.h>
#include "alsa/Mixer.h"
namespace aidl::android::hardware::audio::core::primary {
class PrimaryMixer : public alsa::Mixer {
public:
static constexpr int kInvalidAlsaCard = -1;
static constexpr int kInvalidAlsaDevice = -1;
static constexpr int kAlsaCard = 0;
static constexpr int kAlsaDevice = 0;

View File

@@ -25,9 +25,7 @@
#include <error/Result.h>
#include <error/expected_utils.h>
#include "PrimaryMixer.h"
#include "core-impl/StreamPrimary.h"
#include "core-impl/StreamStub.h"
using aidl::android::hardware::audio::common::SinkMetadata;
using aidl::android::hardware::audio::common::SourceMetadata;
@@ -41,19 +39,49 @@ using android::base::GetBoolProperty;
namespace aidl::android::hardware::audio::core {
const static constexpr std::pair<int, int> kDefaultCardAndDeviceId = {
primary::PrimaryMixer::kAlsaCard, primary::PrimaryMixer::kAlsaDevice};
StreamPrimary::StreamPrimary(
StreamContext* context, const Metadata& metadata,
const std::vector<::aidl::android::media::audio::common::AudioDevice>& devices)
StreamPrimary::StreamPrimary(StreamContext* context, const Metadata& metadata)
: StreamAlsa(context, metadata, 3 /*readWriteRetries*/),
mIsAsynchronous(!!getContext().getAsyncCallback()),
mCardAndDeviceId(getCardAndDeviceId(devices)) {
mStubDriver(getContext()) {
context->startStreamDataProcessor();
}
::android::status_t StreamPrimary::init() {
RETURN_STATUS_IF_ERROR(mStubDriver.init());
return StreamAlsa::init();
}
::android::status_t StreamPrimary::drain(StreamDescriptor::DrainMode mode) {
return isStubStreamOnWorker() ? mStubDriver.drain(mode) : StreamAlsa::drain(mode);
}
::android::status_t StreamPrimary::flush() {
return isStubStreamOnWorker() ? mStubDriver.flush() : StreamAlsa::flush();
}
::android::status_t StreamPrimary::pause() {
return isStubStreamOnWorker() ? mStubDriver.pause() : StreamAlsa::pause();
}
::android::status_t StreamPrimary::standby() {
return isStubStreamOnWorker() ? mStubDriver.standby() : StreamAlsa::standby();
}
::android::status_t StreamPrimary::start() {
bool isStub = true, shutdownAlsaStream = false;
{
std::lock_guard l(mLock);
isStub = mAlsaDeviceId == kStubDeviceId;
shutdownAlsaStream =
mCurrAlsaDeviceId != mAlsaDeviceId && mCurrAlsaDeviceId != kStubDeviceId;
mCurrAlsaDeviceId = mAlsaDeviceId;
}
if (shutdownAlsaStream) {
StreamAlsa::shutdown(); // Close currently opened ALSA devices.
}
if (isStub) {
return mStubDriver.start();
}
RETURN_STATUS_IF_ERROR(StreamAlsa::start());
mStartTimeNs = ::android::uptimeNanos();
mFramesSinceStart = 0;
@@ -63,6 +91,9 @@ StreamPrimary::StreamPrimary(
::android::status_t StreamPrimary::transfer(void* buffer, size_t frameCount,
size_t* actualFrameCount, int32_t* latencyMs) {
if (isStubStreamOnWorker()) {
return mStubDriver.transfer(buffer, frameCount, actualFrameCount, latencyMs);
}
// This is a workaround for the emulator implementation which has a host-side buffer
// and is not being able to achieve real-time behavior similar to ADSPs (b/302587331).
if (!mSkipNextTransfer) {
@@ -102,19 +133,52 @@ StreamPrimary::StreamPrimary(
return ::android::OK;
}
void StreamPrimary::shutdown() {
StreamAlsa::shutdown();
mStubDriver.shutdown();
}
ndk::ScopedAStatus StreamPrimary::setConnectedDevices(const ConnectedDevices& devices) {
LOG(DEBUG) << __func__ << ": " << ::android::internal::ToString(devices);
if (devices.size() > 1) {
LOG(ERROR) << __func__ << ": primary stream can only be connected to one device, got: "
<< devices.size();
return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
}
{
const bool useStubDriver = devices.empty() || useStubStream(mIsInput, devices[0]);
std::lock_guard l(mLock);
mAlsaDeviceId = useStubDriver ? kStubDeviceId : getCardAndDeviceId(devices);
}
if (!devices.empty()) {
auto streamDataProcessor = getContext().getStreamDataProcessor().lock();
if (streamDataProcessor != nullptr) {
streamDataProcessor->setAudioDevice(devices[0]);
}
}
return StreamAlsa::setConnectedDevices(devices);
}
std::vector<alsa::DeviceProfile> StreamPrimary::getDeviceProfiles() {
return {alsa::DeviceProfile{.card = mCardAndDeviceId.first,
.device = mCardAndDeviceId.second,
return {alsa::DeviceProfile{.card = mCurrAlsaDeviceId.first,
.device = mCurrAlsaDeviceId.second,
.direction = mIsInput ? PCM_IN : PCM_OUT,
.isExternal = false}};
}
std::pair<int, int> StreamPrimary::getCardAndDeviceId(const std::vector<AudioDevice>& devices) {
bool StreamPrimary::isStubStream() {
std::lock_guard l(mLock);
return mAlsaDeviceId == kStubDeviceId;
}
// static
StreamPrimary::AlsaDeviceId StreamPrimary::getCardAndDeviceId(
const std::vector<AudioDevice>& devices) {
if (devices.empty() || devices[0].address.getTag() != AudioDeviceAddress::id) {
return kDefaultCardAndDeviceId;
}
std::string deviceAddress = devices[0].address.get<AudioDeviceAddress::id>();
std::pair<int, int> cardAndDeviceId;
AlsaDeviceId cardAndDeviceId;
if (const size_t suffixPos = deviceAddress.rfind("CARD_");
suffixPos == std::string::npos ||
sscanf(deviceAddress.c_str() + suffixPos, "CARD_%d_DEV_%d", &cardAndDeviceId.first,
@@ -126,48 +190,28 @@ std::pair<int, int> StreamPrimary::getCardAndDeviceId(const std::vector<AudioDev
return cardAndDeviceId;
}
// static
bool StreamPrimary::useStubStream(
bool isInput, const ::aidl::android::media::audio::common::AudioDevice& device) {
static const bool kSimulateInput =
GetBoolProperty("ro.boot.audio.tinyalsa.simulate_input", false);
static const bool kSimulateOutput =
GetBoolProperty("ro.boot.audio.tinyalsa.ignore_output", false);
if (isInput) {
return kSimulateInput || device.type.type == AudioDeviceType::IN_TELEPHONY_RX ||
device.type.type == AudioDeviceType::IN_FM_TUNER ||
device.type.connection == AudioDeviceDescription::CONNECTION_BUS /*deprecated */;
}
return kSimulateOutput || device.type.type == AudioDeviceType::OUT_TELEPHONY_TX ||
device.type.connection == AudioDeviceDescription::CONNECTION_BUS /*deprecated*/;
}
StreamInPrimary::StreamInPrimary(StreamContext&& context, const SinkMetadata& sinkMetadata,
const std::vector<MicrophoneInfo>& microphones)
: StreamIn(std::move(context), microphones),
StreamSwitcher(&mContextInstance, sinkMetadata),
StreamPrimary(&mContextInstance, sinkMetadata),
StreamInHwGainHelper(&mContextInstance) {}
bool StreamInPrimary::useStubStream(const AudioDevice& device) {
static const bool kSimulateInput =
GetBoolProperty("ro.boot.audio.tinyalsa.simulate_input", false);
return kSimulateInput || device.type.type == AudioDeviceType::IN_TELEPHONY_RX ||
device.type.type == AudioDeviceType::IN_FM_TUNER ||
device.type.connection == AudioDeviceDescription::CONNECTION_BUS /*deprecated */;
}
StreamSwitcher::DeviceSwitchBehavior StreamInPrimary::switchCurrentStream(
const std::vector<::aidl::android::media::audio::common::AudioDevice>& devices) {
LOG(DEBUG) << __func__;
if (devices.size() > 1) {
LOG(ERROR) << __func__ << ": primary stream can only be connected to one device, got: "
<< devices.size();
return DeviceSwitchBehavior::UNSUPPORTED_DEVICES;
}
if (devices.empty() || useStubStream(devices[0]) == isStubStream()) {
return DeviceSwitchBehavior::USE_CURRENT_STREAM;
}
return DeviceSwitchBehavior::CREATE_NEW_STREAM;
}
std::unique_ptr<StreamCommonInterfaceEx> StreamInPrimary::createNewStream(
const std::vector<::aidl::android::media::audio::common::AudioDevice>& devices,
StreamContext* context, const Metadata& metadata) {
if (devices.empty()) {
LOG(FATAL) << __func__ << ": called with empty devices"; // see 'switchCurrentStream'
}
if (useStubStream(devices[0])) {
return std::unique_ptr<StreamCommonInterfaceEx>(
new InnerStreamWrapper<StreamStub>(context, metadata));
}
return std::unique_ptr<StreamCommonInterfaceEx>(
new InnerStreamWrapper<StreamPrimary>(context, metadata, devices));
}
ndk::ScopedAStatus StreamInPrimary::getHwGain(std::vector<float>* _aidl_return) {
if (isStubStream()) {
return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
@@ -201,44 +245,9 @@ ndk::ScopedAStatus StreamInPrimary::setHwGain(const std::vector<float>& in_chann
StreamOutPrimary::StreamOutPrimary(StreamContext&& context, const SourceMetadata& sourceMetadata,
const std::optional<AudioOffloadInfo>& offloadInfo)
: StreamOut(std::move(context), offloadInfo),
StreamSwitcher(&mContextInstance, sourceMetadata),
StreamPrimary(&mContextInstance, sourceMetadata),
StreamOutHwVolumeHelper(&mContextInstance) {}
bool StreamOutPrimary::useStubStream(const AudioDevice& device) {
static const bool kSimulateOutput =
GetBoolProperty("ro.boot.audio.tinyalsa.ignore_output", false);
return kSimulateOutput || device.type.type == AudioDeviceType::OUT_TELEPHONY_TX ||
device.type.connection == AudioDeviceDescription::CONNECTION_BUS /*deprecated*/;
}
StreamSwitcher::DeviceSwitchBehavior StreamOutPrimary::switchCurrentStream(
const std::vector<::aidl::android::media::audio::common::AudioDevice>& devices) {
LOG(DEBUG) << __func__;
if (devices.size() > 1) {
LOG(ERROR) << __func__ << ": primary stream can only be connected to one device, got: "
<< devices.size();
return DeviceSwitchBehavior::UNSUPPORTED_DEVICES;
}
if (devices.empty() || useStubStream(devices[0]) == isStubStream()) {
return DeviceSwitchBehavior::USE_CURRENT_STREAM;
}
return DeviceSwitchBehavior::CREATE_NEW_STREAM;
}
std::unique_ptr<StreamCommonInterfaceEx> StreamOutPrimary::createNewStream(
const std::vector<::aidl::android::media::audio::common::AudioDevice>& devices,
StreamContext* context, const Metadata& metadata) {
if (devices.empty()) {
LOG(FATAL) << __func__ << ": called with empty devices"; // see 'switchCurrentStream'
}
if (useStubStream(devices[0])) {
return std::unique_ptr<StreamCommonInterfaceEx>(
new InnerStreamWrapper<StreamStub>(context, metadata));
}
return std::unique_ptr<StreamCommonInterfaceEx>(
new InnerStreamWrapper<StreamPrimary>(context, metadata, devices));
}
ndk::ScopedAStatus StreamOutPrimary::getHwVolume(std::vector<float>* _aidl_return) {
if (isStubStream()) {
return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
@@ -264,15 +273,4 @@ ndk::ScopedAStatus StreamOutPrimary::setHwVolume(const std::vector<float>& in_ch
return ndk::ScopedAStatus::ok();
}
ndk::ScopedAStatus StreamOutPrimary::setConnectedDevices(
const std::vector<::aidl::android::media::audio::common::AudioDevice>& devices) {
if (!devices.empty()) {
auto streamDataProcessor = mContextInstance.getStreamDataProcessor().lock();
if (streamDataProcessor != nullptr) {
streamDataProcessor->setAudioDevice(devices[0]);
}
}
return StreamSwitcher::setConnectedDevices(devices);
}
} // namespace aidl::android::hardware::audio::core

View File

@@ -0,0 +1,126 @@
/*
* Copyright (C) 2024 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <cmath>
#define LOG_TAG "AHAL_Stream"
#include <android-base/logging.h>
#include <audio_utils/clock.h>
#include "core-impl/DriverStubImpl.h"
namespace aidl::android::hardware::audio::core {
DriverStubImpl::DriverStubImpl(const StreamContext& context)
: mBufferSizeFrames(context.getBufferSizeInFrames()),
mFrameSizeBytes(context.getFrameSize()),
mSampleRate(context.getSampleRate()),
mIsAsynchronous(!!context.getAsyncCallback()),
mIsInput(context.isInput()) {}
::android::status_t DriverStubImpl::init() {
mIsInitialized = true;
return ::android::OK;
}
::android::status_t DriverStubImpl::drain(StreamDescriptor::DrainMode) {
if (!mIsInitialized) {
LOG(FATAL) << __func__ << ": must not happen for an uninitialized driver";
}
if (!mIsInput) {
if (!mIsAsynchronous) {
static constexpr float kMicrosPerSecond = MICROS_PER_SECOND;
const size_t delayUs = static_cast<size_t>(
std::roundf(mBufferSizeFrames * kMicrosPerSecond / mSampleRate));
usleep(delayUs);
} else {
usleep(500);
}
}
return ::android::OK;
}
::android::status_t DriverStubImpl::flush() {
if (!mIsInitialized) {
LOG(FATAL) << __func__ << ": must not happen for an uninitialized driver";
}
return ::android::OK;
}
::android::status_t DriverStubImpl::pause() {
if (!mIsInitialized) {
LOG(FATAL) << __func__ << ": must not happen for an uninitialized driver";
}
return ::android::OK;
}
::android::status_t DriverStubImpl::standby() {
if (!mIsInitialized) {
LOG(FATAL) << __func__ << ": must not happen for an uninitialized driver";
}
mIsStandby = true;
return ::android::OK;
}
::android::status_t DriverStubImpl::start() {
if (!mIsInitialized) {
LOG(FATAL) << __func__ << ": must not happen for an uninitialized driver";
}
mIsStandby = false;
mStartTimeNs = ::android::uptimeNanos();
mFramesSinceStart = 0;
return ::android::OK;
}
::android::status_t DriverStubImpl::transfer(void* buffer, size_t frameCount,
size_t* actualFrameCount, int32_t*) {
if (!mIsInitialized) {
LOG(FATAL) << __func__ << ": must not happen for an uninitialized driver";
}
if (mIsStandby) {
LOG(FATAL) << __func__ << ": must not happen while in standby";
}
*actualFrameCount = frameCount;
if (mIsAsynchronous) {
usleep(500);
} else {
mFramesSinceStart += *actualFrameCount;
const long bufferDurationUs = (*actualFrameCount) * MICROS_PER_SECOND / mSampleRate;
const auto totalDurationUs =
(::android::uptimeNanos() - mStartTimeNs) / NANOS_PER_MICROSECOND;
const long totalOffsetUs =
mFramesSinceStart * MICROS_PER_SECOND / mSampleRate - totalDurationUs;
LOG(VERBOSE) << __func__ << ": totalOffsetUs " << totalOffsetUs;
if (totalOffsetUs > 0) {
const long sleepTimeUs = std::min(totalOffsetUs, bufferDurationUs);
LOG(VERBOSE) << __func__ << ": sleeping for " << sleepTimeUs << " us";
usleep(sleepTimeUs);
}
}
if (mIsInput) {
uint8_t* byteBuffer = static_cast<uint8_t*>(buffer);
for (size_t i = 0; i < frameCount * mFrameSizeBytes; ++i) {
byteBuffer[i] = std::rand() % 255;
}
}
return ::android::OK;
}
void DriverStubImpl::shutdown() {
mIsInitialized = false;
}
} // namespace aidl::android::hardware::audio::core

View File

@@ -32,110 +32,12 @@ using aidl::android::media::audio::common::MicrophoneInfo;
namespace aidl::android::hardware::audio::core {
StreamStub::StreamStub(StreamContext* context, const Metadata& metadata)
: StreamCommonImpl(context, metadata),
mBufferSizeFrames(getContext().getBufferSizeInFrames()),
mFrameSizeBytes(getContext().getFrameSize()),
mSampleRate(getContext().getSampleRate()),
mIsAsynchronous(!!getContext().getAsyncCallback()),
mIsInput(isInput(metadata)) {}
: StreamCommonImpl(context, metadata), DriverStubImpl(getContext()) {}
StreamStub::~StreamStub() {
cleanupWorker();
}
::android::status_t StreamStub::init() {
mIsInitialized = true;
return ::android::OK;
}
::android::status_t StreamStub::drain(StreamDescriptor::DrainMode) {
if (!mIsInitialized) {
LOG(FATAL) << __func__ << ": must not happen for an uninitialized driver";
}
if (!mIsInput) {
if (!mIsAsynchronous) {
static constexpr float kMicrosPerSecond = MICROS_PER_SECOND;
const size_t delayUs = static_cast<size_t>(
std::roundf(mBufferSizeFrames * kMicrosPerSecond / mSampleRate));
usleep(delayUs);
} else {
usleep(500);
}
}
return ::android::OK;
}
::android::status_t StreamStub::flush() {
if (!mIsInitialized) {
LOG(FATAL) << __func__ << ": must not happen for an uninitialized driver";
}
return ::android::OK;
}
::android::status_t StreamStub::pause() {
if (!mIsInitialized) {
LOG(FATAL) << __func__ << ": must not happen for an uninitialized driver";
}
return ::android::OK;
}
::android::status_t StreamStub::standby() {
if (!mIsInitialized) {
LOG(FATAL) << __func__ << ": must not happen for an uninitialized driver";
}
mIsStandby = true;
return ::android::OK;
}
::android::status_t StreamStub::start() {
if (!mIsInitialized) {
LOG(FATAL) << __func__ << ": must not happen for an uninitialized driver";
}
mIsStandby = false;
mStartTimeNs = ::android::uptimeNanos();
mFramesSinceStart = 0;
return ::android::OK;
}
::android::status_t StreamStub::transfer(void* buffer, size_t frameCount, size_t* actualFrameCount,
int32_t*) {
if (!mIsInitialized) {
LOG(FATAL) << __func__ << ": must not happen for an uninitialized driver";
}
if (mIsStandby) {
LOG(FATAL) << __func__ << ": must not happen while in standby";
}
*actualFrameCount = frameCount;
if (mIsAsynchronous) {
usleep(500);
} else {
mFramesSinceStart += *actualFrameCount;
const long bufferDurationUs =
(*actualFrameCount) * MICROS_PER_SECOND / mContext.getSampleRate();
const auto totalDurationUs =
(::android::uptimeNanos() - mStartTimeNs) / NANOS_PER_MICROSECOND;
const long totalOffsetUs =
mFramesSinceStart * MICROS_PER_SECOND / mContext.getSampleRate() - totalDurationUs;
LOG(VERBOSE) << __func__ << ": totalOffsetUs " << totalOffsetUs;
if (totalOffsetUs > 0) {
const long sleepTimeUs = std::min(totalOffsetUs, bufferDurationUs);
LOG(VERBOSE) << __func__ << ": sleeping for " << sleepTimeUs << " us";
usleep(sleepTimeUs);
}
}
if (mIsInput) {
uint8_t* byteBuffer = static_cast<uint8_t*>(buffer);
for (size_t i = 0; i < frameCount * mFrameSizeBytes; ++i) {
byteBuffer[i] = std::rand() % 255;
}
}
return ::android::OK;
}
void StreamStub::shutdown() {
mIsInitialized = false;
}
StreamInStub::StreamInStub(StreamContext&& context, const SinkMetadata& sinkMetadata,
const std::vector<MicrophoneInfo>& microphones)
: StreamIn(std::move(context), microphones), StreamStub(&mContextInstance, sinkMetadata) {}