Merge changes from topic "fix-b-264712385-primary-module" into main

* changes:
  audio: Move StreamContext ownership out from StreamCommonImpl
  audio: Use ChildInterface in StreamCommonImpl
  audio: Update StreamAlsa and alsa utils for built-in devices
  audio: Simplify and extend alsa::Mixer
This commit is contained in:
Treehugger Robot 2023-07-20 23:09:50 +00:00 committed by Gerrit Code Review
commit 12c4bf6ba1
25 changed files with 393 additions and 257 deletions

View file

@ -675,7 +675,7 @@ ndk::ScopedAStatus Module::openInputStream(const OpenInputStreamArguments& in_ar
nullptr, nullptr, &context));
context.fillDescriptor(&_aidl_return->desc);
std::shared_ptr<StreamIn> stream;
RETURN_STATUS_IF_ERROR(createInputStream(in_args.sinkMetadata, std::move(context),
RETURN_STATUS_IF_ERROR(createInputStream(std::move(context), in_args.sinkMetadata,
mConfig->microphones, &stream));
StreamWrapper streamWrapper(stream);
if (auto patchIt = mPatches.find(in_args.portConfigId); patchIt != mPatches.end()) {
@ -721,7 +721,7 @@ ndk::ScopedAStatus Module::openOutputStream(const OpenOutputStreamArguments& in_
in_args.eventCallback, &context));
context.fillDescriptor(&_aidl_return->desc);
std::shared_ptr<StreamOut> stream;
RETURN_STATUS_IF_ERROR(createOutputStream(in_args.sourceMetadata, std::move(context),
RETURN_STATUS_IF_ERROR(createOutputStream(std::move(context), in_args.sourceMetadata,
in_args.offloadInfo, &stream));
StreamWrapper streamWrapper(stream);
if (auto patchIt = mPatches.find(in_args.portConfigId); patchIt != mPatches.end()) {

View file

@ -38,22 +38,23 @@ ndk::ScopedAStatus ModulePrimary::getTelephony(std::shared_ptr<ITelephony>* _aid
mTelephony = ndk::SharedRefBase::make<Telephony>();
}
*_aidl_return = mTelephony.getPtr();
LOG(DEBUG) << __func__ << ": returning instance of ITelephony: " << _aidl_return->get();
LOG(DEBUG) << __func__
<< ": returning instance of ITelephony: " << _aidl_return->get()->asBinder().get();
return ndk::ScopedAStatus::ok();
}
ndk::ScopedAStatus ModulePrimary::createInputStream(const SinkMetadata& sinkMetadata,
StreamContext&& context,
ndk::ScopedAStatus ModulePrimary::createInputStream(StreamContext&& context,
const SinkMetadata& sinkMetadata,
const std::vector<MicrophoneInfo>& microphones,
std::shared_ptr<StreamIn>* result) {
return createStreamInstance<StreamInStub>(result, sinkMetadata, std::move(context),
return createStreamInstance<StreamInStub>(result, std::move(context), sinkMetadata,
microphones);
}
ndk::ScopedAStatus ModulePrimary::createOutputStream(
const SourceMetadata& sourceMetadata, StreamContext&& context,
StreamContext&& context, const SourceMetadata& sourceMetadata,
const std::optional<AudioOffloadInfo>& offloadInfo, std::shared_ptr<StreamOut>* result) {
return createStreamInstance<StreamOutStub>(result, sourceMetadata, std::move(context),
return createStreamInstance<StreamOutStub>(result, std::move(context), sourceMetadata,
offloadInfo);
}

View file

@ -47,13 +47,19 @@ void StreamContext::fillDescriptor(StreamDescriptor* desc) {
desc->reply = mReplyMQ->dupeDesc();
}
if (mDataMQ) {
const size_t frameSize = getFrameSize();
desc->frameSizeBytes = frameSize;
desc->bufferSizeFrames = mDataMQ->getQuantumCount() * mDataMQ->getQuantumSize() / frameSize;
desc->frameSizeBytes = getFrameSize();
desc->bufferSizeFrames = getBufferSizeInFrames();
desc->audio.set<StreamDescriptor::AudioBuffer::Tag::fmq>(mDataMQ->dupeDesc());
}
}
size_t StreamContext::getBufferSizeInFrames() const {
if (mDataMQ) {
return mDataMQ->getQuantumCount() * mDataMQ->getQuantumSize() / getFrameSize();
}
return 0;
}
size_t StreamContext::getFrameSize() const {
return getFrameSizeInBytes(mFormat, mChannelLayout);
}
@ -597,18 +603,16 @@ StreamCommonImpl::~StreamCommonImpl() {
ndk::ScopedAStatus StreamCommonImpl::initInstance(
const std::shared_ptr<StreamCommonInterface>& delegate) {
mCommon = ndk::SharedRefBase::make<StreamCommonDelegator>(delegate);
mCommonBinder = mCommon->asBinder();
AIBinder_setMinSchedulerPolicy(mCommonBinder.get(), SCHED_NORMAL, ANDROID_PRIORITY_AUDIO);
return mWorker->start() ? ndk::ScopedAStatus::ok()
: ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
}
ndk::ScopedAStatus StreamCommonImpl::getStreamCommonCommon(
std::shared_ptr<IStreamCommon>* _aidl_return) {
if (mCommon == nullptr) {
if (!mCommon) {
LOG(FATAL) << __func__ << ": the common interface was not created";
}
*_aidl_return = mCommon;
*_aidl_return = mCommon.getPtr();
LOG(DEBUG) << __func__ << ": returning " << _aidl_return->get()->asBinder().get();
return ndk::ScopedAStatus::ok();
}
@ -659,7 +663,7 @@ ndk::ScopedAStatus StreamCommonImpl::close() {
LOG(DEBUG) << __func__ << ": joining the worker thread...";
mWorker->stop();
LOG(DEBUG) << __func__ << ": worker thread joined";
mContext.reset();
onClose();
mWorker->setClosed();
return ndk::ScopedAStatus::ok();
} else {
@ -723,11 +727,15 @@ static std::map<AudioDevice, std::string> transformMicrophones(
}
} // namespace
StreamIn::StreamIn(const std::vector<MicrophoneInfo>& microphones)
: mMicrophones(transformMicrophones(microphones)) {
StreamIn::StreamIn(StreamContext&& context, const std::vector<MicrophoneInfo>& microphones)
: mContext(std::move(context)), mMicrophones(transformMicrophones(microphones)) {
LOG(DEBUG) << __func__;
}
void StreamIn::defaultOnClose() {
mContext.reset();
}
ndk::ScopedAStatus StreamIn::getActiveMicrophones(
std::vector<MicrophoneDynamicInfo>* _aidl_return) {
std::vector<MicrophoneDynamicInfo> result;
@ -780,11 +788,15 @@ ndk::ScopedAStatus StreamIn::setHwGain(const std::vector<float>& in_channelGains
return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
}
StreamOut::StreamOut(const std::optional<AudioOffloadInfo>& offloadInfo)
: mOffloadInfo(offloadInfo) {
StreamOut::StreamOut(StreamContext&& context, const std::optional<AudioOffloadInfo>& offloadInfo)
: mContext(std::move(context)), mOffloadInfo(offloadInfo) {
LOG(DEBUG) << __func__;
}
void StreamOut::defaultOnClose() {
mContext.reset();
}
ndk::ScopedAStatus StreamOut::updateOffloadMetadata(
const AudioOffloadMetadata& in_offloadMetadata) {
LOG(DEBUG) << __func__;

View file

@ -14,44 +14,17 @@
* limitations under the License.
*/
#define LOG_TAG "AHAL_AlsaMixer"
#include <android-base/logging.h>
#include <algorithm>
#include <cmath>
#define LOG_TAG "AHAL_AlsaMixer"
#include <android-base/logging.h>
#include <android/binder_status.h>
#include "Mixer.h"
namespace aidl::android::hardware::audio::core::alsa {
//-----------------------------------------------------------------------------
MixerControl::MixerControl(struct mixer_ctl* ctl)
: mCtl(ctl),
mNumValues(mixer_ctl_get_num_values(ctl)),
mMinValue(mixer_ctl_get_range_min(ctl)),
mMaxValue(mixer_ctl_get_range_max(ctl)) {}
unsigned int MixerControl::getNumValues() const {
return mNumValues;
}
int MixerControl::getMaxValue() const {
return mMaxValue;
}
int MixerControl::getMinValue() const {
return mMinValue;
}
int MixerControl::setArray(const void* array, size_t count) {
const std::lock_guard guard(mLock);
return mixer_ctl_set_array(mCtl, array, count);
}
//-----------------------------------------------------------------------------
// static
const std::map<Mixer::Control, std::vector<Mixer::ControlNamesAndExpectedCtlType>>
Mixer::kPossibleControls = {
@ -60,18 +33,20 @@ const std::map<Mixer::Control, std::vector<Mixer::ControlNamesAndExpectedCtlType
{Mixer::HW_VOLUME,
{{"Headphone Playback Volume", MIXER_CTL_TYPE_INT},
{"Headset Playback Volume", MIXER_CTL_TYPE_INT},
{"PCM Playback Volume", MIXER_CTL_TYPE_INT}}}};
{"PCM Playback Volume", MIXER_CTL_TYPE_INT}}},
{Mixer::MIC_SWITCH, {{"Capture Switch", MIXER_CTL_TYPE_BOOL}}},
{Mixer::MIC_GAIN, {{"Capture Volume", MIXER_CTL_TYPE_INT}}}};
// static
std::map<Mixer::Control, std::shared_ptr<MixerControl>> Mixer::initializeMixerControls(
struct mixer* mixer) {
std::map<Mixer::Control, std::shared_ptr<MixerControl>> mixerControls;
Mixer::Controls Mixer::initializeMixerControls(struct mixer* mixer) {
if (mixer == nullptr) return {};
Controls mixerControls;
std::string mixerCtlNames;
for (const auto& [control, possibleCtls] : kPossibleControls) {
for (const auto& [ctlName, expectedCtlType] : possibleCtls) {
struct mixer_ctl* ctl = mixer_get_ctl_by_name(mixer, ctlName.c_str());
if (ctl != nullptr && mixer_ctl_get_type(ctl) == expectedCtlType) {
mixerControls.emplace(control, std::make_unique<MixerControl>(ctl));
mixerControls.emplace(control, ctl);
if (!mixerCtlNames.empty()) {
mixerCtlNames += ",";
}
@ -84,71 +59,141 @@ std::map<Mixer::Control, std::shared_ptr<MixerControl>> Mixer::initializeMixerCo
return mixerControls;
}
Mixer::Mixer(struct mixer* mixer)
: mMixer(mixer), mMixerControls(initializeMixerControls(mMixer)) {}
std::ostream& operator<<(std::ostream& s, Mixer::Control c) {
switch (c) {
case Mixer::Control::MASTER_SWITCH:
s << "master mute";
break;
case Mixer::Control::MASTER_VOLUME:
s << "master volume";
break;
case Mixer::Control::HW_VOLUME:
s << "volume";
break;
case Mixer::Control::MIC_SWITCH:
s << "mic mute";
break;
case Mixer::Control::MIC_GAIN:
s << "mic gain";
break;
}
return s;
}
Mixer::Mixer(int card) : mMixer(mixer_open(card)), mMixerControls(initializeMixerControls(mMixer)) {
if (!isValid()) {
PLOG(ERROR) << __func__ << ": failed to open mixer for card=" << card;
}
}
Mixer::~Mixer() {
mixer_close(mMixer);
if (isValid()) {
std::lock_guard l(mMixerAccess);
mixer_close(mMixer);
}
}
namespace {
int volumeFloatToInteger(float fValue, int maxValue, int minValue) {
return minValue + std::ceil((maxValue - minValue) * fValue);
}
} // namespace
ndk::ScopedAStatus Mixer::setMasterMute(bool muted) {
auto it = mMixerControls.find(Mixer::MASTER_SWITCH);
if (it == mMixerControls.end()) {
return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
}
const int numValues = it->second->getNumValues();
std::vector<int> values(numValues, muted ? 0 : 1);
if (int err = it->second->setArray(values.data(), numValues); err != 0) {
LOG(ERROR) << __func__ << ": failed to set master mute, err=" << err;
return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
}
return ndk::ScopedAStatus::ok();
return setMixerControlMute(MASTER_SWITCH, muted);
}
ndk::ScopedAStatus Mixer::setMasterVolume(float volume) {
auto it = mMixerControls.find(Mixer::MASTER_VOLUME);
if (it == mMixerControls.end()) {
return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
}
const int numValues = it->second->getNumValues();
std::vector<int> values(numValues, volumeFloatToInteger(volume, it->second->getMaxValue(),
it->second->getMinValue()));
if (int err = it->second->setArray(values.data(), numValues); err != 0) {
LOG(ERROR) << __func__ << ": failed to set master volume, err=" << err;
return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
}
return ndk::ScopedAStatus::ok();
return setMixerControlVolume(MASTER_VOLUME, volume);
}
ndk::ScopedAStatus Mixer::setMicGain(float gain) {
return setMixerControlVolume(MIC_GAIN, gain);
}
ndk::ScopedAStatus Mixer::setMicMute(bool muted) {
return setMixerControlMute(MIC_SWITCH, muted);
}
ndk::ScopedAStatus Mixer::setVolumes(const std::vector<float>& volumes) {
if (!isValid()) {
return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
}
auto it = mMixerControls.find(Mixer::HW_VOLUME);
if (it == mMixerControls.end()) {
return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
}
const int numValues = it->second->getNumValues();
if (numValues < 0) {
LOG(FATAL) << __func__ << ": negative number of values: " << numValues;
}
const int maxValue = it->second->getMaxValue();
const int minValue = it->second->getMinValue();
std::vector<int> values;
size_t i = 0;
for (; i < static_cast<size_t>(numValues) && i < values.size(); ++i) {
values.emplace_back(volumeFloatToInteger(volumes[i], maxValue, minValue));
}
if (int err = it->second->setArray(values.data(), values.size()); err != 0) {
std::vector<int> percents;
std::transform(
volumes.begin(), volumes.end(), std::back_inserter(percents),
[](float volume) -> int { return std::floor(std::clamp(volume, 0.0f, 1.0f) * 100); });
std::lock_guard l(mMixerAccess);
if (int err = setMixerControlPercent(it->second, percents); err != 0) {
LOG(ERROR) << __func__ << ": failed to set volume, err=" << err;
return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
}
return ndk::ScopedAStatus::ok();
}
ndk::ScopedAStatus Mixer::setMixerControlMute(Mixer::Control ctl, bool muted) {
if (!isValid()) {
return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
}
auto it = mMixerControls.find(ctl);
if (it == mMixerControls.end()) {
return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
}
std::lock_guard l(mMixerAccess);
if (int err = setMixerControlValue(it->second, muted ? 0 : 1); err != 0) {
LOG(ERROR) << __func__ << ": failed to set " << ctl << " to " << muted << ", err=" << err;
return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
}
return ndk::ScopedAStatus::ok();
}
ndk::ScopedAStatus Mixer::setMixerControlVolume(Control ctl, float volume) {
if (!isValid()) {
return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
}
auto it = mMixerControls.find(ctl);
if (it == mMixerControls.end()) {
return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
}
volume = std::clamp(volume, 0.0f, 1.0f);
std::lock_guard l(mMixerAccess);
if (int err = setMixerControlPercent(it->second, std::floor(volume * 100)); err != 0) {
LOG(ERROR) << __func__ << ": failed to set " << ctl << " to " << volume << ", err=" << err;
return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
}
return ndk::ScopedAStatus::ok();
}
int Mixer::setMixerControlPercent(struct mixer_ctl* ctl, int percent) {
int ret = 0;
const unsigned int n = mixer_ctl_get_num_values(ctl);
for (unsigned int id = 0; id < n; id++) {
if (int error = mixer_ctl_set_percent(ctl, id, percent); error != 0) {
ret = error;
}
}
return ret;
}
int Mixer::setMixerControlPercent(struct mixer_ctl* ctl, const std::vector<int>& percents) {
int ret = 0;
const unsigned int n = mixer_ctl_get_num_values(ctl);
for (unsigned int id = 0; id < n; id++) {
if (int error = mixer_ctl_set_percent(ctl, id, id < percents.size() ? percents[id] : 0);
error != 0) {
ret = error;
}
}
return ret;
}
int Mixer::setMixerControlValue(struct mixer_ctl* ctl, int value) {
int ret = 0;
const unsigned int n = mixer_ctl_get_num_values(ctl);
for (unsigned int id = 0; id < n; id++) {
if (int error = mixer_ctl_set_value(ctl, id, value); error != 0) {
ret = error;
}
}
return ret;
}
} // namespace aidl::android::hardware::audio::core::alsa

View file

@ -16,6 +16,7 @@
#pragma once
#include <iostream>
#include <map>
#include <memory>
#include <mutex>
@ -31,34 +32,17 @@ extern "C" {
namespace aidl::android::hardware::audio::core::alsa {
class MixerControl {
public:
explicit MixerControl(struct mixer_ctl* ctl);
unsigned int getNumValues() const;
int getMaxValue() const;
int getMinValue() const;
int setArray(const void* array, size_t count);
private:
std::mutex mLock;
// The mixer_ctl object is owned by ALSA and will be released when the mixer is closed.
struct mixer_ctl* mCtl GUARDED_BY(mLock);
const unsigned int mNumValues;
const int mMinValue;
const int mMaxValue;
};
class Mixer {
public:
explicit Mixer(struct mixer* mixer);
explicit Mixer(int card);
~Mixer();
bool isValid() const { return mMixer != nullptr; }
ndk::ScopedAStatus setMasterMute(bool muted);
ndk::ScopedAStatus setMasterVolume(float volume);
ndk::ScopedAStatus setMicGain(float gain);
ndk::ScopedAStatus setMicMute(bool muted);
ndk::ScopedAStatus setVolumes(const std::vector<float>& volumes);
private:
@ -66,17 +50,32 @@ class Mixer {
MASTER_SWITCH,
MASTER_VOLUME,
HW_VOLUME,
MIC_SWITCH,
MIC_GAIN,
};
using ControlNamesAndExpectedCtlType = std::pair<std::string, enum mixer_ctl_type>;
static const std::map<Control, std::vector<ControlNamesAndExpectedCtlType>> kPossibleControls;
static std::map<Control, std::shared_ptr<MixerControl>> initializeMixerControls(
struct mixer* mixer);
using Controls = std::map<Control, struct mixer_ctl*>;
friend std::ostream& operator<<(std::ostream&, Control);
static const std::map<Control, std::vector<ControlNamesAndExpectedCtlType>> kPossibleControls;
static Controls initializeMixerControls(struct mixer* mixer);
ndk::ScopedAStatus setMixerControlMute(Control ctl, bool muted);
ndk::ScopedAStatus setMixerControlVolume(Control ctl, float volume);
int setMixerControlPercent(struct mixer_ctl* ctl, int percent) REQUIRES(mMixerAccess);
int setMixerControlPercent(struct mixer_ctl* ctl, const std::vector<int>& percents)
REQUIRES(mMixerAccess);
int setMixerControlValue(struct mixer_ctl* ctl, int value) REQUIRES(mMixerAccess);
// Since ALSA functions do not use internal locking, enforce thread safety at our level.
std::mutex mMixerAccess;
// The mixer object is owned by ALSA and will be released when the mixer is closed.
struct mixer* mMixer;
struct mixer* const mMixer;
// `mMixerControls` will only be initialized in constructor. After that, it wil only be
// read but not be modified.
const std::map<Control, std::shared_ptr<MixerControl>> mMixerControls;
// read but not be modified. Each mixer_ctl object is owned by ALSA, it's life span is
// the same as of the mixer itself.
const Controls mMixerControls;
};
} // namespace aidl::android::hardware::audio::core::alsa

View file

@ -27,16 +27,32 @@
namespace aidl::android::hardware::audio::core {
StreamAlsa::StreamAlsa(const Metadata& metadata, StreamContext&& context)
: StreamCommonImpl(metadata, std::move(context)),
StreamAlsa::StreamAlsa(const StreamContext& context, const Metadata& metadata, int readWriteRetries)
: StreamCommonImpl(context, metadata),
mFrameSizeBytes(getContext().getFrameSize()),
mIsInput(isInput(metadata)),
mConfig(alsa::getPcmConfig(getContext(), mIsInput)) {}
mConfig(alsa::getPcmConfig(getContext(), mIsInput)),
mReadWriteRetries(readWriteRetries) {}
::android::status_t StreamAlsa::init() {
return mConfig.has_value() ? ::android::OK : ::android::NO_INIT;
}
::android::status_t StreamAlsa::drain(StreamDescriptor::DrainMode) {
usleep(1000);
return ::android::OK;
}
::android::status_t StreamAlsa::flush() {
usleep(1000);
return ::android::OK;
}
::android::status_t StreamAlsa::pause() {
usleep(1000);
return ::android::OK;
}
::android::status_t StreamAlsa::standby() {
mAlsaDeviceProxies.clear();
return ::android::OK;
@ -45,27 +61,21 @@ StreamAlsa::StreamAlsa(const Metadata& metadata, StreamContext&& context)
::android::status_t StreamAlsa::start() {
decltype(mAlsaDeviceProxies) alsaDeviceProxies;
for (const auto& device : getDeviceProfiles()) {
auto profile = alsa::readAlsaDeviceInfo(device);
if (!profile.has_value()) {
LOG(ERROR) << __func__ << ": unable to read device info, device address=" << device;
return ::android::UNKNOWN_ERROR;
alsa::DeviceProxy proxy;
if (device.isExternal) {
// Always ask alsa configure as required since the configuration should be supported
// by the connected device. That is guaranteed by `setAudioPortConfig` and
// `setAudioPatch`.
proxy = alsa::openProxyForExternalDevice(
device, const_cast<struct pcm_config*>(&mConfig.value()),
true /*require_exact_match*/);
} else {
proxy = alsa::openProxyForAttachedDevice(
device, const_cast<struct pcm_config*>(&mConfig.value()),
getContext().getBufferSizeInFrames());
}
auto proxy = alsa::makeDeviceProxy();
// Always ask for alsa configure as required since the configuration should be supported
// by the connected device. That is guaranteed by `setAudioPortConfig` and `setAudioPatch`.
if (int err = proxy_prepare(proxy.get(), &profile.value(),
const_cast<struct pcm_config*>(&mConfig.value()),
true /*require_exact_match*/);
err != 0) {
LOG(ERROR) << __func__ << ": fail to prepare for device address=" << device
<< " error=" << err;
return ::android::UNKNOWN_ERROR;
}
if (int err = proxy_open(proxy.get()); err != 0) {
LOG(ERROR) << __func__ << ": failed to open device, address=" << device
<< " error=" << err;
return ::android::UNKNOWN_ERROR;
if (!proxy) {
return ::android::NO_INIT;
}
alsaDeviceProxies.push_back(std::move(proxy));
}
@ -83,11 +93,12 @@ StreamAlsa::StreamAlsa(const Metadata& metadata, StreamContext&& context)
return ::android::NO_INIT;
}
// For input case, only support single device.
proxy_read(mAlsaDeviceProxies[0].get(), buffer, bytesToTransfer);
proxy_read_with_retries(mAlsaDeviceProxies[0].get(), buffer, bytesToTransfer,
mReadWriteRetries);
maxLatency = proxy_get_latency(mAlsaDeviceProxies[0].get());
} else {
for (auto& proxy : mAlsaDeviceProxies) {
proxy_write(proxy.get(), buffer, bytesToTransfer);
proxy_write_with_retries(proxy.get(), buffer, bytesToTransfer, mReadWriteRetries);
maxLatency = std::max(maxLatency, proxy_get_latency(proxy.get()));
}
}

View file

@ -217,7 +217,8 @@ std::optional<DeviceProfile> getDeviceProfile(
}
return DeviceProfile{.card = alsaAddress[0],
.device = alsaAddress[1],
.direction = isInput ? PCM_IN : PCM_OUT};
.direction = isInput ? PCM_IN : PCM_OUT,
.isExternal = !audioDevice.type.connection.empty()};
}
std::optional<DeviceProfile> getDeviceProfile(
@ -269,6 +270,57 @@ DeviceProxy makeDeviceProxy() {
});
}
DeviceProxy openProxyForAttachedDevice(const DeviceProfile& deviceProfile,
struct pcm_config* pcmConfig, size_t bufferFrameCount) {
if (deviceProfile.isExternal) {
LOG(FATAL) << __func__ << ": called for an external device, address=" << deviceProfile;
}
alsa_device_profile profile;
profile_init(&profile, deviceProfile.direction);
profile.card = deviceProfile.card;
profile.device = deviceProfile.device;
if (!profile_fill_builtin_device_info(&profile, pcmConfig, bufferFrameCount)) {
LOG(FATAL) << __func__ << ": failed to init for built-in device, address=" << deviceProfile;
}
auto proxy = makeDeviceProxy();
if (int err = proxy_prepare_from_default_config(proxy.get(), &profile); err != 0) {
LOG(FATAL) << __func__ << ": fail to prepare for device address=" << deviceProfile
<< " error=" << err;
return nullptr;
}
if (int err = proxy_open(proxy.get()); err != 0) {
LOG(ERROR) << __func__ << ": failed to open device, address=" << deviceProfile
<< " error=" << err;
return nullptr;
}
return proxy;
}
DeviceProxy openProxyForExternalDevice(const DeviceProfile& deviceProfile,
struct pcm_config* pcmConfig, bool requireExactMatch) {
if (!deviceProfile.isExternal) {
LOG(FATAL) << __func__ << ": called for an attached device, address=" << deviceProfile;
}
auto profile = readAlsaDeviceInfo(deviceProfile);
if (!profile.has_value()) {
LOG(ERROR) << __func__ << ": unable to read device info, device address=" << deviceProfile;
return nullptr;
}
auto proxy = makeDeviceProxy();
if (int err = proxy_prepare(proxy.get(), &profile.value(), pcmConfig, requireExactMatch);
err != 0) {
LOG(ERROR) << __func__ << ": fail to prepare for device address=" << deviceProfile
<< " error=" << err;
return nullptr;
}
if (int err = proxy_open(proxy.get()); err != 0) {
LOG(ERROR) << __func__ << ": failed to open device, address=" << deviceProfile
<< " error=" << err;
return nullptr;
}
return proxy;
}
std::optional<alsa_device_profile> readAlsaDeviceInfo(const DeviceProfile& deviceProfile) {
alsa_device_profile profile;
profile_init(&profile, deviceProfile.direction);

View file

@ -40,6 +40,7 @@ struct DeviceProfile {
int card;
int device;
int direction; /* PCM_OUT or PCM_IN */
bool isExternal;
};
std::ostream& operator<<(std::ostream& os, const DeviceProfile& device);
using DeviceProxyDeleter = std::function<void(alsa_device_proxy*)>;
@ -60,6 +61,10 @@ std::optional<DeviceProfile> getDeviceProfile(
std::optional<struct pcm_config> getPcmConfig(const StreamContext& context, bool isInput);
std::vector<int> getSampleRatesFromProfile(const alsa_device_profile* profile);
DeviceProxy makeDeviceProxy();
DeviceProxy openProxyForAttachedDevice(const DeviceProfile& deviceProfile,
struct pcm_config* pcmConfig, size_t bufferFrameCount);
DeviceProxy openProxyForExternalDevice(const DeviceProfile& deviceProfile,
struct pcm_config* pcmConfig, bool requireExactMatch);
std::optional<alsa_device_profile> readAlsaDeviceInfo(const DeviceProfile& deviceProfile);
::aidl::android::media::audio::common::AudioFormatDescription

View file

@ -159,13 +159,13 @@ class Module : public BnModule {
// The following virtual functions are intended for vendor extension via inheritance.
virtual ndk::ScopedAStatus createInputStream(
const ::aidl::android::hardware::audio::common::SinkMetadata& sinkMetadata,
StreamContext&& context,
const ::aidl::android::hardware::audio::common::SinkMetadata& sinkMetadata,
const std::vector<::aidl::android::media::audio::common::MicrophoneInfo>& microphones,
std::shared_ptr<StreamIn>* result) = 0;
virtual ndk::ScopedAStatus createOutputStream(
const ::aidl::android::hardware::audio::common::SourceMetadata& sourceMetadata,
StreamContext&& context,
const ::aidl::android::hardware::audio::common::SourceMetadata& sourceMetadata,
const std::optional<::aidl::android::media::audio::common::AudioOffloadInfo>&
offloadInfo,
std::shared_ptr<StreamOut>* result) = 0;

View file

@ -28,13 +28,13 @@ class ModulePrimary final : public Module {
ndk::ScopedAStatus getTelephony(std::shared_ptr<ITelephony>* _aidl_return) override;
ndk::ScopedAStatus createInputStream(
const ::aidl::android::hardware::audio::common::SinkMetadata& sinkMetadata,
StreamContext&& context,
const ::aidl::android::hardware::audio::common::SinkMetadata& sinkMetadata,
const std::vector<::aidl::android::media::audio::common::MicrophoneInfo>& microphones,
std::shared_ptr<StreamIn>* result) override;
ndk::ScopedAStatus createOutputStream(
const ::aidl::android::hardware::audio::common::SourceMetadata& sourceMetadata,
StreamContext&& context,
const ::aidl::android::hardware::audio::common::SourceMetadata& sourceMetadata,
const std::optional<::aidl::android::media::audio::common::AudioOffloadInfo>&
offloadInfo,
std::shared_ptr<StreamOut>* result) override;

View file

@ -33,13 +33,13 @@ class ModuleRemoteSubmix : public Module {
// Module interfaces
ndk::ScopedAStatus createInputStream(
const ::aidl::android::hardware::audio::common::SinkMetadata& sinkMetadata,
StreamContext&& context,
const ::aidl::android::hardware::audio::common::SinkMetadata& sinkMetadata,
const std::vector<::aidl::android::media::audio::common::MicrophoneInfo>& microphones,
std::shared_ptr<StreamIn>* result) override;
ndk::ScopedAStatus createOutputStream(
const ::aidl::android::hardware::audio::common::SourceMetadata& sourceMetadata,
StreamContext&& context,
const ::aidl::android::hardware::audio::common::SourceMetadata& sourceMetadata,
const std::optional<::aidl::android::media::audio::common::AudioOffloadInfo>&
offloadInfo,
std::shared_ptr<StreamOut>* result) override;

View file

@ -30,13 +30,13 @@ class ModuleStub final : public Module {
ndk::ScopedAStatus getBluetoothLe(std::shared_ptr<IBluetoothLe>* _aidl_return) override;
ndk::ScopedAStatus createInputStream(
const ::aidl::android::hardware::audio::common::SinkMetadata& sinkMetadata,
StreamContext&& context,
const ::aidl::android::hardware::audio::common::SinkMetadata& sinkMetadata,
const std::vector<::aidl::android::media::audio::common::MicrophoneInfo>& microphones,
std::shared_ptr<StreamIn>* result) override;
ndk::ScopedAStatus createOutputStream(
const ::aidl::android::hardware::audio::common::SourceMetadata& sourceMetadata,
StreamContext&& context,
const ::aidl::android::hardware::audio::common::SourceMetadata& sourceMetadata,
const std::optional<::aidl::android::media::audio::common::AudioOffloadInfo>&
offloadInfo,
std::shared_ptr<StreamOut>* result) override;

View file

@ -33,13 +33,13 @@ class ModuleUsb final : public ModuleAlsa {
// Module interfaces
ndk::ScopedAStatus createInputStream(
const ::aidl::android::hardware::audio::common::SinkMetadata& sinkMetadata,
StreamContext&& context,
const ::aidl::android::hardware::audio::common::SinkMetadata& sinkMetadata,
const std::vector<::aidl::android::media::audio::common::MicrophoneInfo>& microphones,
std::shared_ptr<StreamIn>* result) override;
ndk::ScopedAStatus createOutputStream(
const ::aidl::android::hardware::audio::common::SourceMetadata& sourceMetadata,
StreamContext&& context,
const ::aidl::android::hardware::audio::common::SourceMetadata& sourceMetadata,
const std::optional<::aidl::android::media::audio::common::AudioOffloadInfo>&
offloadInfo,
std::shared_ptr<StreamOut>* result) override;

View file

@ -43,6 +43,7 @@
#include <system/thread_defs.h>
#include <utils/Errors.h>
#include "core-impl/ChildInterface.h"
#include "core-impl/utils.h"
namespace aidl::android::hardware::audio::core {
@ -132,6 +133,7 @@ class StreamContext {
void fillDescriptor(StreamDescriptor* desc);
std::shared_ptr<IStreamCallback> getAsyncCallback() const { return mAsyncCallback; }
size_t getBufferSizeInFrames() const;
::aidl::android::media::audio::common::AudioChannelLayout getChannelLayout() const {
return mChannelLayout;
}
@ -409,16 +411,17 @@ class StreamCommonDelegator : public BnStreamCommon {
};
// The implementation of DriverInterface must be provided by each concrete stream implementation.
// Note that StreamCommonImpl does not own the context. This is to support swapping on the fly
// implementations of the stream while keeping the same IStreamIn/Out instance. It's that instance
// who must be owner of the context.
class StreamCommonImpl : virtual public StreamCommonInterface, virtual public DriverInterface {
public:
StreamCommonImpl(const Metadata& metadata, StreamContext&& context,
StreamCommonImpl(const StreamContext& context, const Metadata& metadata,
const StreamWorkerInterface::CreateInstance& createWorker)
: mMetadata(metadata),
mContext(std::move(context)),
mWorker(createWorker(mContext, this)) {}
StreamCommonImpl(const Metadata& metadata, StreamContext&& context)
: mContext(context), mMetadata(metadata), mWorker(createWorker(mContext, this)) {}
StreamCommonImpl(const StreamContext& context, const Metadata& metadata)
: StreamCommonImpl(
metadata, std::move(context),
context, metadata,
isInput(metadata) ? getDefaultInWorkerCreator() : getDefaultOutWorkerCreator()) {}
~StreamCommonImpl();
@ -460,13 +463,13 @@ class StreamCommonImpl : virtual public StreamCommonInterface, virtual public Dr
};
}
virtual void onClose() = 0;
void stopWorker();
const StreamContext& mContext;
Metadata mMetadata;
StreamContext mContext;
std::unique_ptr<StreamWorkerInterface> mWorker;
std::shared_ptr<StreamCommonDelegator> mCommon;
ndk::SpAIBinder mCommonBinder;
ChildInterface<StreamCommonDelegator> mCommon;
ConnectedDevices mConnectedDevices;
};
@ -474,6 +477,8 @@ class StreamCommonImpl : virtual public StreamCommonInterface, virtual public Dr
// concrete input/output stream implementations.
class StreamIn : virtual public StreamCommonInterface, public BnStreamIn {
protected:
void defaultOnClose();
ndk::ScopedAStatus getStreamCommon(std::shared_ptr<IStreamCommon>* _aidl_return) override {
return getStreamCommonCommon(_aidl_return);
}
@ -493,14 +498,17 @@ class StreamIn : virtual public StreamCommonInterface, public BnStreamIn {
friend class ndk::SharedRefBase;
explicit StreamIn(
const std::vector<::aidl::android::media::audio::common::MicrophoneInfo>& microphones);
StreamIn(StreamContext&& context,
const std::vector<::aidl::android::media::audio::common::MicrophoneInfo>& microphones);
StreamContext mContext;
const std::map<::aidl::android::media::audio::common::AudioDevice, std::string> mMicrophones;
};
class StreamOut : virtual public StreamCommonInterface, public BnStreamOut {
protected:
void defaultOnClose();
ndk::ScopedAStatus getStreamCommon(std::shared_ptr<IStreamCommon>* _aidl_return) override {
return getStreamCommonCommon(_aidl_return);
}
@ -534,10 +542,12 @@ class StreamOut : virtual public StreamCommonInterface, public BnStreamOut {
friend class ndk::SharedRefBase;
explicit StreamOut(const std::optional<::aidl::android::media::audio::common::AudioOffloadInfo>&
offloadInfo);
StreamOut(StreamContext&& context,
const std::optional<::aidl::android::media::audio::common::AudioOffloadInfo>&
offloadInfo);
std::optional<::aidl::android::media::audio::common::AudioOffloadInfo> mOffloadInfo;
StreamContext mContext;
const std::optional<::aidl::android::media::audio::common::AudioOffloadInfo> mOffloadInfo;
std::optional<::aidl::android::hardware::audio::common::AudioOffloadMetadata> mOffloadMetadata;
};

View file

@ -31,9 +31,12 @@ namespace aidl::android::hardware::audio::core {
// provide necessary overrides for all interface methods omitted here.
class StreamAlsa : public StreamCommonImpl {
public:
StreamAlsa(const Metadata& metadata, StreamContext&& context);
StreamAlsa(const StreamContext& context, const Metadata& metadata, int readWriteRetries);
// 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,
@ -48,6 +51,7 @@ class StreamAlsa : public StreamCommonImpl {
const size_t mFrameSizeBytes;
const bool mIsInput;
const std::optional<struct pcm_config> mConfig;
const int mReadWriteRetries;
// All fields below are only used on the worker thread.
std::vector<alsa::DeviceProxy> mAlsaDeviceProxies;
};

View file

@ -29,7 +29,7 @@ using aidl::android::hardware::audio::core::r_submix::SubmixRoute;
class StreamRemoteSubmix : public StreamCommonImpl {
public:
StreamRemoteSubmix(const Metadata& metadata, StreamContext&& context);
StreamRemoteSubmix(const StreamContext& context, const Metadata& metadata);
::android::status_t init() override;
::android::status_t drain(StreamDescriptor::DrainMode) override;
@ -72,28 +72,32 @@ class StreamRemoteSubmix : public StreamCommonImpl {
static constexpr int kReadAttemptSleepUs = 5000;
};
class StreamInRemoteSubmix final : public StreamRemoteSubmix, public StreamIn {
class StreamInRemoteSubmix final : public StreamIn, public StreamRemoteSubmix {
public:
friend class ndk::SharedRefBase;
StreamInRemoteSubmix(
const ::aidl::android::hardware::audio::common::SinkMetadata& sinkMetadata,
StreamContext&& context,
const ::aidl::android::hardware::audio::common::SinkMetadata& sinkMetadata,
const std::vector<::aidl::android::media::audio::common::MicrophoneInfo>& microphones);
private:
void onClose() override { defaultOnClose(); }
ndk::ScopedAStatus getActiveMicrophones(
std::vector<::aidl::android::media::audio::common::MicrophoneDynamicInfo>* _aidl_return)
override;
};
class StreamOutRemoteSubmix final : public StreamRemoteSubmix, public StreamOut {
class StreamOutRemoteSubmix final : public StreamOut, public StreamRemoteSubmix {
public:
friend class ndk::SharedRefBase;
StreamOutRemoteSubmix(
const ::aidl::android::hardware::audio::common::SourceMetadata& sourceMetadata,
StreamContext&& context,
const ::aidl::android::hardware::audio::common::SourceMetadata& sourceMetadata,
const std::optional<::aidl::android::media::audio::common::AudioOffloadInfo>&
offloadInfo);
private:
void onClose() override { defaultOnClose(); }
};
} // namespace aidl::android::hardware::audio::core

View file

@ -22,7 +22,7 @@ namespace aidl::android::hardware::audio::core {
class StreamStub : public StreamCommonImpl {
public:
StreamStub(const Metadata& metadata, StreamContext&& context);
StreamStub(const StreamContext& context, const Metadata& metadata);
// Methods of 'DriverInterface'.
::android::status_t init() override;
::android::status_t drain(StreamDescriptor::DrainMode) override;
@ -43,22 +43,28 @@ class StreamStub : public StreamCommonImpl {
bool mIsStandby = true; // Used for validating the state machine logic.
};
class StreamInStub final : public StreamStub, public StreamIn {
class StreamInStub final : public StreamIn, public StreamStub {
public:
friend class ndk::SharedRefBase;
StreamInStub(
const ::aidl::android::hardware::audio::common::SinkMetadata& sinkMetadata,
StreamContext&& context,
const ::aidl::android::hardware::audio::common::SinkMetadata& sinkMetadata,
const std::vector<::aidl::android::media::audio::common::MicrophoneInfo>& microphones);
private:
void onClose() override { defaultOnClose(); }
};
class StreamOutStub final : public StreamStub, public StreamOut {
class StreamOutStub final : public StreamOut, public StreamStub {
public:
friend class ndk::SharedRefBase;
StreamOutStub(const ::aidl::android::hardware::audio::common::SourceMetadata& sourceMetadata,
StreamContext&& context,
StreamOutStub(StreamContext&& context,
const ::aidl::android::hardware::audio::common::SourceMetadata& sourceMetadata,
const std::optional<::aidl::android::media::audio::common::AudioOffloadInfo>&
offloadInfo);
private:
void onClose() override { defaultOnClose(); }
};
} // namespace aidl::android::hardware::audio::core

View file

@ -28,11 +28,8 @@ namespace aidl::android::hardware::audio::core {
class StreamUsb : public StreamAlsa {
public:
StreamUsb(const Metadata& metadata, StreamContext&& context);
StreamUsb(const StreamContext& context, const Metadata& metadata);
// Methods of 'DriverInterface'.
::android::status_t drain(StreamDescriptor::DrainMode) override;
::android::status_t flush() override;
::android::status_t pause() override;
::android::status_t transfer(void* buffer, size_t frameCount, size_t* actualFrameCount,
int32_t* latencyMs) override;
@ -47,29 +44,31 @@ class StreamUsb : public StreamAlsa {
std::atomic<bool> mConnectedDevicesUpdated = false;
};
class StreamInUsb final : public StreamUsb, public StreamIn {
class StreamInUsb final : public StreamIn, public StreamUsb {
public:
friend class ndk::SharedRefBase;
StreamInUsb(
const ::aidl::android::hardware::audio::common::SinkMetadata& sinkMetadata,
StreamContext&& context,
const ::aidl::android::hardware::audio::common::SinkMetadata& sinkMetadata,
const std::vector<::aidl::android::media::audio::common::MicrophoneInfo>& microphones);
private:
void onClose() override { defaultOnClose(); }
ndk::ScopedAStatus getActiveMicrophones(
std::vector<::aidl::android::media::audio::common::MicrophoneDynamicInfo>* _aidl_return)
override;
};
class StreamOutUsb final : public StreamUsb, public StreamOut {
class StreamOutUsb final : public StreamOut, public StreamUsb {
public:
friend class ndk::SharedRefBase;
StreamOutUsb(const ::aidl::android::hardware::audio::common::SourceMetadata& sourceMetadata,
StreamContext&& context,
StreamOutUsb(StreamContext&& context,
const ::aidl::android::hardware::audio::common::SourceMetadata& sourceMetadata,
const std::optional<::aidl::android::media::audio::common::AudioOffloadInfo>&
offloadInfo);
private:
void onClose() override { defaultOnClose(); }
ndk::ScopedAStatus getHwVolume(std::vector<float>* _aidl_return) override;
ndk::ScopedAStatus setHwVolume(const std::vector<float>& in_channelVolumes) override;

View file

@ -56,16 +56,16 @@ ndk::ScopedAStatus ModuleRemoteSubmix::setMicMute(bool in_mute __unused) {
}
ndk::ScopedAStatus ModuleRemoteSubmix::createInputStream(
const SinkMetadata& sinkMetadata, StreamContext&& context,
StreamContext&& context, const SinkMetadata& sinkMetadata,
const std::vector<MicrophoneInfo>& microphones, std::shared_ptr<StreamIn>* result) {
return createStreamInstance<StreamInRemoteSubmix>(result, sinkMetadata, std::move(context),
return createStreamInstance<StreamInRemoteSubmix>(result, std::move(context), sinkMetadata,
microphones);
}
ndk::ScopedAStatus ModuleRemoteSubmix::createOutputStream(
const SourceMetadata& sourceMetadata, StreamContext&& context,
StreamContext&& context, const SourceMetadata& sourceMetadata,
const std::optional<AudioOffloadInfo>& offloadInfo, std::shared_ptr<StreamOut>* result) {
return createStreamInstance<StreamOutRemoteSubmix>(result, sourceMetadata, std::move(context),
return createStreamInstance<StreamOutRemoteSubmix>(result, std::move(context), sourceMetadata,
offloadInfo);
}

View file

@ -29,8 +29,8 @@ using aidl::android::media::audio::common::MicrophoneInfo;
namespace aidl::android::hardware::audio::core {
StreamRemoteSubmix::StreamRemoteSubmix(const Metadata& metadata, StreamContext&& context)
: StreamCommonImpl(metadata, std::move(context)),
StreamRemoteSubmix::StreamRemoteSubmix(const StreamContext& context, const Metadata& metadata)
: StreamCommonImpl(context, metadata),
mPortId(context.getPortId()),
mIsInput(isInput(metadata)) {
mStreamConfig.frameSize = context.getFrameSize();
@ -353,10 +353,11 @@ size_t StreamRemoteSubmix::getStreamPipeSizeInFrames() {
return ::android::OK;
}
StreamInRemoteSubmix::StreamInRemoteSubmix(const SinkMetadata& sinkMetadata,
StreamContext&& context,
StreamInRemoteSubmix::StreamInRemoteSubmix(StreamContext&& context,
const SinkMetadata& sinkMetadata,
const std::vector<MicrophoneInfo>& microphones)
: StreamRemoteSubmix(sinkMetadata, std::move(context)), StreamIn(microphones) {}
: StreamIn(std::move(context), microphones),
StreamRemoteSubmix(StreamIn::mContext, sinkMetadata) {}
ndk::ScopedAStatus StreamInRemoteSubmix::getActiveMicrophones(
std::vector<MicrophoneDynamicInfo>* _aidl_return) {
@ -365,9 +366,10 @@ ndk::ScopedAStatus StreamInRemoteSubmix::getActiveMicrophones(
return ndk::ScopedAStatus::ok();
}
StreamOutRemoteSubmix::StreamOutRemoteSubmix(const SourceMetadata& sourceMetadata,
StreamContext&& context,
StreamOutRemoteSubmix::StreamOutRemoteSubmix(StreamContext&& context,
const SourceMetadata& sourceMetadata,
const std::optional<AudioOffloadInfo>& offloadInfo)
: StreamRemoteSubmix(sourceMetadata, std::move(context)), StreamOut(offloadInfo) {}
: StreamOut(std::move(context), offloadInfo),
StreamRemoteSubmix(StreamOut::mContext, sourceMetadata) {}
} // namespace aidl::android::hardware::audio::core

View file

@ -38,7 +38,8 @@ ndk::ScopedAStatus ModuleStub::getBluetooth(std::shared_ptr<IBluetooth>* _aidl_r
mBluetooth = ndk::SharedRefBase::make<Bluetooth>();
}
*_aidl_return = mBluetooth.getPtr();
LOG(DEBUG) << __func__ << ": returning instance of IBluetooth: " << _aidl_return->get();
LOG(DEBUG) << __func__
<< ": returning instance of IBluetooth: " << _aidl_return->get()->asBinder().get();
return ndk::ScopedAStatus::ok();
}
@ -47,7 +48,8 @@ ndk::ScopedAStatus ModuleStub::getBluetoothA2dp(std::shared_ptr<IBluetoothA2dp>*
mBluetoothA2dp = ndk::SharedRefBase::make<BluetoothA2dp>();
}
*_aidl_return = mBluetoothA2dp.getPtr();
LOG(DEBUG) << __func__ << ": returning instance of IBluetoothA2dp: " << _aidl_return->get();
LOG(DEBUG) << __func__ << ": returning instance of IBluetoothA2dp: "
<< _aidl_return->get()->asBinder().get();
return ndk::ScopedAStatus::ok();
}
@ -56,22 +58,23 @@ ndk::ScopedAStatus ModuleStub::getBluetoothLe(std::shared_ptr<IBluetoothLe>* _ai
mBluetoothLe = ndk::SharedRefBase::make<BluetoothLe>();
}
*_aidl_return = mBluetoothLe.getPtr();
LOG(DEBUG) << __func__ << ": returning instance of IBluetoothLe: " << _aidl_return->get();
LOG(DEBUG) << __func__
<< ": returning instance of IBluetoothLe: " << _aidl_return->get()->asBinder().get();
return ndk::ScopedAStatus::ok();
}
ndk::ScopedAStatus ModuleStub::createInputStream(const SinkMetadata& sinkMetadata,
StreamContext&& context,
ndk::ScopedAStatus ModuleStub::createInputStream(StreamContext&& context,
const SinkMetadata& sinkMetadata,
const std::vector<MicrophoneInfo>& microphones,
std::shared_ptr<StreamIn>* result) {
return createStreamInstance<StreamInStub>(result, sinkMetadata, std::move(context),
return createStreamInstance<StreamInStub>(result, std::move(context), sinkMetadata,
microphones);
}
ndk::ScopedAStatus ModuleStub::createOutputStream(
const SourceMetadata& sourceMetadata, StreamContext&& context,
StreamContext&& context, const SourceMetadata& sourceMetadata,
const std::optional<AudioOffloadInfo>& offloadInfo, std::shared_ptr<StreamOut>* result) {
return createStreamInstance<StreamOutStub>(result, sourceMetadata, std::move(context),
return createStreamInstance<StreamOutStub>(result, std::move(context), sourceMetadata,
offloadInfo);
}

View file

@ -31,8 +31,8 @@ using aidl::android::media::audio::common::MicrophoneInfo;
namespace aidl::android::hardware::audio::core {
StreamStub::StreamStub(const Metadata& metadata, StreamContext&& context)
: StreamCommonImpl(metadata, std::move(context)),
StreamStub::StreamStub(const StreamContext& context, const Metadata& metadata)
: StreamCommonImpl(context, metadata),
mFrameSizeBytes(getContext().getFrameSize()),
mSampleRate(getContext().getSampleRate()),
mIsAsynchronous(!!getContext().getAsyncCallback()),
@ -118,12 +118,12 @@ void StreamStub::shutdown() {
mIsInitialized = false;
}
StreamInStub::StreamInStub(const SinkMetadata& sinkMetadata, StreamContext&& context,
StreamInStub::StreamInStub(StreamContext&& context, const SinkMetadata& sinkMetadata,
const std::vector<MicrophoneInfo>& microphones)
: StreamStub(sinkMetadata, std::move(context)), StreamIn(microphones) {}
: StreamIn(std::move(context), microphones), StreamStub(StreamIn::mContext, sinkMetadata) {}
StreamOutStub::StreamOutStub(const SourceMetadata& sourceMetadata, StreamContext&& context,
StreamOutStub::StreamOutStub(StreamContext&& context, const SourceMetadata& sourceMetadata,
const std::optional<AudioOffloadInfo>& offloadInfo)
: StreamStub(sourceMetadata, std::move(context)), StreamOut(offloadInfo) {}
: StreamOut(std::move(context), offloadInfo), StreamStub(StreamOut::mContext, sourceMetadata) {}
} // namespace aidl::android::hardware::audio::core

View file

@ -68,22 +68,22 @@ ndk::ScopedAStatus ModuleUsb::setMicMute(bool in_mute __unused) {
return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
}
ndk::ScopedAStatus ModuleUsb::createInputStream(const SinkMetadata& sinkMetadata,
StreamContext&& context,
ndk::ScopedAStatus ModuleUsb::createInputStream(StreamContext&& context,
const SinkMetadata& sinkMetadata,
const std::vector<MicrophoneInfo>& microphones,
std::shared_ptr<StreamIn>* result) {
return createStreamInstance<StreamInUsb>(result, sinkMetadata, std::move(context), microphones);
return createStreamInstance<StreamInUsb>(result, std::move(context), sinkMetadata, microphones);
}
ndk::ScopedAStatus ModuleUsb::createOutputStream(const SourceMetadata& sourceMetadata,
StreamContext&& context,
ndk::ScopedAStatus ModuleUsb::createOutputStream(StreamContext&& context,
const SourceMetadata& sourceMetadata,
const std::optional<AudioOffloadInfo>& offloadInfo,
std::shared_ptr<StreamOut>* result) {
if (offloadInfo.has_value()) {
LOG(ERROR) << __func__ << ": offload is not supported";
return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
}
return createStreamInstance<StreamOutUsb>(result, sourceMetadata, std::move(context),
return createStreamInstance<StreamOutUsb>(result, std::move(context), sourceMetadata,
offloadInfo);
}

View file

@ -35,8 +35,8 @@ using aidl::android::media::audio::common::MicrophoneInfo;
namespace aidl::android::hardware::audio::core {
StreamUsb::StreamUsb(const Metadata& metadata, StreamContext&& context)
: StreamAlsa(metadata, std::move(context)) {}
StreamUsb::StreamUsb(const StreamContext& context, const Metadata& metadata)
: StreamAlsa(context, metadata, 1 /*readWriteRetries*/) {}
ndk::ScopedAStatus StreamUsb::setConnectedDevices(
const std::vector<AudioDevice>& connectedDevices) {
@ -55,28 +55,13 @@ ndk::ScopedAStatus StreamUsb::setConnectedDevices(
}
connectedDeviceProfiles.push_back(*profile);
}
RETURN_STATUS_IF_ERROR(StreamCommonImpl::setConnectedDevices(connectedDevices));
RETURN_STATUS_IF_ERROR(setConnectedDevices(connectedDevices));
std::lock_guard guard(mLock);
mConnectedDeviceProfiles = std::move(connectedDeviceProfiles);
mConnectedDevicesUpdated.store(true, std::memory_order_release);
return ndk::ScopedAStatus::ok();
}
::android::status_t StreamUsb::drain(StreamDescriptor::DrainMode) {
usleep(1000);
return ::android::OK;
}
::android::status_t StreamUsb::flush() {
usleep(1000);
return ::android::OK;
}
::android::status_t StreamUsb::pause() {
usleep(1000);
return ::android::OK;
}
::android::status_t StreamUsb::transfer(void* buffer, size_t frameCount, size_t* actualFrameCount,
int32_t* latencyMs) {
if (mConnectedDevicesUpdated.load(std::memory_order_acquire)) {
@ -98,9 +83,9 @@ std::vector<alsa::DeviceProfile> StreamUsb::getDeviceProfiles() {
return connectedDevices;
}
StreamInUsb::StreamInUsb(const SinkMetadata& sinkMetadata, StreamContext&& context,
StreamInUsb::StreamInUsb(StreamContext&& context, const SinkMetadata& sinkMetadata,
const std::vector<MicrophoneInfo>& microphones)
: StreamUsb(sinkMetadata, std::move(context)), StreamIn(microphones) {}
: StreamIn(std::move(context), microphones), StreamUsb(StreamIn::mContext, sinkMetadata) {}
ndk::ScopedAStatus StreamInUsb::getActiveMicrophones(
std::vector<MicrophoneDynamicInfo>* _aidl_return __unused) {
@ -108,10 +93,10 @@ ndk::ScopedAStatus StreamInUsb::getActiveMicrophones(
return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
}
StreamOutUsb::StreamOutUsb(const SourceMetadata& sourceMetadata, StreamContext&& context,
StreamOutUsb::StreamOutUsb(StreamContext&& context, const SourceMetadata& sourceMetadata,
const std::optional<AudioOffloadInfo>& offloadInfo)
: StreamUsb(sourceMetadata, std::move(context)),
StreamOut(offloadInfo),
: StreamOut(std::move(context), offloadInfo),
StreamUsb(StreamOut::mContext, sourceMetadata),
mChannelCount(getChannelCount(getContext().getChannelLayout())) {}
ndk::ScopedAStatus StreamOutUsb::getHwVolume(std::vector<float>* _aidl_return) {

View file

@ -33,12 +33,10 @@ void UsbAlsaMixerControl::setDeviceConnectionState(int card, bool masterMuted, f
bool connected) {
LOG(DEBUG) << __func__ << ": card=" << card << ", connected=" << connected;
if (connected) {
struct mixer* mixer = mixer_open(card);
if (mixer == nullptr) {
PLOG(ERROR) << __func__ << ": failed to open mixer for card=" << card;
auto alsaMixer = std::make_shared<alsa::Mixer>(card);
if (!alsaMixer->isValid()) {
return;
}
auto alsaMixer = std::make_shared<alsa::Mixer>(mixer);
alsaMixer->setMasterMute(masterMuted);
alsaMixer->setMasterVolume(masterVolume);
const std::lock_guard guard(mLock);