/* * 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 #include #include #include #include #include #include #include #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> connectedProfiles; std::vector routes; std::vector patches; int32_t nextPortId = 1; int32_t nextPatchId = 1; }; enum Type : int { DEFAULT, R_SUBMIX, STUB, USB, BLUETOOTH }; static std::shared_ptr createInstance(Type type) { return createInstance(type, std::make_unique()); } static std::shared_ptr createInstance(Type type, std::unique_ptr&& config); static std::optional typeFromString(const std::string& type); Module(Type type, std::unique_ptr&& 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* _aidl_return) override; ndk::ScopedAStatus getBluetooth(std::shared_ptr* _aidl_return) override; ndk::ScopedAStatus getBluetoothA2dp(std::shared_ptr* _aidl_return) override; ndk::ScopedAStatus getBluetoothLe(std::shared_ptr* _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* _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* _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* _aidl_return) override; ndk::ScopedAStatus generateHwAvSyncId(int32_t* _aidl_return) override; ndk::ScopedAStatus getVendorParameters(const std::vector& in_ids, std::vector* _aidl_return) override; ndk::ScopedAStatus setVendorParameters(const std::vector& 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>; // 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; const Type mType; std::unique_ptr mConfig; ModuleDebug mDebug; VendorDebug mVendorDebug; ConnectedDevicePorts mConnectedDevicePorts; Streams mStreams; Patches mPatches; bool mMicMute = false; bool mMasterMute = false; float mMasterVolume = 1.0f; ChildInterface mSoundDose; std::optional 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* 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* 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 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); // Round up to nearest 16 frames since in the framework this is the size of a mixer burst. const int32_t multipleOf16 = (rawSizeFrames + 15) & ~15; if (sampleRateHz < 44100 || multipleOf16 <= 512) return multipleOf16; // Larger buffers should use powers of 2. int32_t powerOf2 = 1; while (powerOf2 < multipleOf16) 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 asyncCallback, std::shared_ptr outEventCallback, ::aidl::android::hardware::audio::core::StreamContext* out_context); std::vector<::aidl::android::media::audio::common::AudioDevice> findConnectedDevices( int32_t portConfigId); std::set 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 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 getRoutableAudioPortIds(int32_t portId, std::vector* routes = nullptr); const Streams& getStreams() const { return mStreams; } Type getType() const { return mType; } bool isMmapSupported(); void populateConnectedProfiles(); template std::set portIdsFromPortConfigIds(C portConfigIds); void registerPatch(const AudioPatch& patch); ndk::ScopedAStatus setAudioPortConfigImpl( const ::aidl::android::media::audio::common::AudioPortConfig& in_requested, const std::function& 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