audio: Allow Module subclasses to customize stream creation
Since specializations of the 'Module' class likely need
to provide their own specializations for streams, provide
virtual methods for them.
Bug: 282568751
Test: atest VtsHalAudioCoreTargetTest
Change-Id: Iddb1bff9f11bc867aba61897ea2f8b9bc3c27544
diff --git a/audio/aidl/default/Module.cpp b/audio/aidl/default/Module.cpp
index c0c6c48..6f89d4b 100644
--- a/audio/aidl/default/Module.cpp
+++ b/audio/aidl/default/Module.cpp
@@ -30,7 +30,6 @@
#include "core-impl/ModuleUsb.h"
#include "core-impl/SoundDose.h"
#include "core-impl/StreamStub.h"
-#include "core-impl/StreamUsb.h"
#include "core-impl/Telephony.h"
#include "core-impl/utils.h"
@@ -119,30 +118,6 @@
}
}
-// static
-StreamIn::CreateInstance Module::getStreamInCreator(Type type) {
- switch (type) {
- case Type::USB:
- return StreamInUsb::createInstance;
- case Type::DEFAULT:
- case Type::R_SUBMIX:
- default:
- return StreamInStub::createInstance;
- }
-}
-
-// static
-StreamOut::CreateInstance Module::getStreamOutCreator(Type type) {
- switch (type) {
- case Type::USB:
- return StreamOutUsb::createInstance;
- case Type::DEFAULT:
- case Type::R_SUBMIX:
- default:
- return StreamOutStub::createInstance;
- }
-}
-
std::ostream& operator<<(std::ostream& os, Module::Type t) {
switch (t) {
case Module::Type::DEFAULT:
@@ -687,8 +662,8 @@
nullptr, nullptr, &context));
context.fillDescriptor(&_aidl_return->desc);
std::shared_ptr<StreamIn> stream;
- RETURN_STATUS_IF_ERROR(getStreamInCreator(mType)(in_args.sinkMetadata, std::move(context),
- mConfig->microphones, &stream));
+ RETURN_STATUS_IF_ERROR(createInputStream(in_args.sinkMetadata, std::move(context),
+ mConfig->microphones, &stream));
StreamWrapper streamWrapper(stream);
if (auto patchIt = mPatches.find(in_args.portConfigId); patchIt != mPatches.end()) {
RETURN_STATUS_IF_ERROR(
@@ -733,8 +708,8 @@
in_args.eventCallback, &context));
context.fillDescriptor(&_aidl_return->desc);
std::shared_ptr<StreamOut> stream;
- RETURN_STATUS_IF_ERROR(getStreamOutCreator(mType)(in_args.sourceMetadata, std::move(context),
- in_args.offloadInfo, &stream));
+ RETURN_STATUS_IF_ERROR(createOutputStream(in_args.sourceMetadata, std::move(context),
+ in_args.offloadInfo, &stream));
StreamWrapper streamWrapper(stream);
if (auto patchIt = mPatches.find(in_args.portConfigId); patchIt != mPatches.end()) {
RETURN_STATUS_IF_ERROR(
@@ -1346,6 +1321,22 @@
return mIsMmapSupported.value();
}
+ndk::ScopedAStatus Module::createInputStream(const SinkMetadata& sinkMetadata,
+ StreamContext&& context,
+ const std::vector<MicrophoneInfo>& microphones,
+ std::shared_ptr<StreamIn>* result) {
+ return createStreamInstance<StreamInStub>(result, sinkMetadata, std::move(context),
+ microphones);
+}
+
+ndk::ScopedAStatus Module::createOutputStream(const SourceMetadata& sourceMetadata,
+ StreamContext&& context,
+ const std::optional<AudioOffloadInfo>& offloadInfo,
+ std::shared_ptr<StreamOut>* result) {
+ return createStreamInstance<StreamOutStub>(result, sourceMetadata, std::move(context),
+ offloadInfo);
+}
+
ndk::ScopedAStatus Module::populateConnectedDevicePort(AudioPort* audioPort __unused) {
LOG(VERBOSE) << __func__ << ": do nothing and return ok";
return ndk::ScopedAStatus::ok();
diff --git a/audio/aidl/default/StreamStub.cpp b/audio/aidl/default/StreamStub.cpp
index 289afa1..d88dfbc 100644
--- a/audio/aidl/default/StreamStub.cpp
+++ b/audio/aidl/default/StreamStub.cpp
@@ -87,38 +87,10 @@
void StreamStub::shutdown() {}
-// static
-ndk::ScopedAStatus StreamInStub::createInstance(const SinkMetadata& sinkMetadata,
- StreamContext&& context,
- const std::vector<MicrophoneInfo>& microphones,
- std::shared_ptr<StreamIn>* result) {
- std::shared_ptr<StreamIn> stream =
- ndk::SharedRefBase::make<StreamInStub>(sinkMetadata, std::move(context), microphones);
- if (auto status = stream->initInstance(stream); !status.isOk()) {
- return status;
- }
- *result = std::move(stream);
- return ndk::ScopedAStatus::ok();
-}
-
StreamInStub::StreamInStub(const SinkMetadata& sinkMetadata, StreamContext&& context,
const std::vector<MicrophoneInfo>& microphones)
: StreamStub(sinkMetadata, std::move(context)), StreamIn(microphones) {}
-// static
-ndk::ScopedAStatus StreamOutStub::createInstance(const SourceMetadata& sourceMetadata,
- StreamContext&& context,
- const std::optional<AudioOffloadInfo>& offloadInfo,
- std::shared_ptr<StreamOut>* result) {
- std::shared_ptr<StreamOut> stream = ndk::SharedRefBase::make<StreamOutStub>(
- sourceMetadata, std::move(context), offloadInfo);
- if (auto status = stream->initInstance(stream); !status.isOk()) {
- return status;
- }
- *result = std::move(stream);
- return ndk::ScopedAStatus::ok();
-}
-
StreamOutStub::StreamOutStub(const SourceMetadata& sourceMetadata, StreamContext&& context,
const std::optional<AudioOffloadInfo>& offloadInfo)
: StreamStub(sourceMetadata, std::move(context)), StreamOut(offloadInfo) {}
diff --git a/audio/aidl/default/include/core-impl/Module.h b/audio/aidl/default/include/core-impl/Module.h
index 212cfd9..4a23637 100644
--- a/audio/aidl/default/include/core-impl/Module.h
+++ b/audio/aidl/default/include/core-impl/Module.h
@@ -33,11 +33,9 @@
static constexpr int32_t kLatencyMs = 10;
enum Type : int { DEFAULT, R_SUBMIX, USB };
- explicit Module(Type type) : mType(type) {}
-
static std::shared_ptr<Module> createInstance(Type type);
- static StreamIn::CreateInstance getStreamInCreator(Type type);
- static StreamOut::CreateInstance getStreamOutCreator(Type type);
+
+ explicit Module(Type type) : mType(type) {}
protected:
// The vendor extension done via inheritance can override interface methods and augment
@@ -182,6 +180,17 @@
protected:
// 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 std::vector<::aidl::android::media::audio::common::MicrophoneInfo>& microphones,
+ std::shared_ptr<StreamIn>* result);
+ virtual ndk::ScopedAStatus createOutputStream(
+ const ::aidl::android::hardware::audio::common::SourceMetadata& sourceMetadata,
+ StreamContext&& context,
+ const std::optional<::aidl::android::media::audio::common::AudioOffloadInfo>&
+ offloadInfo,
+ std::shared_ptr<StreamOut>* result);
// If the module is unable to populate the connected device port correctly, the returned error
// code must correspond to the errors of `IModule.connectedExternalDevice` method.
virtual ndk::ScopedAStatus populateConnectedDevicePort(
diff --git a/audio/aidl/default/include/core-impl/ModuleUsb.h b/audio/aidl/default/include/core-impl/ModuleUsb.h
index 1aa2244..5a5429d 100644
--- a/audio/aidl/default/include/core-impl/ModuleUsb.h
+++ b/audio/aidl/default/include/core-impl/ModuleUsb.h
@@ -32,6 +32,17 @@
ndk::ScopedAStatus setMicMute(bool in_mute) override;
// Module interfaces
+ ndk::ScopedAStatus createInputStream(
+ const ::aidl::android::hardware::audio::common::SinkMetadata& sinkMetadata,
+ StreamContext&& context,
+ 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 std::optional<::aidl::android::media::audio::common::AudioOffloadInfo>&
+ offloadInfo,
+ std::shared_ptr<StreamOut>* result) override;
ndk::ScopedAStatus populateConnectedDevicePort(
::aidl::android::media::audio::common::AudioPort* audioPort) override;
ndk::ScopedAStatus checkAudioPatchEndpointsMatch(
diff --git a/audio/aidl/default/include/core-impl/Stream.h b/audio/aidl/default/include/core-impl/Stream.h
index ff5b5a0..c20a421 100644
--- a/audio/aidl/default/include/core-impl/Stream.h
+++ b/audio/aidl/default/include/core-impl/Stream.h
@@ -25,6 +25,7 @@
#include <variant>
#include <StreamWorker.h>
+#include <Utils.h>
#include <aidl/android/hardware/audio/common/SinkMetadata.h>
#include <aidl/android/hardware/audio/common/SourceMetadata.h>
#include <aidl/android/hardware/audio/core/BnStreamCommon.h>
@@ -37,6 +38,7 @@
#include <aidl/android/media/audio/common/AudioIoFlags.h>
#include <aidl/android/media/audio/common/AudioOffloadInfo.h>
#include <aidl/android/media/audio/common/MicrophoneInfo.h>
+#include <error/expected_utils.h>
#include <fmq/AidlMessageQueue.h>
#include <system/thread_defs.h>
#include <utils/Errors.h>
@@ -482,13 +484,6 @@
const std::vector<::aidl::android::media::audio::common::MicrophoneInfo>& microphones);
const std::map<::aidl::android::media::audio::common::AudioDevice, std::string> mMicrophones;
-
- public:
- using CreateInstance = std::function<ndk::ScopedAStatus(
- const ::aidl::android::hardware::audio::common::SinkMetadata& sinkMetadata,
- StreamContext&& context,
- const std::vector<::aidl::android::media::audio::common::MicrophoneInfo>& microphones,
- std::shared_ptr<StreamIn>* result)>;
};
class StreamOut : virtual public StreamCommonInterface, public BnStreamOut {
@@ -531,16 +526,20 @@
std::optional<::aidl::android::media::audio::common::AudioOffloadInfo> mOffloadInfo;
std::optional<::aidl::android::hardware::audio::common::AudioOffloadMetadata> mOffloadMetadata;
-
- public:
- using CreateInstance = std::function<ndk::ScopedAStatus(
- const ::aidl::android::hardware::audio::common::SourceMetadata& sourceMetadata,
- StreamContext&& context,
- const std::optional<::aidl::android::media::audio::common::AudioOffloadInfo>&
- offloadInfo,
- std::shared_ptr<StreamOut>* result)>;
};
+// The recommended way to create a stream instance.
+// 'StreamImpl' is the concrete stream implementation, 'StreamInOrOut' is either 'StreamIn' or
+// 'StreamOut', the rest are the arguments forwarded to the constructor of 'StreamImpl'.
+template <class StreamImpl, class StreamInOrOut, class... Args>
+ndk::ScopedAStatus createStreamInstance(std::shared_ptr<StreamInOrOut>* result, Args&&... args) {
+ std::shared_ptr<StreamInOrOut> stream =
+ ::ndk::SharedRefBase::make<StreamImpl>(std::forward<Args>(args)...);
+ RETURN_STATUS_IF_ERROR(stream->initInstance(stream));
+ *result = std::move(stream);
+ return ndk::ScopedAStatus::ok();
+}
+
class StreamWrapper {
public:
explicit StreamWrapper(const std::shared_ptr<StreamIn>& streamIn)
diff --git a/audio/aidl/default/include/core-impl/StreamStub.h b/audio/aidl/default/include/core-impl/StreamStub.h
index def98b7..c8900f3 100644
--- a/audio/aidl/default/include/core-impl/StreamStub.h
+++ b/audio/aidl/default/include/core-impl/StreamStub.h
@@ -42,13 +42,6 @@
class StreamInStub final : public StreamStub, public StreamIn {
public:
- static ndk::ScopedAStatus createInstance(
- const ::aidl::android::hardware::audio::common::SinkMetadata& sinkMetadata,
- StreamContext&& context,
- const std::vector<::aidl::android::media::audio::common::MicrophoneInfo>& microphones,
- std::shared_ptr<StreamIn>* result);
-
- private:
friend class ndk::SharedRefBase;
StreamInStub(
const ::aidl::android::hardware::audio::common::SinkMetadata& sinkMetadata,
@@ -58,14 +51,6 @@
class StreamOutStub final : public StreamStub, public StreamOut {
public:
- static ndk::ScopedAStatus createInstance(
- const ::aidl::android::hardware::audio::common::SourceMetadata& sourceMetadata,
- StreamContext&& context,
- const std::optional<::aidl::android::media::audio::common::AudioOffloadInfo>&
- offloadInfo,
- std::shared_ptr<StreamOut>* result);
-
- private:
friend class ndk::SharedRefBase;
StreamOutStub(const ::aidl::android::hardware::audio::common::SourceMetadata& sourceMetadata,
StreamContext&& context,
diff --git a/audio/aidl/default/include/core-impl/StreamUsb.h b/audio/aidl/default/include/core-impl/StreamUsb.h
index 24ea8be..5e55cd8 100644
--- a/audio/aidl/default/include/core-impl/StreamUsb.h
+++ b/audio/aidl/default/include/core-impl/StreamUsb.h
@@ -60,41 +60,28 @@
};
class StreamInUsb final : public StreamUsb, public StreamIn {
- ndk::ScopedAStatus getActiveMicrophones(
- std::vector<::aidl::android::media::audio::common::MicrophoneDynamicInfo>* _aidl_return)
- override;
-
public:
- static ndk::ScopedAStatus createInstance(
- const ::aidl::android::hardware::audio::common::SinkMetadata& sinkMetadata,
- StreamContext&& context,
- const std::vector<::aidl::android::media::audio::common::MicrophoneInfo>& microphones,
- std::shared_ptr<StreamIn>* result);
-
- private:
friend class ndk::SharedRefBase;
StreamInUsb(
const ::aidl::android::hardware::audio::common::SinkMetadata& sinkMetadata,
StreamContext&& context,
const std::vector<::aidl::android::media::audio::common::MicrophoneInfo>& microphones);
+
+ private:
+ ndk::ScopedAStatus getActiveMicrophones(
+ std::vector<::aidl::android::media::audio::common::MicrophoneDynamicInfo>* _aidl_return)
+ override;
};
class StreamOutUsb final : public StreamUsb, public StreamOut {
public:
- static ndk::ScopedAStatus createInstance(
- const ::aidl::android::hardware::audio::common::SourceMetadata& sourceMetadata,
- StreamContext&& context,
- const std::optional<::aidl::android::media::audio::common::AudioOffloadInfo>&
- offloadInfo,
- std::shared_ptr<StreamOut>* result);
-
- private:
friend class ndk::SharedRefBase;
StreamOutUsb(const ::aidl::android::hardware::audio::common::SourceMetadata& sourceMetadata,
StreamContext&& context,
const std::optional<::aidl::android::media::audio::common::AudioOffloadInfo>&
offloadInfo);
+ private:
ndk::ScopedAStatus getHwVolume(std::vector<float>* _aidl_return) override;
ndk::ScopedAStatus setHwVolume(const std::vector<float>& in_channelVolumes) override;
diff --git a/audio/aidl/default/usb/ModuleUsb.cpp b/audio/aidl/default/usb/ModuleUsb.cpp
index c568dc9..5c9d477 100644
--- a/audio/aidl/default/usb/ModuleUsb.cpp
+++ b/audio/aidl/default/usb/ModuleUsb.cpp
@@ -25,11 +25,14 @@
#include "UsbAlsaMixerControl.h"
#include "UsbAlsaUtils.h"
#include "core-impl/ModuleUsb.h"
+#include "core-impl/StreamUsb.h"
extern "C" {
#include "alsa_device_profile.h"
}
+using aidl::android::hardware::audio::common::SinkMetadata;
+using aidl::android::hardware::audio::common::SourceMetadata;
using aidl::android::media::audio::common::AudioChannelLayout;
using aidl::android::media::audio::common::AudioDeviceAddress;
using aidl::android::media::audio::common::AudioDeviceDescription;
@@ -37,10 +40,12 @@
using aidl::android::media::audio::common::AudioFormatDescription;
using aidl::android::media::audio::common::AudioFormatType;
using aidl::android::media::audio::common::AudioIoFlags;
+using aidl::android::media::audio::common::AudioOffloadInfo;
using aidl::android::media::audio::common::AudioPort;
using aidl::android::media::audio::common::AudioPortConfig;
using aidl::android::media::audio::common::AudioPortExt;
using aidl::android::media::audio::common::AudioProfile;
+using aidl::android::media::audio::common::MicrophoneInfo;
namespace aidl::android::hardware::audio::core {
@@ -97,6 +102,25 @@
return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
}
+ndk::ScopedAStatus ModuleUsb::createInputStream(const SinkMetadata& sinkMetadata,
+ StreamContext&& context,
+ const std::vector<MicrophoneInfo>& microphones,
+ std::shared_ptr<StreamIn>* result) {
+ return createStreamInstance<StreamInUsb>(result, sinkMetadata, std::move(context), microphones);
+}
+
+ndk::ScopedAStatus ModuleUsb::createOutputStream(const SourceMetadata& sourceMetadata,
+ StreamContext&& context,
+ 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),
+ offloadInfo);
+}
+
ndk::ScopedAStatus ModuleUsb::populateConnectedDevicePort(AudioPort* audioPort) {
if (audioPort->ext.getTag() != AudioPortExt::Tag::device) {
LOG(ERROR) << __func__ << ": port id " << audioPort->id << " is not a device port";
diff --git a/audio/aidl/default/usb/StreamUsb.cpp b/audio/aidl/default/usb/StreamUsb.cpp
index fcac5df..49bc1d6 100644
--- a/audio/aidl/default/usb/StreamUsb.cpp
+++ b/audio/aidl/default/usb/StreamUsb.cpp
@@ -205,20 +205,6 @@
return ::android::OK;
}
-// static
-ndk::ScopedAStatus StreamInUsb::createInstance(const SinkMetadata& sinkMetadata,
- StreamContext&& context,
- const std::vector<MicrophoneInfo>& microphones,
- std::shared_ptr<StreamIn>* result) {
- std::shared_ptr<StreamIn> stream =
- ndk::SharedRefBase::make<StreamInUsb>(sinkMetadata, std::move(context), microphones);
- if (auto status = stream->initInstance(stream); !status.isOk()) {
- return status;
- }
- *result = std::move(stream);
- return ndk::ScopedAStatus::ok();
-}
-
StreamInUsb::StreamInUsb(const SinkMetadata& sinkMetadata, StreamContext&& context,
const std::vector<MicrophoneInfo>& microphones)
: StreamUsb(sinkMetadata, std::move(context)), StreamIn(microphones) {}
@@ -229,24 +215,6 @@
return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
}
-// static
-ndk::ScopedAStatus StreamOutUsb::createInstance(const SourceMetadata& sourceMetadata,
- StreamContext&& context,
- 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);
- }
- std::shared_ptr<StreamOut> stream =
- ndk::SharedRefBase::make<StreamOutUsb>(sourceMetadata, std::move(context), offloadInfo);
- if (auto status = stream->initInstance(stream); !status.isOk()) {
- return status;
- }
- *result = std::move(stream);
- return ndk::ScopedAStatus::ok();
-}
-
StreamOutUsb::StreamOutUsb(const SourceMetadata& sourceMetadata, StreamContext&& context,
const std::optional<AudioOffloadInfo>& offloadInfo)
: StreamUsb(sourceMetadata, std::move(context)), StreamOut(offloadInfo) {