audio: Add DriverInterface::start method am: 49712b56d8
am: d8e545d9d8
am: 4eb39af463
am: 5e9873805d
am: 9a652231e0
am: ef83280c00
Original change: https://android-review.googlesource.com/c/platform/hardware/interfaces/+/2647304 Change-Id: I43852509f7326b8ab5010ca9f92514668be06b72 Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
commit
a225cb7a28
8 changed files with 150 additions and 96 deletions
|
@ -166,10 +166,15 @@ StreamInWorkerLogic::Status StreamInWorkerLogic::cycle() {
|
|||
case Tag::start:
|
||||
if (mState == StreamDescriptor::State::STANDBY ||
|
||||
mState == StreamDescriptor::State::DRAINING) {
|
||||
populateReply(&reply, mIsConnected);
|
||||
mState = mState == StreamDescriptor::State::STANDBY
|
||||
? StreamDescriptor::State::IDLE
|
||||
: StreamDescriptor::State::ACTIVE;
|
||||
if (::android::status_t status = mDriver->start(); status == ::android::OK) {
|
||||
populateReply(&reply, mIsConnected);
|
||||
mState = mState == StreamDescriptor::State::STANDBY
|
||||
? StreamDescriptor::State::IDLE
|
||||
: StreamDescriptor::State::ACTIVE;
|
||||
} else {
|
||||
LOG(ERROR) << __func__ << ": start failed: " << status;
|
||||
mState = StreamDescriptor::State::ERROR;
|
||||
}
|
||||
} else {
|
||||
populateReplyWrongState(&reply, command);
|
||||
}
|
||||
|
@ -377,26 +382,36 @@ StreamOutWorkerLogic::Status StreamOutWorkerLogic::cycle() {
|
|||
populateReply(&reply, mIsConnected);
|
||||
break;
|
||||
case Tag::start: {
|
||||
bool commandAccepted = true;
|
||||
std::optional<StreamDescriptor::State> nextState;
|
||||
switch (mState) {
|
||||
case StreamDescriptor::State::STANDBY:
|
||||
mState = StreamDescriptor::State::IDLE;
|
||||
nextState = StreamDescriptor::State::IDLE;
|
||||
break;
|
||||
case StreamDescriptor::State::PAUSED:
|
||||
mState = StreamDescriptor::State::ACTIVE;
|
||||
nextState = StreamDescriptor::State::ACTIVE;
|
||||
break;
|
||||
case StreamDescriptor::State::DRAIN_PAUSED:
|
||||
switchToTransientState(StreamDescriptor::State::DRAINING);
|
||||
nextState = StreamDescriptor::State::DRAINING;
|
||||
break;
|
||||
case StreamDescriptor::State::TRANSFER_PAUSED:
|
||||
switchToTransientState(StreamDescriptor::State::TRANSFERRING);
|
||||
nextState = StreamDescriptor::State::TRANSFERRING;
|
||||
break;
|
||||
default:
|
||||
populateReplyWrongState(&reply, command);
|
||||
commandAccepted = false;
|
||||
}
|
||||
if (commandAccepted) {
|
||||
populateReply(&reply, mIsConnected);
|
||||
if (nextState.has_value()) {
|
||||
if (::android::status_t status = mDriver->start(); status == ::android::OK) {
|
||||
populateReply(&reply, mIsConnected);
|
||||
if (*nextState == StreamDescriptor::State::IDLE ||
|
||||
*nextState == StreamDescriptor::State::ACTIVE) {
|
||||
mState = *nextState;
|
||||
} else {
|
||||
switchToTransientState(*nextState);
|
||||
}
|
||||
} else {
|
||||
LOG(ERROR) << __func__ << ": start failed: " << status;
|
||||
mState = StreamDescriptor::State::ERROR;
|
||||
}
|
||||
}
|
||||
} break;
|
||||
case Tag::burst:
|
||||
|
|
|
@ -33,33 +33,67 @@ namespace aidl::android::hardware::audio::core {
|
|||
|
||||
StreamStub::StreamStub(const Metadata& metadata, StreamContext&& context)
|
||||
: StreamCommonImpl(metadata, std::move(context)),
|
||||
mFrameSizeBytes(context.getFrameSize()),
|
||||
mSampleRate(context.getSampleRate()),
|
||||
mIsAsynchronous(!!context.getAsyncCallback()),
|
||||
mFrameSizeBytes(getContext().getFrameSize()),
|
||||
mSampleRate(getContext().getSampleRate()),
|
||||
mIsAsynchronous(!!getContext().getAsyncCallback()),
|
||||
mIsInput(isInput(metadata)) {}
|
||||
|
||||
::android::status_t StreamStub::init() {
|
||||
mIsInitialized = true;
|
||||
usleep(500);
|
||||
return ::android::OK;
|
||||
}
|
||||
|
||||
::android::status_t StreamStub::drain(StreamDescriptor::DrainMode) {
|
||||
if (!mIsInitialized) {
|
||||
LOG(FATAL) << __func__ << ": must not happen for an uninitialized driver";
|
||||
}
|
||||
usleep(500);
|
||||
return ::android::OK;
|
||||
}
|
||||
|
||||
::android::status_t StreamStub::flush() {
|
||||
if (!mIsInitialized) {
|
||||
LOG(FATAL) << __func__ << ": must not happen for an uninitialized driver";
|
||||
}
|
||||
usleep(500);
|
||||
return ::android::OK;
|
||||
}
|
||||
|
||||
::android::status_t StreamStub::pause() {
|
||||
if (!mIsInitialized) {
|
||||
LOG(FATAL) << __func__ << ": must not happen for an uninitialized driver";
|
||||
}
|
||||
usleep(500);
|
||||
return ::android::OK;
|
||||
}
|
||||
|
||||
::android::status_t StreamStub::standby() {
|
||||
if (!mIsInitialized) {
|
||||
LOG(FATAL) << __func__ << ": must not happen for an uninitialized driver";
|
||||
}
|
||||
usleep(500);
|
||||
mIsStandby = true;
|
||||
return ::android::OK;
|
||||
}
|
||||
|
||||
::android::status_t StreamStub::start() {
|
||||
if (!mIsInitialized) {
|
||||
LOG(FATAL) << __func__ << ": must not happen for an uninitialized driver";
|
||||
}
|
||||
usleep(500);
|
||||
mIsStandby = false;
|
||||
return ::android::OK;
|
||||
}
|
||||
|
||||
::android::status_t StreamStub::transfer(void* buffer, size_t frameCount, size_t* actualFrameCount,
|
||||
int32_t* latencyMs) {
|
||||
if (!mIsInitialized) {
|
||||
LOG(FATAL) << __func__ << ": must not happen for an uninitialized driver";
|
||||
}
|
||||
if (mIsStandby) {
|
||||
LOG(FATAL) << __func__ << ": must not happen while in standby";
|
||||
}
|
||||
static constexpr float kMicrosPerSecond = MICROS_PER_SECOND;
|
||||
static constexpr float kScaleFactor = .8f;
|
||||
if (mIsAsynchronous) {
|
||||
|
@ -80,13 +114,10 @@ StreamStub::StreamStub(const Metadata& metadata, StreamContext&& context)
|
|||
return ::android::OK;
|
||||
}
|
||||
|
||||
::android::status_t StreamStub::standby() {
|
||||
usleep(500);
|
||||
return ::android::OK;
|
||||
void StreamStub::shutdown() {
|
||||
mIsInitialized = false;
|
||||
}
|
||||
|
||||
void StreamStub::shutdown() {}
|
||||
|
||||
StreamInStub::StreamInStub(const SinkMetadata& sinkMetadata, StreamContext&& context,
|
||||
const std::vector<MicrophoneInfo>& microphones)
|
||||
: StreamStub(sinkMetadata, std::move(context)), StreamIn(microphones) {}
|
||||
|
|
|
@ -180,9 +180,10 @@ struct DriverInterface {
|
|||
virtual ::android::status_t drain(StreamDescriptor::DrainMode mode) = 0;
|
||||
virtual ::android::status_t flush() = 0;
|
||||
virtual ::android::status_t pause() = 0;
|
||||
virtual ::android::status_t standby() = 0;
|
||||
virtual ::android::status_t start() = 0;
|
||||
virtual ::android::status_t transfer(void* buffer, size_t frameCount, size_t* actualFrameCount,
|
||||
int32_t* latencyMs) = 0;
|
||||
virtual ::android::status_t standby() = 0;
|
||||
virtual void shutdown() = 0; // This function is only called once.
|
||||
};
|
||||
|
||||
|
|
|
@ -35,9 +35,10 @@ class StreamRemoteSubmix : public StreamCommonImpl {
|
|||
::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;
|
||||
::android::status_t standby() override;
|
||||
void shutdown() override;
|
||||
|
||||
// Overridden methods of 'StreamCommonImpl', called on a Binder thread.
|
||||
|
@ -53,7 +54,6 @@ class StreamRemoteSubmix : public StreamCommonImpl {
|
|||
const bool mIsInput;
|
||||
AudioConfig mStreamConfig;
|
||||
std::shared_ptr<SubmixRoute> mCurrentRoute = nullptr;
|
||||
::android::status_t mStatus = ::android::NO_INIT;
|
||||
|
||||
// Mutex lock to protect vector of submix routes, each of these submix routes have their mutex
|
||||
// locks and none of the mutex locks should be taken together.
|
||||
|
|
|
@ -28,9 +28,10 @@ class StreamStub : public StreamCommonImpl {
|
|||
::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;
|
||||
::android::status_t standby() override;
|
||||
void shutdown() override;
|
||||
|
||||
private:
|
||||
|
@ -38,6 +39,8 @@ class StreamStub : public StreamCommonImpl {
|
|||
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.
|
||||
};
|
||||
|
||||
class StreamInStub final : public StreamStub, public StreamIn {
|
||||
|
|
|
@ -16,7 +16,10 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <atomic>
|
||||
#include <functional>
|
||||
#include <mutex>
|
||||
#include <optional>
|
||||
#include <vector>
|
||||
|
||||
#include <aidl/android/media/audio/common/AudioChannelLayout.h>
|
||||
|
@ -38,9 +41,10 @@ class StreamUsb : public StreamCommonImpl {
|
|||
::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;
|
||||
::android::status_t standby() override;
|
||||
void shutdown() override;
|
||||
|
||||
// Overridden methods of 'StreamCommonImpl', called on a Binder thread.
|
||||
|
@ -48,15 +52,20 @@ class StreamUsb : public StreamCommonImpl {
|
|||
ndk::ScopedAStatus setConnectedDevices(const ConnectedDevices& devices) override;
|
||||
|
||||
private:
|
||||
::android::status_t exitStandby();
|
||||
using AlsaDeviceProxyDeleter = std::function<void(alsa_device_proxy*)>;
|
||||
using AlsaDeviceProxy = std::unique_ptr<alsa_device_proxy, AlsaDeviceProxyDeleter>;
|
||||
|
||||
static std::optional<struct pcm_config> maybePopulateConfig(const StreamContext& context,
|
||||
bool isInput);
|
||||
|
||||
mutable std::mutex mLock;
|
||||
|
||||
const size_t mFrameSizeBytes;
|
||||
std::optional<struct pcm_config> mConfig;
|
||||
const bool mIsInput;
|
||||
std::vector<std::shared_ptr<alsa_device_proxy>> mAlsaDeviceProxies GUARDED_BY(mLock);
|
||||
bool mIsStandby = true;
|
||||
const std::optional<struct pcm_config> mConfig;
|
||||
std::atomic<bool> mConnectedDevicesUpdated = false;
|
||||
// All fields below are only used on the worker thread.
|
||||
std::vector<AlsaDeviceProxy> mAlsaDeviceProxies;
|
||||
};
|
||||
|
||||
class StreamInUsb final : public StreamUsb, public StreamIn {
|
||||
|
|
|
@ -55,7 +55,7 @@ std::map<int32_t, std::shared_ptr<SubmixRoute>> StreamRemoteSubmix::sSubmixRoute
|
|||
mCurrentRoute = std::make_shared<SubmixRoute>();
|
||||
if (::android::OK != mCurrentRoute->createPipe(mStreamConfig)) {
|
||||
LOG(ERROR) << __func__ << ": create pipe failed";
|
||||
return mStatus;
|
||||
return ::android::NO_INIT;
|
||||
}
|
||||
{
|
||||
std::lock_guard guard(sSubmixRoutesLock);
|
||||
|
@ -64,12 +64,12 @@ std::map<int32_t, std::shared_ptr<SubmixRoute>> StreamRemoteSubmix::sSubmixRoute
|
|||
} else {
|
||||
if (!mCurrentRoute->isStreamConfigValid(mIsInput, mStreamConfig)) {
|
||||
LOG(ERROR) << __func__ << ": invalid stream config";
|
||||
return mStatus;
|
||||
return ::android::NO_INIT;
|
||||
}
|
||||
sp<MonoPipe> sink = mCurrentRoute->getSink();
|
||||
if (sink == nullptr) {
|
||||
LOG(ERROR) << __func__ << ": nullptr sink when opening stream";
|
||||
return mStatus;
|
||||
return ::android::NO_INIT;
|
||||
}
|
||||
// If the sink has been shutdown or pipe recreation is forced, delete the pipe and
|
||||
// recreate it.
|
||||
|
@ -77,14 +77,13 @@ std::map<int32_t, std::shared_ptr<SubmixRoute>> StreamRemoteSubmix::sSubmixRoute
|
|||
LOG(DEBUG) << __func__ << ": Non-nullptr shut down sink when opening stream";
|
||||
if (::android::OK != mCurrentRoute->resetPipe()) {
|
||||
LOG(ERROR) << __func__ << ": reset pipe failed";
|
||||
return mStatus;
|
||||
return ::android::NO_INIT;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mCurrentRoute->openStream(mIsInput);
|
||||
mStatus = ::android::OK;
|
||||
return mStatus;
|
||||
return ::android::OK;
|
||||
}
|
||||
|
||||
::android::status_t StreamRemoteSubmix::drain(StreamDescriptor::DrainMode) {
|
||||
|
@ -102,6 +101,16 @@ std::map<int32_t, std::shared_ptr<SubmixRoute>> StreamRemoteSubmix::sSubmixRoute
|
|||
return ::android::OK;
|
||||
}
|
||||
|
||||
::android::status_t StreamRemoteSubmix::standby() {
|
||||
mCurrentRoute->standby(mIsInput);
|
||||
return ::android::OK;
|
||||
}
|
||||
|
||||
::android::status_t StreamRemoteSubmix::start() {
|
||||
mCurrentRoute->exitStandby(mIsInput);
|
||||
return ::android::OK;
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus StreamRemoteSubmix::prepareToClose() {
|
||||
if (!mIsInput) {
|
||||
std::shared_ptr<SubmixRoute> route = nullptr;
|
||||
|
@ -138,17 +147,12 @@ void StreamRemoteSubmix::shutdown() {
|
|||
|
||||
std::lock_guard guard(sSubmixRoutesLock);
|
||||
sSubmixRoutes.erase(mPortId);
|
||||
mStatus = ::android::NO_INIT;
|
||||
}
|
||||
mCurrentRoute.reset();
|
||||
}
|
||||
|
||||
::android::status_t StreamRemoteSubmix::transfer(void* buffer, size_t frameCount,
|
||||
size_t* actualFrameCount, int32_t* latencyMs) {
|
||||
if (mStatus != ::android::OK) {
|
||||
LOG(ERROR) << __func__ << ": failed, not configured";
|
||||
return ::android::NO_INIT;
|
||||
}
|
||||
|
||||
*latencyMs = (getStreamPipeSizeInFrames() * MILLIS_PER_SECOND) / mStreamConfig.sampleRate;
|
||||
LOG(VERBOSE) << __func__ << ": Latency " << *latencyMs << "ms";
|
||||
|
||||
|
@ -171,7 +175,6 @@ void StreamRemoteSubmix::shutdown() {
|
|||
return ::android::UNEXPECTED_NULL;
|
||||
}
|
||||
|
||||
mCurrentRoute->exitStandby(mIsInput);
|
||||
return (mIsInput ? inRead(buffer, frameCount, actualFrameCount)
|
||||
: outWrite(buffer, frameCount, actualFrameCount));
|
||||
}
|
||||
|
@ -329,11 +332,6 @@ size_t StreamRemoteSubmix::getStreamPipeSizeInFrames() {
|
|||
return ::android::OK;
|
||||
}
|
||||
|
||||
::android::status_t StreamRemoteSubmix::standby() {
|
||||
mCurrentRoute->standby(mIsInput);
|
||||
return ::android::OK;
|
||||
}
|
||||
|
||||
StreamInRemoteSubmix::StreamInRemoteSubmix(const SinkMetadata& sinkMetadata,
|
||||
StreamContext&& context,
|
||||
const std::vector<MicrophoneInfo>& microphones)
|
||||
|
|
|
@ -14,6 +14,8 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <limits>
|
||||
|
||||
#define LOG_TAG "AHAL_StreamUsb"
|
||||
#include <android-base/logging.h>
|
||||
|
||||
|
@ -45,25 +47,30 @@ namespace aidl::android::hardware::audio::core {
|
|||
|
||||
StreamUsb::StreamUsb(const Metadata& metadata, StreamContext&& context)
|
||||
: StreamCommonImpl(metadata, std::move(context)),
|
||||
mFrameSizeBytes(context.getFrameSize()),
|
||||
mIsInput(isInput(metadata)) {
|
||||
mFrameSizeBytes(getContext().getFrameSize()),
|
||||
mIsInput(isInput(metadata)),
|
||||
mConfig(maybePopulateConfig(getContext(), mIsInput)) {}
|
||||
|
||||
// static
|
||||
std::optional<struct pcm_config> StreamUsb::maybePopulateConfig(const StreamContext& context,
|
||||
bool isInput) {
|
||||
struct pcm_config config;
|
||||
config.channels = usb::getChannelCountFromChannelMask(context.getChannelLayout(), mIsInput);
|
||||
config.channels = usb::getChannelCountFromChannelMask(context.getChannelLayout(), isInput);
|
||||
if (config.channels == 0) {
|
||||
LOG(ERROR) << __func__ << ": invalid channel=" << context.getChannelLayout().toString();
|
||||
return;
|
||||
return std::nullopt;
|
||||
}
|
||||
config.format = usb::aidl2legacy_AudioFormatDescription_pcm_format(context.getFormat());
|
||||
if (config.format == PCM_FORMAT_INVALID) {
|
||||
LOG(ERROR) << __func__ << ": invalid format=" << context.getFormat().toString();
|
||||
return;
|
||||
return std::nullopt;
|
||||
}
|
||||
config.rate = context.getSampleRate();
|
||||
if (config.rate == 0) {
|
||||
LOG(ERROR) << __func__ << ": invalid sample rate=" << config.rate;
|
||||
return;
|
||||
return std::nullopt;
|
||||
}
|
||||
mConfig = config;
|
||||
return config;
|
||||
}
|
||||
|
||||
::android::status_t StreamUsb::init() {
|
||||
|
@ -89,8 +96,8 @@ ndk::ScopedAStatus StreamUsb::setConnectedDevices(
|
|||
}
|
||||
}
|
||||
std::lock_guard guard(mLock);
|
||||
mAlsaDeviceProxies.clear();
|
||||
RETURN_STATUS_IF_ERROR(StreamCommonImpl::setConnectedDevices(connectedDevices));
|
||||
mConnectedDevicesUpdated.store(true, std::memory_order_release);
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
|
@ -111,59 +118,53 @@ ndk::ScopedAStatus StreamUsb::setConnectedDevices(
|
|||
|
||||
::android::status_t StreamUsb::transfer(void* buffer, size_t frameCount, size_t* actualFrameCount,
|
||||
int32_t* latencyMs) {
|
||||
{
|
||||
std::lock_guard guard(mLock);
|
||||
if (!mConfig.has_value() || mConnectedDevices.empty()) {
|
||||
LOG(ERROR) << __func__ << ": failed, has config: " << mConfig.has_value()
|
||||
<< ", has connected devices: " << mConnectedDevices.empty();
|
||||
return ::android::NO_INIT;
|
||||
}
|
||||
}
|
||||
if (mIsStandby) {
|
||||
if (::android::status_t status = exitStandby(); status != ::android::OK) {
|
||||
LOG(ERROR) << __func__ << ": failed to exit standby, status=" << status;
|
||||
return status;
|
||||
}
|
||||
}
|
||||
std::vector<std::shared_ptr<alsa_device_proxy>> alsaDeviceProxies;
|
||||
{
|
||||
std::lock_guard guard(mLock);
|
||||
alsaDeviceProxies = mAlsaDeviceProxies;
|
||||
if (mConnectedDevicesUpdated.load(std::memory_order_acquire)) {
|
||||
// 'setConnectedDevices' has been called. I/O will be restarted.
|
||||
*actualFrameCount = 0;
|
||||
*latencyMs = StreamDescriptor::LATENCY_UNKNOWN;
|
||||
return ::android::OK;
|
||||
}
|
||||
const size_t bytesToTransfer = frameCount * mFrameSizeBytes;
|
||||
unsigned maxLatency = 0;
|
||||
if (mIsInput) {
|
||||
if (mAlsaDeviceProxies.empty()) {
|
||||
LOG(FATAL) << __func__ << ": no input devices";
|
||||
return ::android::NO_INIT;
|
||||
}
|
||||
// For input case, only support single device.
|
||||
proxy_read(alsaDeviceProxies[0].get(), buffer, bytesToTransfer);
|
||||
proxy_read(mAlsaDeviceProxies[0].get(), buffer, bytesToTransfer);
|
||||
maxLatency = proxy_get_latency(mAlsaDeviceProxies[0].get());
|
||||
} else {
|
||||
for (auto& proxy : alsaDeviceProxies) {
|
||||
for (auto& proxy : mAlsaDeviceProxies) {
|
||||
proxy_write(proxy.get(), buffer, bytesToTransfer);
|
||||
maxLatency = std::max(maxLatency, proxy_get_latency(proxy.get()));
|
||||
}
|
||||
}
|
||||
*actualFrameCount = frameCount;
|
||||
*latencyMs = Module::kLatencyMs;
|
||||
maxLatency = std::min(maxLatency, static_cast<unsigned>(std::numeric_limits<int32_t>::max()));
|
||||
*latencyMs = maxLatency;
|
||||
return ::android::OK;
|
||||
}
|
||||
|
||||
::android::status_t StreamUsb::standby() {
|
||||
if (!mIsStandby) {
|
||||
std::lock_guard guard(mLock);
|
||||
mAlsaDeviceProxies.clear();
|
||||
mIsStandby = true;
|
||||
}
|
||||
mAlsaDeviceProxies.clear();
|
||||
return ::android::OK;
|
||||
}
|
||||
|
||||
void StreamUsb::shutdown() {}
|
||||
void StreamUsb::shutdown() {
|
||||
mAlsaDeviceProxies.clear();
|
||||
}
|
||||
|
||||
::android::status_t StreamUsb::exitStandby() {
|
||||
::android::status_t StreamUsb::start() {
|
||||
std::vector<AudioDeviceAddress> connectedDevices;
|
||||
{
|
||||
std::lock_guard guard(mLock);
|
||||
std::transform(mConnectedDevices.begin(), mConnectedDevices.end(),
|
||||
std::back_inserter(connectedDevices),
|
||||
[](const auto& device) { return device.address; });
|
||||
mConnectedDevicesUpdated.store(false, std::memory_order_release);
|
||||
}
|
||||
std::vector<std::shared_ptr<alsa_device_proxy>> alsaDeviceProxies;
|
||||
decltype(mAlsaDeviceProxies) alsaDeviceProxies;
|
||||
for (const auto& device : connectedDevices) {
|
||||
alsa_device_profile profile;
|
||||
profile_init(&profile, mIsInput ? PCM_IN : PCM_OUT);
|
||||
|
@ -175,16 +176,16 @@ void StreamUsb::shutdown() {}
|
|||
return ::android::UNKNOWN_ERROR;
|
||||
}
|
||||
|
||||
auto proxy = std::shared_ptr<alsa_device_proxy>(new alsa_device_proxy(),
|
||||
[](alsa_device_proxy* proxy) {
|
||||
proxy_close(proxy);
|
||||
free(proxy);
|
||||
});
|
||||
AlsaDeviceProxy proxy(new alsa_device_proxy, [](alsa_device_proxy* proxy) {
|
||||
proxy_close(proxy);
|
||||
free(proxy);
|
||||
});
|
||||
// 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, &mConfig.value(), true /*is_bit_perfect*/);
|
||||
if (int err = proxy_prepare(proxy.get(), &profile,
|
||||
const_cast<struct pcm_config*>(&mConfig.value()),
|
||||
true /*is_bit_perfect*/);
|
||||
err != 0) {
|
||||
LOG(ERROR) << __func__ << ": fail to prepare for device address=" << device.toString()
|
||||
<< " error=" << err;
|
||||
|
@ -197,11 +198,7 @@ void StreamUsb::shutdown() {}
|
|||
}
|
||||
alsaDeviceProxies.push_back(std::move(proxy));
|
||||
}
|
||||
{
|
||||
std::lock_guard guard(mLock);
|
||||
mAlsaDeviceProxies = alsaDeviceProxies;
|
||||
}
|
||||
mIsStandby = false;
|
||||
mAlsaDeviceProxies = std::move(alsaDeviceProxies);
|
||||
return ::android::OK;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue