1 /*
2  * Copyright (C) 2022 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #pragma once
18 
19 #include <functional>
20 #include <iostream>
21 #include <map>
22 #include <memory>
23 #include <optional>
24 #include <set>
25 
26 #include <Utils.h>
27 #include <aidl/android/hardware/audio/core/BnModule.h>
28 
29 #include "core-impl/ChildInterface.h"
30 #include "core-impl/Stream.h"
31 
32 namespace aidl::android::hardware::audio::core {
33 
34 class Module : public BnModule {
35   public:
36     struct Configuration {
37         std::vector<::aidl::android::media::audio::common::AudioPort> ports;
38         std::vector<::aidl::android::media::audio::common::AudioPortConfig> portConfigs;
39         std::vector<::aidl::android::media::audio::common::AudioPortConfig> initialConfigs;
40         // Port id -> List of profiles to use when the device port state is set to 'connected'
41         // in connection simulation mode.
42         std::map<int32_t, std::vector<::aidl::android::media::audio::common::AudioProfile>>
43                 connectedProfiles;
44         std::vector<AudioRoute> routes;
45         std::vector<AudioPatch> patches;
46         int32_t nextPortId = 1;
47         int32_t nextPatchId = 1;
48     };
49     enum Type : int { DEFAULT, R_SUBMIX, STUB, USB, BLUETOOTH };
50 
createInstance(Type type)51     static std::shared_ptr<Module> createInstance(Type type) {
52         return createInstance(type, std::make_unique<Configuration>());
53     }
54     static std::shared_ptr<Module> createInstance(Type type,
55                                                   std::unique_ptr<Configuration>&& config);
56     static std::optional<Type> typeFromString(const std::string& type);
57 
58     Module(Type type, std::unique_ptr<Configuration>&& config);
59 
60   protected:
61     // The vendor extension done via inheritance can override interface methods and augment
62     // a call to the base implementation.
63 
64     ndk::ScopedAStatus setModuleDebug(
65             const ::aidl::android::hardware::audio::core::ModuleDebug& in_debug) override;
66     ndk::ScopedAStatus getTelephony(std::shared_ptr<ITelephony>* _aidl_return) override;
67     ndk::ScopedAStatus getBluetooth(std::shared_ptr<IBluetooth>* _aidl_return) override;
68     ndk::ScopedAStatus getBluetoothA2dp(std::shared_ptr<IBluetoothA2dp>* _aidl_return) override;
69     ndk::ScopedAStatus getBluetoothLe(std::shared_ptr<IBluetoothLe>* _aidl_return) override;
70     ndk::ScopedAStatus connectExternalDevice(
71             const ::aidl::android::media::audio::common::AudioPort& in_templateIdAndAdditionalData,
72             ::aidl::android::media::audio::common::AudioPort* _aidl_return) override;
73     ndk::ScopedAStatus disconnectExternalDevice(int32_t in_portId) override;
74     ndk::ScopedAStatus prepareToDisconnectExternalDevice(int32_t in_portId) override;
75     ndk::ScopedAStatus getAudioPatches(std::vector<AudioPatch>* _aidl_return) override;
76     ndk::ScopedAStatus getAudioPort(
77             int32_t in_portId,
78             ::aidl::android::media::audio::common::AudioPort* _aidl_return) override;
79     ndk::ScopedAStatus getAudioPortConfigs(
80             std::vector<::aidl::android::media::audio::common::AudioPortConfig>* _aidl_return)
81             override;
82     ndk::ScopedAStatus getAudioPorts(
83             std::vector<::aidl::android::media::audio::common::AudioPort>* _aidl_return) override;
84     ndk::ScopedAStatus getAudioRoutes(std::vector<AudioRoute>* _aidl_return) override;
85     ndk::ScopedAStatus getAudioRoutesForAudioPort(
86             int32_t in_portId,
87             std::vector<::aidl::android::hardware::audio::core::AudioRoute>* _aidl_return) override;
88     ndk::ScopedAStatus openInputStream(
89             const ::aidl::android::hardware::audio::core::IModule::OpenInputStreamArguments&
90                     in_args,
91             ::aidl::android::hardware::audio::core::IModule::OpenInputStreamReturn* _aidl_return)
92             override;
93     ndk::ScopedAStatus openOutputStream(
94             const ::aidl::android::hardware::audio::core::IModule::OpenOutputStreamArguments&
95                     in_args,
96             ::aidl::android::hardware::audio::core::IModule::OpenOutputStreamReturn* _aidl_return)
97             override;
98     ndk::ScopedAStatus getSupportedPlaybackRateFactors(
99             SupportedPlaybackRateFactors* _aidl_return) override;
100     ndk::ScopedAStatus setAudioPatch(const AudioPatch& in_requested,
101                                      AudioPatch* _aidl_return) override;
102     ndk::ScopedAStatus setAudioPortConfig(
103             const ::aidl::android::media::audio::common::AudioPortConfig& in_requested,
104             ::aidl::android::media::audio::common::AudioPortConfig* out_suggested,
105             bool* _aidl_return) override;
106     ndk::ScopedAStatus resetAudioPatch(int32_t in_patchId) override;
107     ndk::ScopedAStatus resetAudioPortConfig(int32_t in_portConfigId) override;
108     ndk::ScopedAStatus getMasterMute(bool* _aidl_return) override;
109     ndk::ScopedAStatus setMasterMute(bool in_mute) override;
110     ndk::ScopedAStatus getMasterVolume(float* _aidl_return) override;
111     ndk::ScopedAStatus setMasterVolume(float in_volume) override;
112     ndk::ScopedAStatus getMicMute(bool* _aidl_return) override;
113     ndk::ScopedAStatus setMicMute(bool in_mute) override;
114     ndk::ScopedAStatus getMicrophones(
115             std::vector<::aidl::android::media::audio::common::MicrophoneInfo>* _aidl_return)
116             override;
117     ndk::ScopedAStatus updateAudioMode(
118             ::aidl::android::media::audio::common::AudioMode in_mode) override;
119     ndk::ScopedAStatus updateScreenRotation(
120             ::aidl::android::hardware::audio::core::IModule::ScreenRotation in_rotation) override;
121     ndk::ScopedAStatus updateScreenState(bool in_isTurnedOn) override;
122     ndk::ScopedAStatus getSoundDose(std::shared_ptr<sounddose::ISoundDose>* _aidl_return) override;
123     ndk::ScopedAStatus generateHwAvSyncId(int32_t* _aidl_return) override;
124     ndk::ScopedAStatus getVendorParameters(const std::vector<std::string>& in_ids,
125                                            std::vector<VendorParameter>* _aidl_return) override;
126     ndk::ScopedAStatus setVendorParameters(const std::vector<VendorParameter>& in_parameters,
127                                            bool in_async) override;
128     ndk::ScopedAStatus addDeviceEffect(
129             int32_t in_portConfigId,
130             const std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect>& in_effect)
131             override;
132     ndk::ScopedAStatus removeDeviceEffect(
133             int32_t in_portConfigId,
134             const std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect>& in_effect)
135             override;
136     ndk::ScopedAStatus getMmapPolicyInfos(
137             ::aidl::android::media::audio::common::AudioMMapPolicyType mmapPolicyType,
138             std::vector<::aidl::android::media::audio::common::AudioMMapPolicyInfo>* _aidl_return)
139             override;
140     ndk::ScopedAStatus supportsVariableLatency(bool* _aidl_return) override;
141     ndk::ScopedAStatus getAAudioMixerBurstCount(int32_t* _aidl_return) override;
142     ndk::ScopedAStatus getAAudioHardwareBurstMinUsec(int32_t* _aidl_return) override;
143 
144     // The maximum stream buffer size is 1 GiB = 2 ** 30 bytes;
145     static constexpr int32_t kMaximumStreamBufferSizeBytes = 1 << 30;
146 
147   private:
148     struct VendorDebug {
149         static const std::string kForceTransientBurstName;
150         static const std::string kForceSynchronousDrainName;
151         bool forceTransientBurst = false;
152         bool forceSynchronousDrain = false;
153     };
154     // ids of device ports created at runtime via 'connectExternalDevice'.
155     // Also stores a list of ids of mix ports with dynamic profiles that were populated from
156     // the connected port. This list can be empty, thus an int->int multimap can't be used.
157     using ConnectedDevicePorts = std::map<int32_t, std::set<int32_t>>;
158     // Maps port ids and port config ids to patch ids.
159     // Multimap because both ports and configs can be used by multiple patches.
160     using Patches = std::multimap<int32_t, int32_t>;
161 
162     const Type mType;
163     std::unique_ptr<Configuration> mConfig;
164     ModuleDebug mDebug;
165     VendorDebug mVendorDebug;
166     ConnectedDevicePorts mConnectedDevicePorts;
167     Streams mStreams;
168     Patches mPatches;
169     bool mMicMute = false;
170     bool mMasterMute = false;
171     float mMasterVolume = 1.0f;
172     ChildInterface<sounddose::SoundDose> mSoundDose;
173     std::optional<bool> mIsMmapSupported;
174 
175   protected:
176     // The following virtual functions are intended for vendor extension via inheritance.
177 
178     virtual ndk::ScopedAStatus createInputStream(
179             StreamContext&& context,
180             const ::aidl::android::hardware::audio::common::SinkMetadata& sinkMetadata,
181             const std::vector<::aidl::android::media::audio::common::MicrophoneInfo>& microphones,
182             std::shared_ptr<StreamIn>* result) = 0;
183     virtual ndk::ScopedAStatus createOutputStream(
184             StreamContext&& context,
185             const ::aidl::android::hardware::audio::common::SourceMetadata& sourceMetadata,
186             const std::optional<::aidl::android::media::audio::common::AudioOffloadInfo>&
187                     offloadInfo,
188             std::shared_ptr<StreamOut>* result) = 0;
189     // If the module is unable to populate the connected device port correctly, the returned error
190     // code must correspond to the errors of `IModule.connectedExternalDevice` method.
191     virtual ndk::ScopedAStatus populateConnectedDevicePort(
192             ::aidl::android::media::audio::common::AudioPort* audioPort, int32_t nextPortId);
193     // If the module finds that the patch endpoints configurations are not matched, the returned
194     // error code must correspond to the errors of `IModule.setAudioPatch` method.
195     virtual ndk::ScopedAStatus checkAudioPatchEndpointsMatch(
196             const std::vector<::aidl::android::media::audio::common::AudioPortConfig*>& sources,
197             const std::vector<::aidl::android::media::audio::common::AudioPortConfig*>& sinks);
198     virtual void onExternalDeviceConnectionChanged(
199             const ::aidl::android::media::audio::common::AudioPort& audioPort, bool connected);
200     virtual void onPrepareToDisconnectExternalDevice(
201             const ::aidl::android::media::audio::common::AudioPort& audioPort);
202     virtual ndk::ScopedAStatus onMasterMuteChanged(bool mute);
203     virtual ndk::ScopedAStatus onMasterVolumeChanged(float volume);
204     virtual std::vector<::aidl::android::media::audio::common::MicrophoneInfo> getMicrophoneInfos();
205     virtual std::unique_ptr<Configuration> initializeConfig();
206     virtual int32_t getNominalLatencyMs(
207             const ::aidl::android::media::audio::common::AudioPortConfig& portConfig);
208 
209     // Utility and helper functions accessible to subclasses.
calculateBufferSizeFrames(int32_t latencyMs,int32_t sampleRateHz)210     static int32_t calculateBufferSizeFrames(int32_t latencyMs, int32_t sampleRateHz) {
211         const int32_t rawSizeFrames =
212                 aidl::android::hardware::audio::common::frameCountFromDurationMs(latencyMs,
213                                                                                  sampleRateHz);
214         // Round up to nearest 16 frames since in the framework this is the size of a mixer burst.
215         const int32_t multipleOf16 = (rawSizeFrames + 15) & ~15;
216         if (sampleRateHz < 44100 || multipleOf16 <= 512) return multipleOf16;
217         // Larger buffers should use powers of 2.
218         int32_t powerOf2 = 1;
219         while (powerOf2 < multipleOf16) powerOf2 <<= 1;
220         return powerOf2;
221     }
222 
223     ndk::ScopedAStatus bluetoothParametersUpdated();
224     void cleanUpPatch(int32_t patchId);
225     ndk::ScopedAStatus createStreamContext(
226             int32_t in_portConfigId, int64_t in_bufferSizeFrames,
227             std::shared_ptr<IStreamCallback> asyncCallback,
228             std::shared_ptr<IStreamOutEventCallback> outEventCallback,
229             ::aidl::android::hardware::audio::core::StreamContext* out_context);
230     std::vector<::aidl::android::media::audio::common::AudioDevice> findConnectedDevices(
231             int32_t portConfigId);
232     std::set<int32_t> findConnectedPortConfigIds(int32_t portConfigId);
233     ndk::ScopedAStatus findPortIdForNewStream(
234             int32_t in_portConfigId, ::aidl::android::media::audio::common::AudioPort** port);
235     // Note: does not assign an ID to the config.
236     bool generateDefaultPortConfig(const ::aidl::android::media::audio::common::AudioPort& port,
237                                    ::aidl::android::media::audio::common::AudioPortConfig* config);
238     std::vector<AudioRoute*> getAudioRoutesForAudioPortImpl(int32_t portId);
239     Configuration& getConfig();
getConnectedDevicePorts()240     const ConnectedDevicePorts& getConnectedDevicePorts() const { return mConnectedDevicePorts; }
getMasterMute()241     bool getMasterMute() const { return mMasterMute; }
getMasterVolume()242     bool getMasterVolume() const { return mMasterVolume; }
getMicMute()243     bool getMicMute() const { return mMicMute; }
getModuleDebug()244     const ModuleDebug& getModuleDebug() const { return mDebug; }
getPatches()245     const Patches& getPatches() const { return mPatches; }
246     std::set<int32_t> getRoutableAudioPortIds(int32_t portId,
247                                               std::vector<AudioRoute*>* routes = nullptr);
getStreams()248     const Streams& getStreams() const { return mStreams; }
getType()249     Type getType() const { return mType; }
250     bool isMmapSupported();
251     void populateConnectedProfiles();
252     template <typename C>
253     std::set<int32_t> portIdsFromPortConfigIds(C portConfigIds);
254     void registerPatch(const AudioPatch& patch);
255     ndk::ScopedAStatus setAudioPortConfigImpl(
256             const ::aidl::android::media::audio::common::AudioPortConfig& in_requested,
257             const std::function<bool(const ::aidl::android::media::audio::common::AudioPort& port,
258                                      ::aidl::android::media::audio::common::AudioPortConfig*
259                                              config)>& fillPortConfig,
260             ::aidl::android::media::audio::common::AudioPortConfig* out_suggested, bool* applied);
261     ndk::ScopedAStatus updateStreamsConnectedState(const AudioPatch& oldPatch,
262                                                    const AudioPatch& newPatch);
263 };
264 
265 std::ostream& operator<<(std::ostream& os, Module::Type t);
266 
267 }  // namespace aidl::android::hardware::audio::core
268