blob: ce71d709039145d5834644fc69eab7d04bd44afe [file] [log] [blame]
/*
* Copyright (C) 2022 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <functional>
#include <iostream>
#include <map>
#include <memory>
#include <optional>
#include <set>
#include <Utils.h>
#include <aidl/android/hardware/audio/core/BnModule.h>
#include "core-impl/ChildInterface.h"
#include "core-impl/Stream.h"
namespace aidl::android::hardware::audio::core {
class Module : public BnModule {
public:
struct Configuration {
std::vector<::aidl::android::media::audio::common::AudioPort> ports;
std::vector<::aidl::android::media::audio::common::AudioPortConfig> portConfigs;
std::vector<::aidl::android::media::audio::common::AudioPortConfig> initialConfigs;
// Port id -> List of profiles to use when the device port state is set to 'connected'
// in connection simulation mode.
std::map<int32_t, std::vector<::aidl::android::media::audio::common::AudioProfile>>
connectedProfiles;
std::vector<AudioRoute> routes;
std::vector<AudioPatch> patches;
int32_t nextPortId = 1;
int32_t nextPatchId = 1;
};
enum Type : int { DEFAULT, R_SUBMIX, STUB, USB, BLUETOOTH };
static std::shared_ptr<Module> createInstance(Type type) {
return createInstance(type, std::make_unique<Configuration>());
}
static std::shared_ptr<Module> createInstance(Type type,
std::unique_ptr<Configuration>&& config);
static std::optional<Type> typeFromString(const std::string& type);
Module(Type type, std::unique_ptr<Configuration>&& config);
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;
ndk::ScopedAStatus getTelephony(std::shared_ptr<ITelephony>* _aidl_return) override;
ndk::ScopedAStatus getBluetooth(std::shared_ptr<IBluetooth>* _aidl_return) override;
ndk::ScopedAStatus getBluetoothA2dp(std::shared_ptr<IBluetoothA2dp>* _aidl_return) override;
ndk::ScopedAStatus getBluetoothLe(std::shared_ptr<IBluetoothLe>* _aidl_return) override;
ndk::ScopedAStatus connectExternalDevice(
const ::aidl::android::media::audio::common::AudioPort& in_templateIdAndAdditionalData,
::aidl::android::media::audio::common::AudioPort* _aidl_return) override;
ndk::ScopedAStatus disconnectExternalDevice(int32_t in_portId) override;
ndk::ScopedAStatus prepareToDisconnectExternalDevice(int32_t in_portId) override;
ndk::ScopedAStatus getAudioPatches(std::vector<AudioPatch>* _aidl_return) override;
ndk::ScopedAStatus getAudioPort(
int32_t in_portId,
::aidl::android::media::audio::common::AudioPort* _aidl_return) override;
ndk::ScopedAStatus getAudioPortConfigs(
std::vector<::aidl::android::media::audio::common::AudioPortConfig>* _aidl_return)
override;
ndk::ScopedAStatus getAudioPorts(
std::vector<::aidl::android::media::audio::common::AudioPort>* _aidl_return) override;
ndk::ScopedAStatus getAudioRoutes(std::vector<AudioRoute>* _aidl_return) override;
ndk::ScopedAStatus getAudioRoutesForAudioPort(
int32_t in_portId,
std::vector<::aidl::android::hardware::audio::core::AudioRoute>* _aidl_return) override;
ndk::ScopedAStatus openInputStream(
const ::aidl::android::hardware::audio::core::IModule::OpenInputStreamArguments&
in_args,
::aidl::android::hardware::audio::core::IModule::OpenInputStreamReturn* _aidl_return)
override;
ndk::ScopedAStatus openOutputStream(
const ::aidl::android::hardware::audio::core::IModule::OpenOutputStreamArguments&
in_args,
::aidl::android::hardware::audio::core::IModule::OpenOutputStreamReturn* _aidl_return)
override;
ndk::ScopedAStatus getSupportedPlaybackRateFactors(
SupportedPlaybackRateFactors* _aidl_return) override;
ndk::ScopedAStatus setAudioPatch(const AudioPatch& in_requested,
AudioPatch* _aidl_return) override;
ndk::ScopedAStatus setAudioPortConfig(
const ::aidl::android::media::audio::common::AudioPortConfig& in_requested,
::aidl::android::media::audio::common::AudioPortConfig* out_suggested,
bool* _aidl_return) override;
ndk::ScopedAStatus resetAudioPatch(int32_t in_patchId) override;
ndk::ScopedAStatus resetAudioPortConfig(int32_t in_portConfigId) override;
ndk::ScopedAStatus getMasterMute(bool* _aidl_return) override;
ndk::ScopedAStatus setMasterMute(bool in_mute) override;
ndk::ScopedAStatus getMasterVolume(float* _aidl_return) override;
ndk::ScopedAStatus setMasterVolume(float in_volume) override;
ndk::ScopedAStatus getMicMute(bool* _aidl_return) override;
ndk::ScopedAStatus setMicMute(bool in_mute) override;
ndk::ScopedAStatus getMicrophones(
std::vector<::aidl::android::media::audio::common::MicrophoneInfo>* _aidl_return)
override;
ndk::ScopedAStatus updateAudioMode(
::aidl::android::media::audio::common::AudioMode in_mode) override;
ndk::ScopedAStatus updateScreenRotation(
::aidl::android::hardware::audio::core::IModule::ScreenRotation in_rotation) override;
ndk::ScopedAStatus updateScreenState(bool in_isTurnedOn) override;
ndk::ScopedAStatus getSoundDose(std::shared_ptr<sounddose::ISoundDose>* _aidl_return) override;
ndk::ScopedAStatus generateHwAvSyncId(int32_t* _aidl_return) override;
ndk::ScopedAStatus getVendorParameters(const std::vector<std::string>& in_ids,
std::vector<VendorParameter>* _aidl_return) override;
ndk::ScopedAStatus setVendorParameters(const std::vector<VendorParameter>& in_parameters,
bool in_async) override;
ndk::ScopedAStatus addDeviceEffect(
int32_t in_portConfigId,
const std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect>& in_effect)
override;
ndk::ScopedAStatus removeDeviceEffect(
int32_t in_portConfigId,
const std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect>& in_effect)
override;
ndk::ScopedAStatus getMmapPolicyInfos(
::aidl::android::media::audio::common::AudioMMapPolicyType mmapPolicyType,
std::vector<::aidl::android::media::audio::common::AudioMMapPolicyInfo>* _aidl_return)
override;
ndk::ScopedAStatus supportsVariableLatency(bool* _aidl_return) override;
ndk::ScopedAStatus getAAudioMixerBurstCount(int32_t* _aidl_return) override;
ndk::ScopedAStatus getAAudioHardwareBurstMinUsec(int32_t* _aidl_return) override;
// 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;
};
// 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::set<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<Configuration> mConfig;
ModuleDebug mDebug;
VendorDebug mVendorDebug;
ConnectedDevicePorts mConnectedDevicePorts;
Streams mStreams;
Patches mPatches;
bool mMicMute = false;
bool mMasterMute = false;
float mMasterVolume = 1.0f;
ChildInterface<sounddose::SoundDose> mSoundDose;
std::optional<bool> mIsMmapSupported;
protected:
// The following virtual functions are intended for vendor extension via inheritance.
virtual ndk::ScopedAStatus createInputStream(
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(
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;
// 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(
::aidl::android::media::audio::common::AudioPort* audioPort, int32_t nextPortId);
// If the module finds that the patch endpoints configurations are not matched, the returned
// error code must correspond to the errors of `IModule.setAudioPatch` method.
virtual ndk::ScopedAStatus checkAudioPatchEndpointsMatch(
const std::vector<::aidl::android::media::audio::common::AudioPortConfig*>& sources,
const std::vector<::aidl::android::media::audio::common::AudioPortConfig*>& sinks);
virtual void onExternalDeviceConnectionChanged(
const ::aidl::android::media::audio::common::AudioPort& audioPort, bool connected);
virtual void onPrepareToDisconnectExternalDevice(
const ::aidl::android::media::audio::common::AudioPort& audioPort);
virtual ndk::ScopedAStatus onMasterMuteChanged(bool mute);
virtual ndk::ScopedAStatus onMasterVolumeChanged(float volume);
virtual std::vector<::aidl::android::media::audio::common::MicrophoneInfo> getMicrophoneInfos();
virtual std::unique_ptr<Configuration> initializeConfig();
virtual int32_t getNominalLatencyMs(
const ::aidl::android::media::audio::common::AudioPortConfig& portConfig);
// Utility and helper functions accessible to subclasses.
static int32_t calculateBufferSizeFrames(int32_t latencyMs, int32_t sampleRateHz) {
const int32_t rawSizeFrames =
aidl::android::hardware::audio::common::frameCountFromDurationMs(latencyMs,
sampleRateHz);
if (latencyMs >= 5) return rawSizeFrames;
int32_t powerOf2 = 1;
while (powerOf2 < rawSizeFrames) powerOf2 <<= 1;
return powerOf2;
}
ndk::ScopedAStatus bluetoothParametersUpdated();
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);
// Note: does not assign an ID to the config.
bool generateDefaultPortConfig(const ::aidl::android::media::audio::common::AudioPort& port,
::aidl::android::media::audio::common::AudioPortConfig* config);
std::vector<AudioRoute*> getAudioRoutesForAudioPortImpl(int32_t portId);
Configuration& getConfig();
const ConnectedDevicePorts& getConnectedDevicePorts() const { return mConnectedDevicePorts; }
bool getMasterMute() const { return mMasterMute; }
bool getMasterVolume() const { return mMasterVolume; }
bool getMicMute() const { return mMicMute; }
const ModuleDebug& getModuleDebug() const { return mDebug; }
const Patches& getPatches() const { return mPatches; }
std::set<int32_t> getRoutableAudioPortIds(int32_t portId,
std::vector<AudioRoute*>* routes = nullptr);
const Streams& getStreams() const { return mStreams; }
Type getType() const { return mType; }
bool isMmapSupported();
void populateConnectedProfiles();
template <typename C>
std::set<int32_t> portIdsFromPortConfigIds(C portConfigIds);
void registerPatch(const AudioPatch& patch);
ndk::ScopedAStatus setAudioPortConfigImpl(
const ::aidl::android::media::audio::common::AudioPortConfig& in_requested,
const std::function<bool(const ::aidl::android::media::audio::common::AudioPort& port,
::aidl::android::media::audio::common::AudioPortConfig*
config)>& fillPortConfig,
::aidl::android::media::audio::common::AudioPortConfig* out_suggested, bool* applied);
ndk::ScopedAStatus updateStreamsConnectedState(const AudioPatch& oldPatch,
const AudioPatch& newPatch);
};
std::ostream& operator<<(std::ostream& os, Module::Type t);
} // namespace aidl::android::hardware::audio::core