audio: Facilitate extension of Module class by vendors

Make interface methods protected so that subclasses can
augment them.

Provide getters for private fields.

Bug: 282568751
Test: atest VtsHalAudioCoreTargetTest
Change-Id: I0e4810f8a4c816c4f673139816e9768f6dc8da7c
This commit is contained in:
Mikhail Naganov
2023-06-16 12:16:16 -07:00
parent 377be1fa1b
commit 57f0dcf78d
2 changed files with 70 additions and 56 deletions

View File

@@ -39,33 +39,9 @@ class Module : public BnModule {
static StreamIn::CreateInstance getStreamInCreator(Type type);
static StreamOut::CreateInstance getStreamOutCreator(Type type);
private:
struct VendorDebug {
static const std::string kForceTransientBurstName;
static const std::string kForceSynchronousDrainName;
bool forceTransientBurst = false;
bool forceSynchronousDrain = false;
};
// Helper used for interfaces that require a persistent instance. We hold them via a strong
// pointer. The binder token is retained for a call to 'setMinSchedulerPolicy'.
template <class C>
struct ChildInterface : private std::pair<std::shared_ptr<C>, ndk::SpAIBinder> {
ChildInterface() {}
ChildInterface& operator=(const std::shared_ptr<C>& c) {
return operator=(std::shared_ptr<C>(c));
}
ChildInterface& operator=(std::shared_ptr<C>&& c) {
this->first = std::move(c);
this->second = this->first->asBinder();
AIBinder_setMinSchedulerPolicy(this->second.get(), SCHED_NORMAL,
ANDROID_PRIORITY_AUDIO);
return *this;
}
explicit operator bool() const { return !!this->first; }
C& operator*() const { return *(this->first); }
C* operator->() const { return this->first; }
std::shared_ptr<C> getPtr() const { return this->first; }
};
protected:
// The vendor extension done via inheritance can override interface methods and augment
// a call to the base implementation.
ndk::ScopedAStatus setModuleDebug(
const ::aidl::android::hardware::audio::core::ModuleDebug& in_debug) override;
@@ -146,29 +122,46 @@ class Module : public BnModule {
ndk::ScopedAStatus getAAudioMixerBurstCount(int32_t* _aidl_return) override;
ndk::ScopedAStatus getAAudioHardwareBurstMinUsec(int32_t* _aidl_return) override;
void cleanUpPatch(int32_t patchId);
ndk::ScopedAStatus createStreamContext(
int32_t in_portConfigId, int64_t in_bufferSizeFrames,
std::shared_ptr<IStreamCallback> asyncCallback,
std::shared_ptr<IStreamOutEventCallback> outEventCallback,
::aidl::android::hardware::audio::core::StreamContext* out_context);
std::vector<::aidl::android::media::audio::common::AudioDevice> findConnectedDevices(
int32_t portConfigId);
std::set<int32_t> findConnectedPortConfigIds(int32_t portConfigId);
ndk::ScopedAStatus findPortIdForNewStream(
int32_t in_portConfigId, ::aidl::android::media::audio::common::AudioPort** port);
internal::Configuration& getConfig();
template <typename C>
std::set<int32_t> portIdsFromPortConfigIds(C portConfigIds);
void registerPatch(const AudioPatch& patch);
void updateStreamsConnectedState(const AudioPatch& oldPatch, const AudioPatch& newPatch);
bool isMmapSupported();
// This value is used for all AudioPatches.
static constexpr int32_t kMinimumStreamBufferSizeFrames = 256;
// The maximum stream buffer size is 1 GiB = 2 ** 30 bytes;
static constexpr int32_t kMaximumStreamBufferSizeBytes = 1 << 30;
private:
struct VendorDebug {
static const std::string kForceTransientBurstName;
static const std::string kForceSynchronousDrainName;
bool forceTransientBurst = false;
bool forceSynchronousDrain = false;
};
// Helper used for interfaces that require a persistent instance. We hold them via a strong
// pointer. The binder token is retained for a call to 'setMinSchedulerPolicy'.
template <class C>
struct ChildInterface : private std::pair<std::shared_ptr<C>, ndk::SpAIBinder> {
ChildInterface() {}
ChildInterface& operator=(const std::shared_ptr<C>& c) {
return operator=(std::shared_ptr<C>(c));
}
ChildInterface& operator=(std::shared_ptr<C>&& c) {
this->first = std::move(c);
this->second = this->first->asBinder();
AIBinder_setMinSchedulerPolicy(this->second.get(), SCHED_NORMAL,
ANDROID_PRIORITY_AUDIO);
return *this;
}
explicit operator bool() const { return !!this->first; }
C& operator*() const { return *(this->first); }
C* operator->() const { return this->first; }
std::shared_ptr<C> getPtr() const { return this->first; }
};
// ids of device ports created at runtime via 'connectExternalDevice'.
// Also stores a list of ids of mix ports with dynamic profiles that were populated from
// the connected port. This list can be empty, thus an int->int multimap can't be used.
using ConnectedDevicePorts = std::map<int32_t, std::vector<int32_t>>;
// Maps port ids and port config ids to patch ids.
// Multimap because both ports and configs can be used by multiple patches.
using Patches = std::multimap<int32_t, int32_t>;
const Type mType;
std::unique_ptr<internal::Configuration> mConfig;
ModuleDebug mDebug;
@@ -177,19 +170,18 @@ class Module : public BnModule {
ChildInterface<IBluetooth> mBluetooth;
ChildInterface<IBluetoothA2dp> mBluetoothA2dp;
ChildInterface<IBluetoothLe> mBluetoothLe;
// ids of device ports created at runtime via 'connectExternalDevice'.
// Also stores ids of mix ports with dynamic profiles which got populated from the connected
// port.
std::map<int32_t, std::vector<int32_t>> mConnectedDevicePorts;
ConnectedDevicePorts mConnectedDevicePorts;
Streams mStreams;
// Maps port ids and port config ids to patch ids.
// Multimap because both ports and configs can be used by multiple patches.
std::multimap<int32_t, int32_t> mPatches;
Patches mPatches;
bool mMicMute = false;
bool mMasterMute = false;
float mMasterVolume = 1.0f;
ChildInterface<sounddose::ISoundDose> mSoundDose;
std::optional<bool> mIsMmapSupported;
protected:
// The following virtual functions are intended for vendor extension via inheritance.
// 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(
@@ -204,8 +196,30 @@ class Module : public BnModule {
virtual ndk::ScopedAStatus onMasterMuteChanged(bool mute);
virtual ndk::ScopedAStatus onMasterVolumeChanged(float volume);
bool mMasterMute = false;
float mMasterVolume = 1.0f;
// Utility and helper functions accessible to subclasses.
void cleanUpPatch(int32_t patchId);
ndk::ScopedAStatus createStreamContext(
int32_t in_portConfigId, int64_t in_bufferSizeFrames,
std::shared_ptr<IStreamCallback> asyncCallback,
std::shared_ptr<IStreamOutEventCallback> outEventCallback,
::aidl::android::hardware::audio::core::StreamContext* out_context);
std::vector<::aidl::android::media::audio::common::AudioDevice> findConnectedDevices(
int32_t portConfigId);
std::set<int32_t> findConnectedPortConfigIds(int32_t portConfigId);
ndk::ScopedAStatus findPortIdForNewStream(
int32_t in_portConfigId, ::aidl::android::media::audio::common::AudioPort** port);
internal::Configuration& getConfig();
const ConnectedDevicePorts& getConnectedDevicePorts() const { return mConnectedDevicePorts; }
bool getMasterMute() const { return mMasterMute; }
bool getMasterVolume() const { return mMasterVolume; }
bool getMicMute() const { return mMicMute; }
const Patches& getPatches() const { return mPatches; }
const Streams& getStreams() const { return mStreams; }
bool isMmapSupported();
template <typename C>
std::set<int32_t> portIdsFromPortConfigIds(C portConfigIds);
void registerPatch(const AudioPatch& patch);
void updateStreamsConnectedState(const AudioPatch& oldPatch, const AudioPatch& newPatch);
};
} // namespace aidl::android::hardware::audio::core

View File

@@ -175,8 +175,8 @@ void ModuleUsb::onExternalDeviceConnectionChanged(
return;
}
const int card = address.get<AudioDeviceAddress::alsa>()[0];
usb::UsbAlsaMixerControl::getInstance().setDeviceConnectionState(card, mMasterMute,
mMasterVolume, connected);
usb::UsbAlsaMixerControl::getInstance().setDeviceConnectionState(card, getMasterMute(),
getMasterVolume(), connected);
}
ndk::ScopedAStatus ModuleUsb::onMasterMuteChanged(bool mute) {