xref: /aosp_15_r20/frameworks/av/media/libaudiohal/tests/CoreAudioHalAidl_test.cpp (revision ec779b8e0859a360c3d303172224686826e6e0e1)
1 /*
2  * Copyright 2023 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 #include <algorithm>
18 #include <memory>
19 #include <mutex>
20 #include <string>
21 #include <thread>
22 #include <vector>
23 
24 #define LOG_TAG "CoreAudioHalAidlTest"
25 #include <gtest/gtest.h>
26 
27 #include <DeviceHalAidl.h>
28 #include <Hal2AidlMapper.h>
29 #include <StreamHalAidl.h>
30 #include <aidl/android/hardware/audio/core/BnModule.h>
31 #include <aidl/android/hardware/audio/core/BnStreamCommon.h>
32 #include <aidl/android/hardware/audio/core/BnStreamOut.h>
33 #include <aidl/android/media/audio/BnHalAdapterVendorExtension.h>
34 #include <aidl/android/media/audio/common/AudioGainMode.h>
35 #include <aidl/android/media/audio/common/Int.h>
36 #include <utils/Log.h>
37 
38 namespace {
39 
40 using ::aidl::android::hardware::audio::core::AudioPatch;
41 using ::aidl::android::hardware::audio::core::AudioRoute;
42 using ::aidl::android::hardware::audio::core::VendorParameter;
43 using ::aidl::android::media::audio::common::AudioChannelLayout;
44 using ::aidl::android::media::audio::common::AudioConfig;
45 using ::aidl::android::media::audio::common::AudioDevice;
46 using ::aidl::android::media::audio::common::AudioDeviceDescription;
47 using ::aidl::android::media::audio::common::AudioDeviceType;
48 using ::aidl::android::media::audio::common::AudioFormatDescription;
49 using ::aidl::android::media::audio::common::AudioFormatType;
50 using ::aidl::android::media::audio::common::AudioGainConfig;
51 using ::aidl::android::media::audio::common::AudioGainMode;
52 using ::aidl::android::media::audio::common::AudioIoFlags;
53 using ::aidl::android::media::audio::common::AudioPort;
54 using ::aidl::android::media::audio::common::AudioPortConfig;
55 using ::aidl::android::media::audio::common::AudioPortDeviceExt;
56 using ::aidl::android::media::audio::common::AudioPortExt;
57 using ::aidl::android::media::audio::common::AudioPortMixExt;
58 using ::aidl::android::media::audio::common::AudioProfile;
59 using ::aidl::android::media::audio::common::AudioSource;
60 using ::aidl::android::media::audio::common::PcmType;
61 
62 class VendorParameterMock {
63   public:
getRetrievedParameterIds() const64     const std::vector<std::string>& getRetrievedParameterIds() const { return mGetParameterIds; }
getAsyncParameters() const65     const std::vector<VendorParameter>& getAsyncParameters() const { return mAsyncParameters; }
getSyncParameters() const66     const std::vector<VendorParameter>& getSyncParameters() const { return mSyncParameters; }
67 
68   protected:
getVendorParameters(const std::vector<std::string> & in_parameterIds)69     ndk::ScopedAStatus getVendorParameters(const std::vector<std::string>& in_parameterIds) {
70         mGetParameterIds.insert(mGetParameterIds.end(), in_parameterIds.begin(),
71                                 in_parameterIds.end());
72         return ndk::ScopedAStatus::ok();
73     }
setVendorParameters(const std::vector<VendorParameter> & in_parameters,bool async)74     ndk::ScopedAStatus setVendorParameters(const std::vector<VendorParameter>& in_parameters,
75                                            bool async) {
76         if (async) {
77             mAsyncParameters.insert(mAsyncParameters.end(), in_parameters.begin(),
78                                     in_parameters.end());
79         } else {
80             mSyncParameters.insert(mSyncParameters.end(), in_parameters.begin(),
81                                    in_parameters.end());
82         }
83         return ndk::ScopedAStatus::ok();
84     }
85 
86   private:
87     std::vector<std::string> mGetParameterIds;
88     std::vector<VendorParameter> mAsyncParameters;
89     std::vector<VendorParameter> mSyncParameters;
90 };
91 
92 struct Configuration {
93     std::vector<AudioPort> ports;
94     std::vector<AudioPortConfig> portConfigs;
95     std::vector<AudioRoute> routes;
96     std::vector<AudioPatch> patches;
97     int32_t nextPortId = 1;
98     int32_t nextPatchId = 1;
99 };
100 
fillProfile(AudioProfile * profile,const std::vector<int32_t> & channelLayouts,const std::vector<int32_t> & sampleRates)101 void fillProfile(AudioProfile* profile, const std::vector<int32_t>& channelLayouts,
102                  const std::vector<int32_t>& sampleRates) {
103     for (auto layout : channelLayouts) {
104         profile->channelMasks.push_back(
105                 AudioChannelLayout::make<AudioChannelLayout::layoutMask>(layout));
106     }
107     profile->sampleRates.insert(profile->sampleRates.end(), sampleRates.begin(), sampleRates.end());
108 }
109 
createProfile(PcmType pcmType,const std::vector<int32_t> & channelLayouts,const std::vector<int32_t> & sampleRates)110 AudioProfile createProfile(PcmType pcmType, const std::vector<int32_t>& channelLayouts,
111                            const std::vector<int32_t>& sampleRates) {
112     AudioProfile profile;
113     profile.format.type = AudioFormatType::PCM;
114     profile.format.pcm = pcmType;
115     fillProfile(&profile, channelLayouts, sampleRates);
116     return profile;
117 }
118 
createPortDeviceExt(AudioDeviceType devType,int32_t flags,std::string connection="")119 AudioPortExt createPortDeviceExt(AudioDeviceType devType, int32_t flags,
120                                  std::string connection = "") {
121     AudioPortDeviceExt deviceExt;
122     deviceExt.device.type.type = devType;
123     if (devType == AudioDeviceType::IN_MICROPHONE && connection.empty()) {
124         deviceExt.device.address = "bottom";
125     } else if (devType == AudioDeviceType::IN_MICROPHONE_BACK && connection.empty()) {
126         deviceExt.device.address = "back";
127     }
128     deviceExt.device.type.connection = std::move(connection);
129     deviceExt.flags = flags;
130     return AudioPortExt::make<AudioPortExt::device>(deviceExt);
131 }
132 
createPortMixExt(int32_t maxOpenStreamCount,int32_t maxActiveStreamCount)133 AudioPortExt createPortMixExt(int32_t maxOpenStreamCount, int32_t maxActiveStreamCount) {
134     AudioPortMixExt mixExt;
135     mixExt.maxOpenStreamCount = maxOpenStreamCount;
136     mixExt.maxActiveStreamCount = maxActiveStreamCount;
137     return AudioPortExt::make<AudioPortExt::mix>(mixExt);
138 }
139 
createPort(int32_t id,const std::string & name,int32_t flags,bool isInput,const AudioPortExt & ext)140 AudioPort createPort(int32_t id, const std::string& name, int32_t flags, bool isInput,
141                      const AudioPortExt& ext) {
142     AudioPort port;
143     port.id = id;
144     port.name = name;
145     port.flags = isInput ? AudioIoFlags::make<AudioIoFlags::input>(flags)
146                          : AudioIoFlags::make<AudioIoFlags::output>(flags);
147     port.ext = ext;
148     return port;
149 }
150 
createRoute(const std::vector<AudioPort> & sources,const AudioPort & sink)151 AudioRoute createRoute(const std::vector<AudioPort>& sources, const AudioPort& sink) {
152     AudioRoute route;
153     route.sinkPortId = sink.id;
154     std::transform(sources.begin(), sources.end(), std::back_inserter(route.sourcePortIds),
155                    [](const auto& port) { return port.id; });
156     return route;
157 }
158 
159 template <typename T>
findById(std::vector<T> & v,int32_t id)160 auto findById(std::vector<T>& v, int32_t id) {
161     return std::find_if(v.begin(), v.end(), [&](const auto& e) { return e.id == id; });
162 }
163 
getTestConfiguration()164 Configuration getTestConfiguration() {
165     const std::vector<AudioProfile> standardPcmAudioProfiles = {
166             createProfile(PcmType::INT_16_BIT, {AudioChannelLayout::LAYOUT_STEREO}, {48000})};
167     Configuration c;
168 
169     AudioPort micInDevice =
170             createPort(c.nextPortId++, "Built-In Mic", 0, true,
171                        createPortDeviceExt(AudioDeviceType::IN_MICROPHONE,
172                                            1 << AudioPortDeviceExt::FLAG_INDEX_DEFAULT_DEVICE));
173     micInDevice.profiles = standardPcmAudioProfiles;
174     c.ports.push_back(micInDevice);
175 
176     AudioPort micInBackDevice =
177             createPort(c.nextPortId++, "Built-In Back Mic", 0, true,
178                        createPortDeviceExt(AudioDeviceType::IN_MICROPHONE_BACK, 0));
179     micInDevice.profiles = standardPcmAudioProfiles;
180     c.ports.push_back(micInBackDevice);
181 
182     AudioPort primaryInMix =
183             createPort(c.nextPortId++, "primary input", 0, true, createPortMixExt(0, 1));
184     primaryInMix.profiles = standardPcmAudioProfiles;
185     c.ports.push_back(primaryInMix);
186 
187     AudioPort speakerOutDevice = createPort(c.nextPortId++, "Speaker", 0, false,
188                                             createPortDeviceExt(AudioDeviceType::OUT_SPEAKER, 0));
189     speakerOutDevice.profiles = standardPcmAudioProfiles;
190     c.ports.push_back(speakerOutDevice);
191 
192     AudioPort primaryOutMix =
193             createPort(c.nextPortId++, "primary output", 0, false, createPortMixExt(1, 1));
194     primaryOutMix.profiles = standardPcmAudioProfiles;
195     c.ports.push_back(primaryOutMix);
196 
197     AudioPort btOutDevice =
198             createPort(c.nextPortId++, "BT A2DP Out", 0, false,
199                        createPortDeviceExt(AudioDeviceType::OUT_DEVICE, 0,
200                                            AudioDeviceDescription::CONNECTION_BT_A2DP));
201     btOutDevice.profiles = standardPcmAudioProfiles;
202     c.ports.push_back(btOutDevice);
203 
204     AudioPort btOutMix =
205             createPort(c.nextPortId++, "a2dp output", 0, false, createPortMixExt(1, 1));
206     btOutMix.profiles = standardPcmAudioProfiles;
207     c.ports.push_back(btOutMix);
208 
209     c.routes.push_back(createRoute({micInDevice, micInBackDevice}, primaryInMix));
210     c.routes.push_back(createRoute({primaryOutMix}, speakerOutDevice));
211     c.routes.push_back(createRoute({btOutMix}, btOutDevice));
212 
213     return c;
214 }
215 
216 class StreamCommonMock : public ::aidl::android::hardware::audio::core::BnStreamCommon,
217                          public VendorParameterMock {
close()218     ndk::ScopedAStatus close() override { return ndk::ScopedAStatus::ok(); }
prepareToClose()219     ndk::ScopedAStatus prepareToClose() override { return ndk::ScopedAStatus::ok(); }
updateHwAvSyncId(int32_t)220     ndk::ScopedAStatus updateHwAvSyncId(int32_t) override { return ndk::ScopedAStatus::ok(); }
getVendorParameters(const std::vector<std::string> & in_parameterIds,std::vector<VendorParameter> *)221     ndk::ScopedAStatus getVendorParameters(const std::vector<std::string>& in_parameterIds,
222                                            std::vector<VendorParameter>*) override {
223         return VendorParameterMock::getVendorParameters(in_parameterIds);
224     }
setVendorParameters(const std::vector<VendorParameter> & in_parameters,bool async)225     ndk::ScopedAStatus setVendorParameters(const std::vector<VendorParameter>& in_parameters,
226                                            bool async) override {
227         return VendorParameterMock::setVendorParameters(in_parameters, async);
228     }
addEffect(const std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect> &)229     ndk::ScopedAStatus addEffect(
230             const std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect>&) override {
231         return ndk::ScopedAStatus::ok();
232     }
removeEffect(const std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect> &)233     ndk::ScopedAStatus removeEffect(
234             const std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect>&) override {
235         return ndk::ScopedAStatus::ok();
236     }
237 };
238 
239 class StreamContext {
240   public:
241     using Descriptor = ::aidl::android::hardware::audio::core::StreamDescriptor;
242     typedef ::android::AidlMessageQueue<
243             Descriptor::Command, ::aidl::android::hardware::common::fmq::SynchronizedReadWrite>
244             CommandMQ;
245     typedef ::android::AidlMessageQueue<
246             Descriptor::Reply, ::aidl::android::hardware::common::fmq::SynchronizedReadWrite>
247             ReplyMQ;
248     typedef ::android::AidlMessageQueue<
249             int8_t, ::aidl::android::hardware::common::fmq::SynchronizedReadWrite>
250             DataMQ;
251 
252     StreamContext() = default;
StreamContext(std::unique_ptr<CommandMQ> commandMQ,std::unique_ptr<ReplyMQ> replyMQ,std::unique_ptr<DataMQ> dataMQ)253     StreamContext(std::unique_ptr<CommandMQ> commandMQ, std::unique_ptr<ReplyMQ> replyMQ,
254                   std::unique_ptr<DataMQ> dataMQ)
255         : mCommandMQ(std::move(commandMQ)),
256           mReplyMQ(std::move(replyMQ)),
257           mDataMQ(std::move(dataMQ)) {}
fillDescriptor(Descriptor * desc)258     void fillDescriptor(Descriptor* desc) {
259         if (mCommandMQ) {
260             desc->command = mCommandMQ->dupeDesc();
261         }
262         if (mReplyMQ) {
263             desc->reply = mReplyMQ->dupeDesc();
264         }
265         if (mDataMQ) {
266             desc->frameSizeBytes = 2;
267             desc->bufferSizeFrames = 48;
268             desc->audio.set<Descriptor::AudioBuffer::Tag::fmq>(mDataMQ->dupeDesc());
269         }
270     }
271 
272   private:
273     std::unique_ptr<CommandMQ> mCommandMQ =
274             std::make_unique<CommandMQ>(1, true /*configureEventFlagWord*/);
275     std::unique_ptr<ReplyMQ> mReplyMQ =
276             std::make_unique<ReplyMQ>(1, true /*configureEventFlagWord*/);
277     std::unique_ptr<DataMQ> mDataMQ = std::make_unique<DataMQ>(96);
278 };
279 
280 class StreamOutMock : public ::aidl::android::hardware::audio::core::BnStreamOut {
281   public:
StreamOutMock(StreamContext && ctx)282     explicit StreamOutMock(StreamContext&& ctx) : mContext(std::move(ctx)) {}
283 
284   private:
getStreamCommon(std::shared_ptr<::aidl::android::hardware::audio::core::IStreamCommon> * _aidl_return)285     ndk::ScopedAStatus getStreamCommon(
286             std::shared_ptr<::aidl::android::hardware::audio::core::IStreamCommon>* _aidl_return)
287             override {
288         if (!mCommon) {
289             mCommon = ndk::SharedRefBase::make<StreamCommonMock>();
290         }
291         *_aidl_return = mCommon;
292         return ndk::ScopedAStatus::ok();
293     }
updateMetadata(const::aidl::android::hardware::audio::common::SourceMetadata &)294     ndk::ScopedAStatus updateMetadata(
295             const ::aidl::android::hardware::audio::common::SourceMetadata&) override {
296         return ndk::ScopedAStatus::ok();
297     }
updateOffloadMetadata(const::aidl::android::hardware::audio::common::AudioOffloadMetadata &)298     ndk::ScopedAStatus updateOffloadMetadata(
299             const ::aidl::android::hardware::audio::common::AudioOffloadMetadata&) override {
300         return ndk::ScopedAStatus::ok();
301     }
getHwVolume(std::vector<float> *)302     ndk::ScopedAStatus getHwVolume(std::vector<float>*) override {
303         return ndk::ScopedAStatus::ok();
304     }
setHwVolume(const std::vector<float> &)305     ndk::ScopedAStatus setHwVolume(const std::vector<float>&) override {
306         return ndk::ScopedAStatus::ok();
307     }
getAudioDescriptionMixLevel(float *)308     ndk::ScopedAStatus getAudioDescriptionMixLevel(float*) override {
309         return ndk::ScopedAStatus::ok();
310     }
setAudioDescriptionMixLevel(float)311     ndk::ScopedAStatus setAudioDescriptionMixLevel(float) override {
312         return ndk::ScopedAStatus::ok();
313     }
getDualMonoMode(::aidl::android::media::audio::common::AudioDualMonoMode *)314     ndk::ScopedAStatus getDualMonoMode(
315             ::aidl::android::media::audio::common::AudioDualMonoMode*) override {
316         return ndk::ScopedAStatus::ok();
317     }
setDualMonoMode(::aidl::android::media::audio::common::AudioDualMonoMode)318     ndk::ScopedAStatus setDualMonoMode(
319             ::aidl::android::media::audio::common::AudioDualMonoMode) override {
320         return ndk::ScopedAStatus::ok();
321     }
getRecommendedLatencyModes(std::vector<::aidl::android::media::audio::common::AudioLatencyMode> *)322     ndk::ScopedAStatus getRecommendedLatencyModes(
323             std::vector<::aidl::android::media::audio::common::AudioLatencyMode>*) override {
324         return ndk::ScopedAStatus::ok();
325     }
setLatencyMode(::aidl::android::media::audio::common::AudioLatencyMode)326     ndk::ScopedAStatus setLatencyMode(
327             ::aidl::android::media::audio::common::AudioLatencyMode) override {
328         return ndk::ScopedAStatus::ok();
329     }
getPlaybackRateParameters(::aidl::android::media::audio::common::AudioPlaybackRate *)330     ndk::ScopedAStatus getPlaybackRateParameters(
331             ::aidl::android::media::audio::common::AudioPlaybackRate*) override {
332         return ndk::ScopedAStatus::ok();
333     }
setPlaybackRateParameters(const::aidl::android::media::audio::common::AudioPlaybackRate &)334     ndk::ScopedAStatus setPlaybackRateParameters(
335             const ::aidl::android::media::audio::common::AudioPlaybackRate&) override {
336         return ndk::ScopedAStatus::ok();
337     }
selectPresentation(int32_t,int32_t)338     ndk::ScopedAStatus selectPresentation(int32_t, int32_t) override {
339         return ndk::ScopedAStatus::ok();
340     }
341     StreamContext mContext;
342     std::shared_ptr<StreamCommonMock> mCommon;
343 };
344 
345 class ModuleMock : public ::aidl::android::hardware::audio::core::BnModule,
346                    public VendorParameterMock {
347   public:
348     ModuleMock() = default;
ModuleMock(const Configuration & config)349     explicit ModuleMock(const Configuration& config) : mConfig(config) {}
isScreenTurnedOn() const350     bool isScreenTurnedOn() const { return mIsScreenTurnedOn; }
getScreenRotation() const351     ScreenRotation getScreenRotation() const { return mScreenRotation; }
getPatches()352     std::vector<AudioPatch> getPatches() {
353         std::vector<AudioPatch> result;
354         getAudioPatches(&result);
355         return result;
356     }
getPortConfig(int32_t id)357     std::optional<AudioPortConfig> getPortConfig(int32_t id) {
358         auto iter = findById<AudioPortConfig>(mConfig.portConfigs, id);
359         if (iter != mConfig.portConfigs.end()) {
360             return *iter;
361         }
362         return std::nullopt;
363     }
364 
365   private:
setModuleDebug(const::aidl::android::hardware::audio::core::ModuleDebug &)366     ndk::ScopedAStatus setModuleDebug(
367             const ::aidl::android::hardware::audio::core::ModuleDebug&) override {
368         return ndk::ScopedAStatus::ok();
369     }
getTelephony(std::shared_ptr<::aidl::android::hardware::audio::core::ITelephony> *)370     ndk::ScopedAStatus getTelephony(
371             std::shared_ptr<::aidl::android::hardware::audio::core::ITelephony>*) override {
372         return ndk::ScopedAStatus::ok();
373     }
getBluetooth(std::shared_ptr<::aidl::android::hardware::audio::core::IBluetooth> *)374     ndk::ScopedAStatus getBluetooth(
375             std::shared_ptr<::aidl::android::hardware::audio::core::IBluetooth>*) override {
376         return ndk::ScopedAStatus::ok();
377     }
getBluetoothA2dp(std::shared_ptr<::aidl::android::hardware::audio::core::IBluetoothA2dp> *)378     ndk::ScopedAStatus getBluetoothA2dp(
379             std::shared_ptr<::aidl::android::hardware::audio::core::IBluetoothA2dp>*) override {
380         return ndk::ScopedAStatus::ok();
381     }
getBluetoothLe(std::shared_ptr<::aidl::android::hardware::audio::core::IBluetoothLe> *)382     ndk::ScopedAStatus getBluetoothLe(
383             std::shared_ptr<::aidl::android::hardware::audio::core::IBluetoothLe>*) override {
384         return ndk::ScopedAStatus::ok();
385     }
connectExternalDevice(const::aidl::android::media::audio::common::AudioPort & portIdAndData,::aidl::android::media::audio::common::AudioPort * port)386     ndk::ScopedAStatus connectExternalDevice(
387             const ::aidl::android::media::audio::common::AudioPort& portIdAndData,
388             ::aidl::android::media::audio::common::AudioPort* port) override {
389         auto src = portIdAndData;  // Make a copy to mimic RPC behavior.
390         auto iter = findById<AudioPort>(mConfig.ports, src.id);
391         if (iter == mConfig.ports.end()) {
392             return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
393         }
394         *port = *iter;
395         port->ext = src.ext;
396         port->id = mConfig.nextPortId++;
397         ALOGD("%s: returning %s", __func__, port->toString().c_str());
398         mConfig.ports.push_back(*port);
399         std::vector<AudioRoute> newRoutes;
400         for (auto& r : mConfig.routes) {
401             if (r.sinkPortId == src.id) {
402                 newRoutes.push_back(AudioRoute{.sourcePortIds = r.sourcePortIds,
403                                                .sinkPortId = port->id,
404                                                .isExclusive = r.isExclusive});
405             } else if (std::find(r.sourcePortIds.begin(), r.sourcePortIds.end(), src.id) !=
406                        r.sourcePortIds.end()) {
407                 r.sourcePortIds.push_back(port->id);
408             }
409         }
410         mConfig.routes.insert(mConfig.routes.end(), newRoutes.begin(), newRoutes.end());
411         return ndk::ScopedAStatus::ok();
412     }
disconnectExternalDevice(int32_t portId)413     ndk::ScopedAStatus disconnectExternalDevice(int32_t portId) override {
414         auto iter = findById<AudioPort>(mConfig.ports, portId);
415         if (iter == mConfig.ports.end()) {
416             return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
417         }
418         mConfig.ports.erase(iter);
419         for (auto it = mConfig.routes.begin(); it != mConfig.routes.end();) {
420             if (it->sinkPortId == portId) {
421                 it = mConfig.routes.erase(it);
422             } else {
423                 if (auto srcIt =
424                             std::find(it->sourcePortIds.begin(), it->sourcePortIds.end(), portId);
425                     srcIt != it->sourcePortIds.end()) {
426                     it->sourcePortIds.erase(srcIt);
427                 }
428                 ++it;
429             }
430         }
431         return ndk::ScopedAStatus::ok();
432     }
getAudioPatches(std::vector<::aidl::android::hardware::audio::core::AudioPatch> * patches)433     ndk::ScopedAStatus getAudioPatches(
434             std::vector<::aidl::android::hardware::audio::core::AudioPatch>* patches) override {
435         *patches = mConfig.patches;
436         return ndk::ScopedAStatus::ok();
437     }
getAudioPort(int32_t portId,::aidl::android::media::audio::common::AudioPort * port)438     ndk::ScopedAStatus getAudioPort(
439             int32_t portId, ::aidl::android::media::audio::common::AudioPort* port) override {
440         auto iter = findById<AudioPort>(mConfig.ports, portId);
441         if (iter == mConfig.ports.end()) {
442             return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
443         }
444         *port = *iter;
445         return ndk::ScopedAStatus::ok();
446     }
getAudioPortConfigs(std::vector<::aidl::android::media::audio::common::AudioPortConfig> * configs)447     ndk::ScopedAStatus getAudioPortConfigs(
448             std::vector<::aidl::android::media::audio::common::AudioPortConfig>* configs) override {
449         *configs = mConfig.portConfigs;
450         return ndk::ScopedAStatus::ok();
451     }
getAudioPorts(std::vector<::aidl::android::media::audio::common::AudioPort> * ports)452     ndk::ScopedAStatus getAudioPorts(
453             std::vector<::aidl::android::media::audio::common::AudioPort>* ports) override {
454         *ports = mConfig.ports;
455         return ndk::ScopedAStatus::ok();
456     }
getAudioRoutes(std::vector<::aidl::android::hardware::audio::core::AudioRoute> * routes)457     ndk::ScopedAStatus getAudioRoutes(
458             std::vector<::aidl::android::hardware::audio::core::AudioRoute>* routes) override {
459         *routes = mConfig.routes;
460         return ndk::ScopedAStatus::ok();
461     }
getAudioRoutesForAudioPort(int32_t portId,std::vector<::aidl::android::hardware::audio::core::AudioRoute> * routes)462     ndk::ScopedAStatus getAudioRoutesForAudioPort(
463             int32_t portId,
464             std::vector<::aidl::android::hardware::audio::core::AudioRoute>* routes) override {
465         for (auto& r : mConfig.routes) {
466             const auto& srcs = r.sourcePortIds;
467             if (r.sinkPortId == portId ||
468                 std::find(srcs.begin(), srcs.end(), portId) != srcs.end()) {
469                 routes->push_back(r);
470             }
471         }
472         return ndk::ScopedAStatus::ok();
473     }
openInputStream(const OpenInputStreamArguments &,OpenInputStreamReturn *)474     ndk::ScopedAStatus openInputStream(const OpenInputStreamArguments&,
475                                        OpenInputStreamReturn*) override {
476         return ndk::ScopedAStatus::ok();
477     }
openOutputStream(const OpenOutputStreamArguments &,OpenOutputStreamReturn * _aidl_return)478     ndk::ScopedAStatus openOutputStream(const OpenOutputStreamArguments&,
479                                         OpenOutputStreamReturn* _aidl_return) override {
480         StreamContext context;
481         context.fillDescriptor(&_aidl_return->desc);
482         _aidl_return->stream = ndk::SharedRefBase::make<StreamOutMock>(std::move(context));
483         return ndk::ScopedAStatus::ok();
484     }
getSupportedPlaybackRateFactors(SupportedPlaybackRateFactors *)485     ndk::ScopedAStatus getSupportedPlaybackRateFactors(SupportedPlaybackRateFactors*) override {
486         return ndk::ScopedAStatus::ok();
487     }
setAudioPatch(const::aidl::android::hardware::audio::core::AudioPatch & requested,::aidl::android::hardware::audio::core::AudioPatch * patch)488     ndk::ScopedAStatus setAudioPatch(
489             const ::aidl::android::hardware::audio::core::AudioPatch& requested,
490             ::aidl::android::hardware::audio::core::AudioPatch* patch) override {
491         if (requested.id == 0) {
492             *patch = requested;
493             patch->id = mConfig.nextPatchId++;
494             patch->latenciesMs.push_back(100);
495             mConfig.patches.push_back(*patch);
496             ALOGD("%s: returning %s", __func__, patch->toString().c_str());
497         } else {
498             auto iter = findById<AudioPatch>(mConfig.patches, requested.id);
499             if (iter == mConfig.patches.end()) {
500                 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
501             }
502             *iter = *patch = requested;
503             ALOGD("%s: updated %s", __func__, patch->toString().c_str());
504         }
505         return ndk::ScopedAStatus::ok();
506     }
setAudioPortConfig(const::aidl::android::media::audio::common::AudioPortConfig & requested,::aidl::android::media::audio::common::AudioPortConfig * config,bool * applied)507     ndk::ScopedAStatus setAudioPortConfig(
508             const ::aidl::android::media::audio::common::AudioPortConfig& requested,
509             ::aidl::android::media::audio::common::AudioPortConfig* config,
510             bool* applied) override {
511         *applied = false;
512         auto src = requested;  // Make a copy to mimic RPC behavior.
513         if (src.id == 0) {
514             *config = src;
515             if (config->ext.getTag() == AudioPortExt::unspecified) {
516                 auto iter = findById<AudioPort>(mConfig.ports, src.portId);
517                 if (iter == mConfig.ports.end()) {
518                     return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
519                 }
520                 config->ext = iter->ext;
521             }
522             config->id = mConfig.nextPortId++;
523             mConfig.portConfigs.push_back(*config);
524             ALOGD("%s: returning %s", __func__, config->toString().c_str());
525         } else {
526             auto iter = findById<AudioPortConfig>(mConfig.portConfigs, src.id);
527             if (iter == mConfig.portConfigs.end()) {
528                 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
529             }
530             *iter = *config = src;
531             ALOGD("%s: updated %s", __func__, config->toString().c_str());
532         }
533         *applied = true;
534         return ndk::ScopedAStatus::ok();
535     }
resetAudioPatch(int32_t patchId)536     ndk::ScopedAStatus resetAudioPatch(int32_t patchId) override {
537         auto iter = findById<AudioPatch>(mConfig.patches, patchId);
538         if (iter == mConfig.patches.end()) {
539             return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
540         }
541         mConfig.patches.erase(iter);
542         return ndk::ScopedAStatus::ok();
543     }
resetAudioPortConfig(int32_t portConfigId)544     ndk::ScopedAStatus resetAudioPortConfig(int32_t portConfigId) override {
545         auto iter = findById<AudioPortConfig>(mConfig.portConfigs, portConfigId);
546         if (iter == mConfig.portConfigs.end()) {
547             return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
548         }
549         mConfig.portConfigs.erase(iter);
550         return ndk::ScopedAStatus::ok();
551     }
getMasterMute(bool *)552     ndk::ScopedAStatus getMasterMute(bool*) override { return ndk::ScopedAStatus::ok(); }
setMasterMute(bool)553     ndk::ScopedAStatus setMasterMute(bool) override { return ndk::ScopedAStatus::ok(); }
getMasterVolume(float *)554     ndk::ScopedAStatus getMasterVolume(float*) override { return ndk::ScopedAStatus::ok(); }
setMasterVolume(float)555     ndk::ScopedAStatus setMasterVolume(float) override { return ndk::ScopedAStatus::ok(); }
getMicMute(bool *)556     ndk::ScopedAStatus getMicMute(bool*) override { return ndk::ScopedAStatus::ok(); }
setMicMute(bool)557     ndk::ScopedAStatus setMicMute(bool) override { return ndk::ScopedAStatus::ok(); }
getMicrophones(std::vector<::aidl::android::media::audio::common::MicrophoneInfo> *)558     ndk::ScopedAStatus getMicrophones(
559             std::vector<::aidl::android::media::audio::common::MicrophoneInfo>*) override {
560         return ndk::ScopedAStatus::ok();
561     }
updateAudioMode(::aidl::android::media::audio::common::AudioMode)562     ndk::ScopedAStatus updateAudioMode(::aidl::android::media::audio::common::AudioMode) override {
563         return ndk::ScopedAStatus::ok();
564     }
updateScreenRotation(ScreenRotation in_rotation)565     ndk::ScopedAStatus updateScreenRotation(ScreenRotation in_rotation) override {
566         mScreenRotation = in_rotation;
567         return ndk::ScopedAStatus::ok();
568     }
updateScreenState(bool in_isTurnedOn)569     ndk::ScopedAStatus updateScreenState(bool in_isTurnedOn) override {
570         mIsScreenTurnedOn = in_isTurnedOn;
571         return ndk::ScopedAStatus::ok();
572     }
getSoundDose(std::shared_ptr<::aidl::android::hardware::audio::core::sounddose::ISoundDose> *)573     ndk::ScopedAStatus getSoundDose(
574             std::shared_ptr<::aidl::android::hardware::audio::core::sounddose::ISoundDose>*)
575             override {
576         return ndk::ScopedAStatus::ok();
577     }
generateHwAvSyncId(int32_t *)578     ndk::ScopedAStatus generateHwAvSyncId(int32_t*) override { return ndk::ScopedAStatus::ok(); }
getVendorParameters(const std::vector<std::string> & in_parameterIds,std::vector<VendorParameter> *)579     ndk::ScopedAStatus getVendorParameters(const std::vector<std::string>& in_parameterIds,
580                                            std::vector<VendorParameter>*) override {
581         return VendorParameterMock::getVendorParameters(in_parameterIds);
582     }
setVendorParameters(const std::vector<VendorParameter> & in_parameters,bool async)583     ndk::ScopedAStatus setVendorParameters(const std::vector<VendorParameter>& in_parameters,
584                                            bool async) override {
585         return VendorParameterMock::setVendorParameters(in_parameters, async);
586     }
addDeviceEffect(int32_t,const std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect> &)587     ndk::ScopedAStatus addDeviceEffect(
588             int32_t,
589             const std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect>&) override {
590         return ndk::ScopedAStatus::ok();
591     }
removeDeviceEffect(int32_t,const std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect> &)592     ndk::ScopedAStatus removeDeviceEffect(
593             int32_t,
594             const std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect>&) override {
595         return ndk::ScopedAStatus::ok();
596     }
getMmapPolicyInfos(::aidl::android::media::audio::common::AudioMMapPolicyType,std::vector<::aidl::android::media::audio::common::AudioMMapPolicyInfo> *)597     ndk::ScopedAStatus getMmapPolicyInfos(
598             ::aidl::android::media::audio::common::AudioMMapPolicyType,
599             std::vector<::aidl::android::media::audio::common::AudioMMapPolicyInfo>*) override {
600         return ndk::ScopedAStatus::ok();
601     }
supportsVariableLatency(bool *)602     ndk::ScopedAStatus supportsVariableLatency(bool*) override { return ndk::ScopedAStatus::ok(); }
getAAudioMixerBurstCount(int32_t *)603     ndk::ScopedAStatus getAAudioMixerBurstCount(int32_t*) override {
604         return ndk::ScopedAStatus::ok();
605     }
getAAudioHardwareBurstMinUsec(int32_t *)606     ndk::ScopedAStatus getAAudioHardwareBurstMinUsec(int32_t*) override {
607         return ndk::ScopedAStatus::ok();
608     }
prepareToDisconnectExternalDevice(int32_t)609     ndk::ScopedAStatus prepareToDisconnectExternalDevice(int32_t) override {
610         return ndk::ScopedAStatus::ok();
611     }
612 
613     Configuration mConfig;
614     bool mIsScreenTurnedOn = false;
615     ScreenRotation mScreenRotation = ScreenRotation::DEG_0;
616 };
617 
makeVendorParameter(const std::string & id,int value)618 VendorParameter makeVendorParameter(const std::string& id, int value) {
619     VendorParameter result{.id = id};
620     // Note: in real life, a parcelable type defined by vendor must be used,
621     // here we use Int just for test purposes.
622     ::aidl::android::media::audio::common::Int vendorValue{.value = value};
623     result.ext.setParcelable(std::move(vendorValue));
624     return result;
625 }
626 
parseVendorParameter(const VendorParameter & param,int * value)627 android::status_t parseVendorParameter(const VendorParameter& param, int* value) {
628     std::optional<::aidl::android::media::audio::common::Int> vendorValue;
629     RETURN_STATUS_IF_ERROR(param.ext.getParcelable(&vendorValue));
630     if (!vendorValue.has_value()) return android::BAD_VALUE;
631     *value = vendorValue.value().value;
632     return android::OK;
633 }
634 
635 class TestHalAdapterVendorExtension
636     : public ::aidl::android::media::audio::BnHalAdapterVendorExtension {
637   public:
638     static const std::string kLegacyParameterKey;
639     static const std::string kLegacyAsyncParameterKey;
640     static const std::string kModuleVendorParameterId;
641     static const std::string kStreamVendorParameterId;
642 
643   private:
parseVendorParameterIds(ParameterScope in_scope,const std::string & in_rawKeys,std::vector<std::string> * _aidl_return)644     ndk::ScopedAStatus parseVendorParameterIds(ParameterScope in_scope,
645                                                const std::string& in_rawKeys,
646                                                std::vector<std::string>* _aidl_return) override {
647         android::AudioParameter keys(android::String8(in_rawKeys.c_str()));
648         for (size_t i = 0; i < keys.size(); ++i) {
649             android::String8 key;
650             if (android::status_t status = keys.getAt(i, key); status != android::OK) {
651                 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
652             }
653             switch (in_scope) {
654                 case ParameterScope::MODULE:
655                     if (key == android::String8(kLegacyParameterKey.c_str()) ||
656                         key == android::String8(kLegacyAsyncParameterKey.c_str())) {
657                         _aidl_return->push_back(kModuleVendorParameterId);
658                     } else {
659                         return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
660                     }
661                     break;
662                 case ParameterScope::STREAM:
663                     if (key == android::String8(kLegacyParameterKey.c_str()) ||
664                         key == android::String8(kLegacyAsyncParameterKey.c_str())) {
665                         _aidl_return->push_back(kStreamVendorParameterId);
666                     } else {
667                         return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
668                     }
669                     break;
670             }
671         }
672         return ndk::ScopedAStatus::ok();
673     }
parseVendorParameters(ParameterScope in_scope,const std::string & in_rawKeysAndValues,std::vector<VendorParameter> * out_syncParameters,std::vector<VendorParameter> * out_asyncParameters)674     ndk::ScopedAStatus parseVendorParameters(
675             ParameterScope in_scope, const std::string& in_rawKeysAndValues,
676             std::vector<VendorParameter>* out_syncParameters,
677             std::vector<VendorParameter>* out_asyncParameters) override {
678         android::AudioParameter legacy(android::String8(in_rawKeysAndValues.c_str()));
679         for (size_t i = 0; i < legacy.size(); ++i) {
680             android::String8 key;
681             if (android::status_t status = legacy.getAt(i, key); status != android::OK) {
682                 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
683             }
684             int value;
685             if (android::status_t status = legacy.getInt(key, value); status != android::OK) {
686                 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
687             }
688             std::string parameterId;
689             switch (in_scope) {
690                 case ParameterScope::MODULE:
691                     parameterId = kModuleVendorParameterId;
692                     break;
693                 case ParameterScope::STREAM:
694                     parameterId = kStreamVendorParameterId;
695                     break;
696             }
697             if (key == android::String8(kLegacyParameterKey.c_str())) {
698                 out_syncParameters->push_back(makeVendorParameter(parameterId, value));
699             } else if (key == android::String8(kLegacyAsyncParameterKey.c_str())) {
700                 out_asyncParameters->push_back(makeVendorParameter(parameterId, value));
701             } else {
702                 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
703             }
704         }
705         return ndk::ScopedAStatus::ok();
706     }
parseBluetoothA2dpReconfigureOffload(const std::string &,std::vector<VendorParameter> *)707     ndk::ScopedAStatus parseBluetoothA2dpReconfigureOffload(
708             const std::string&, std::vector<VendorParameter>*) override {
709         return ndk::ScopedAStatus::ok();
710     }
parseBluetoothLeReconfigureOffload(const std::string &,std::vector<VendorParameter> *)711     ndk::ScopedAStatus parseBluetoothLeReconfigureOffload(const std::string&,
712                                                           std::vector<VendorParameter>*) override {
713         return ndk::ScopedAStatus::ok();
714     }
processVendorParameters(ParameterScope in_scope,const std::vector<VendorParameter> & in_parameters,std::string * _aidl_return)715     ndk::ScopedAStatus processVendorParameters(ParameterScope in_scope,
716                                                const std::vector<VendorParameter>& in_parameters,
717                                                std::string* _aidl_return) override {
718         android::AudioParameter legacy;
719         for (const auto& vendorParam : in_parameters) {
720             if ((in_scope == ParameterScope::MODULE &&
721                  vendorParam.id == kModuleVendorParameterId) ||
722                 (in_scope == ParameterScope::STREAM &&
723                  vendorParam.id == kStreamVendorParameterId)) {
724                 int value;
725                 if (android::status_t status = parseVendorParameter(vendorParam, &value);
726                     status != android::OK) {
727                     return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
728                 }
729                 legacy.addInt(android::String8(kLegacyParameterKey.c_str()), value);
730             }
731         }
732         *_aidl_return = legacy.toString().c_str();
733         return ndk::ScopedAStatus::ok();
734     }
735 };
736 
737 const std::string TestHalAdapterVendorExtension::kLegacyParameterKey = "aosp_test_param";
738 const std::string TestHalAdapterVendorExtension::kLegacyAsyncParameterKey = "aosp_test_param_async";
739 // Note: in real life, there is no need to explicitly separate "module" and "stream"
740 // parameters, here it's done just for test purposes.
741 const std::string TestHalAdapterVendorExtension::kModuleVendorParameterId =
742         "aosp.test.module.parameter";
743 const std::string TestHalAdapterVendorExtension::kStreamVendorParameterId =
744         "aosp.test.stream.parameter";
745 
createParameterString(const std::string & key,const std::string & value)746 android::String8 createParameterString(const std::string& key, const std::string& value) {
747     android::AudioParameter params;
748     params.add(android::String8(key.c_str()), android::String8(value.c_str()));
749     return params.toString();
750 }
751 
createParameterString(const std::string & key,int value)752 android::String8 createParameterString(const std::string& key, int value) {
753     android::AudioParameter params;
754     params.addInt(android::String8(key.c_str()), value);
755     return params.toString();
756 }
757 
758 template <typename>
759 struct mf_traits {};
760 template <class T, class U>
761 struct mf_traits<U T::*> {
762     using member_type = U;
763 };
764 
765 }  // namespace
766 
767 // Provide value printers for types generated from AIDL
768 // They need to be in the same namespace as the types we intend to print
769 namespace aidl::android::hardware::audio::core {
770 template <typename P>
771 std::enable_if_t<std::is_function_v<typename mf_traits<decltype(&P::toString)>::member_type>,
772                  std::ostream&>
operator <<(std::ostream & os,const P & p)773 operator<<(std::ostream& os, const P& p) {
774     return os << p.toString();
775 }
776 template <typename E>
operator <<(std::ostream & os,const E & e)777 std::enable_if_t<std::is_enum_v<E>, std::ostream&> operator<<(std::ostream& os, const E& e) {
778     return os << toString(e);
779 }
780 }  // namespace aidl::android::hardware::audio::core
781 
782 namespace aidl::android::media::audio::common {
783 template <typename P>
784 std::enable_if_t<std::is_function_v<typename mf_traits<decltype(&P::toString)>::member_type>,
785                  std::ostream&>
operator <<(std::ostream & os,const P & p)786 operator<<(std::ostream& os, const P& p) {
787     return os << p.toString();
788 }
789 template <typename E>
operator <<(std::ostream & os,const E & e)790 std::enable_if_t<std::is_enum_v<E>, std::ostream&> operator<<(std::ostream& os, const E& e) {
791     return os << toString(e);
792 }
793 }  // namespace aidl::android::media::audio::common
794 
795 using namespace android;
796 
797 namespace {
798 
799 class StreamHalMock : public virtual StreamHalInterface {
800   public:
801     StreamHalMock() = default;
802     ~StreamHalMock() override = default;
getBufferSize(size_t *)803     status_t getBufferSize(size_t*) override { return OK; }
getAudioProperties(audio_config_base_t *)804     status_t getAudioProperties(audio_config_base_t*) override { return OK; }
setParameters(const String8 &)805     status_t setParameters(const String8&) override { return OK; }
getParameters(const String8 &,String8 *)806     status_t getParameters(const String8&, String8*) override { return OK; }
getFrameSize(size_t *)807     status_t getFrameSize(size_t*) override { return OK; }
addEffect(sp<EffectHalInterface>)808     status_t addEffect(sp<EffectHalInterface>) override { return OK; }
removeEffect(sp<EffectHalInterface>)809     status_t removeEffect(sp<EffectHalInterface>) override { return OK; }
standby()810     status_t standby() override { return OK; }
dump(int,const Vector<String16> &)811     status_t dump(int, const Vector<String16>&) override { return OK; }
start()812     status_t start() override { return OK; }
stop()813     status_t stop() override { return OK; }
createMmapBuffer(int32_t,struct audio_mmap_buffer_info *)814     status_t createMmapBuffer(int32_t, struct audio_mmap_buffer_info*) override { return OK; }
getMmapPosition(struct audio_mmap_position *)815     status_t getMmapPosition(struct audio_mmap_position*) override { return OK; }
setHalThreadPriority(int)816     status_t setHalThreadPriority(int) override { return OK; }
legacyCreateAudioPatch(const struct audio_port_config &,std::optional<audio_source_t>,audio_devices_t)817     status_t legacyCreateAudioPatch(const struct audio_port_config&, std::optional<audio_source_t>,
818                                     audio_devices_t) override {
819         return OK;
820     }
legacyReleaseAudioPatch()821     status_t legacyReleaseAudioPatch() override { return OK; }
822 };
823 
824 }  // namespace
825 
826 class DeviceHalAidlTest : public testing::Test {
827   public:
SetUp()828     void SetUp() override {
829         mModule = ndk::SharedRefBase::make<ModuleMock>(getTestConfiguration());
830         mDevice = sp<DeviceHalAidl>::make("test", mModule, nullptr /*vext*/);
831     }
TearDown()832     void TearDown() override {
833         mDevice.clear();
834         mModule.reset();
835     }
836 
837   protected:
838     std::shared_ptr<ModuleMock> mModule;
839     sp<DeviceHalAidl> mDevice;
840 };
841 
TEST_F(DeviceHalAidlTest,ScreenState)842 TEST_F(DeviceHalAidlTest, ScreenState) {
843     EXPECT_FALSE(mModule->isScreenTurnedOn());
844     EXPECT_EQ(OK, mDevice->setParameters(createParameterString(AudioParameter::keyScreenState,
845                                                                AudioParameter::valueOn)));
846     EXPECT_TRUE(mModule->isScreenTurnedOn());
847     EXPECT_EQ(OK, mDevice->setParameters(createParameterString(AudioParameter::keyScreenState,
848                                                                AudioParameter::valueOff)));
849     EXPECT_FALSE(mModule->isScreenTurnedOn());
850     // The adaptation layer only logs a warning.
851     EXPECT_EQ(OK, mDevice->setParameters(
852                           createParameterString(AudioParameter::keyScreenState, "blah")));
853     EXPECT_FALSE(mModule->isScreenTurnedOn());
854 }
855 
TEST_F(DeviceHalAidlTest,ScreenRotation)856 TEST_F(DeviceHalAidlTest, ScreenRotation) {
857     using ScreenRotation = ::aidl::android::hardware::audio::core::IModule::ScreenRotation;
858     EXPECT_EQ(ScreenRotation::DEG_0, mModule->getScreenRotation());
859     EXPECT_EQ(OK,
860               mDevice->setParameters(createParameterString(AudioParameter::keyScreenRotation, 90)));
861     EXPECT_EQ(ScreenRotation::DEG_90, mModule->getScreenRotation());
862     EXPECT_EQ(OK,
863               mDevice->setParameters(createParameterString(AudioParameter::keyScreenRotation, 0)));
864     EXPECT_EQ(ScreenRotation::DEG_0, mModule->getScreenRotation());
865     // The adaptation layer only logs a warning.
866     EXPECT_EQ(OK,
867               mDevice->setParameters(createParameterString(AudioParameter::keyScreenRotation, 42)));
868     EXPECT_EQ(ScreenRotation::DEG_0, mModule->getScreenRotation());
869 }
870 
871 // See http://b/357487484#comment6
TEST_F(DeviceHalAidlTest,StreamReleaseOnMapperCleanup)872 TEST_F(DeviceHalAidlTest, StreamReleaseOnMapperCleanup) {
873     ASSERT_EQ(OK, mDevice->initCheck());
874     // Since the test is in effect probabilistic, try multiple times.
875     for (int i = 0; i < 100; ++i) {
876         sp<StreamOutHalInterface> stream1;
877         struct audio_config config = AUDIO_CONFIG_INITIALIZER;
878         config.sample_rate = 48000;
879         config.channel_mask = AUDIO_CHANNEL_OUT_STEREO;
880         config.format = AUDIO_FORMAT_PCM_16_BIT;
881         ASSERT_EQ(OK, mDevice->openOutputStream(42 /*handle*/, AUDIO_DEVICE_OUT_SPEAKER,
882                                                 AUDIO_OUTPUT_FLAG_NONE, &config, "" /*address*/,
883                                                 &stream1));
884         ASSERT_EQ(1, stream1->getStrongCount());
885         std::atomic<bool> stopReleaser = false;
886         // Try to catch the moment when Hal2AidlMapper promotes its wp<StreamHalInterface> to sp<>
887         // in Hal2AidlMapper::resetUnusedPatchesAndPortConfigs and release on our side in order to
888         // make Hal2AidlMapper the sole owner via a temporary sp and enforce destruction of the
889         // stream while the DeviceHalAidl::mLock is held.
890         std::thread releaser([&stream1, &stopReleaser]() {
891             while (!stopReleaser) {
892                 if (stream1->getStrongCount() > 1) {
893                     stream1.clear();
894                     break;
895                 }
896                 std::this_thread::yield();
897             }
898         });
899         sp<StreamOutHalInterface> stream2;
900         // Opening another stream triggers a call to
901         // Hal2AidlMapper::resetUnusedPatchesAndPortConfigs.  It must not cause a deadlock of the
902         // test (main) thread.
903         ASSERT_EQ(OK, mDevice->openOutputStream(43 /*handle*/, AUDIO_DEVICE_OUT_SPEAKER,
904                                                 AUDIO_OUTPUT_FLAG_NONE, &config, "" /*address*/,
905                                                 &stream2));
906         stopReleaser = true;
907         releaser.join();
908     }
909 }
910 
911 class DeviceHalAidlVendorParametersTest : public testing::Test {
912   public:
SetUp()913     void SetUp() override {
914         mModule = ndk::SharedRefBase::make<ModuleMock>();
915         mVendorExt = ndk::SharedRefBase::make<TestHalAdapterVendorExtension>();
916         mDevice = sp<DeviceHalAidl>::make("test", mModule, mVendorExt);
917     }
TearDown()918     void TearDown() override {
919         mDevice.clear();
920         mVendorExt.reset();
921         mModule.reset();
922     }
923 
924   protected:
925     std::shared_ptr<ModuleMock> mModule;
926     std::shared_ptr<TestHalAdapterVendorExtension> mVendorExt;
927     sp<DeviceHalAidl> mDevice;
928 };
929 
TEST_F(DeviceHalAidlVendorParametersTest,GetVendorParameter)930 TEST_F(DeviceHalAidlVendorParametersTest, GetVendorParameter) {
931     EXPECT_EQ(0UL, mModule->getRetrievedParameterIds().size());
932     String8 values;
933     EXPECT_EQ(OK, mDevice->getParameters(
934                           String8(TestHalAdapterVendorExtension::kLegacyParameterKey.c_str()),
935                           &values));
936     EXPECT_EQ(1UL, mModule->getRetrievedParameterIds().size());
937     if (mModule->getRetrievedParameterIds().size() >= 1) {
938         EXPECT_EQ(TestHalAdapterVendorExtension::kModuleVendorParameterId,
939                   mModule->getRetrievedParameterIds()[0]);
940     }
941 }
942 
TEST_F(DeviceHalAidlVendorParametersTest,SetVendorParameter)943 TEST_F(DeviceHalAidlVendorParametersTest, SetVendorParameter) {
944     EXPECT_EQ(0UL, mModule->getAsyncParameters().size());
945     EXPECT_EQ(0UL, mModule->getSyncParameters().size());
946     EXPECT_EQ(OK, mDevice->setParameters(createParameterString(
947                           TestHalAdapterVendorExtension::kLegacyParameterKey, 42)));
948     EXPECT_EQ(0UL, mModule->getAsyncParameters().size());
949     EXPECT_EQ(1UL, mModule->getSyncParameters().size());
950     EXPECT_EQ(OK, mDevice->setParameters(createParameterString(
951                           TestHalAdapterVendorExtension::kLegacyAsyncParameterKey, 43)));
952     EXPECT_EQ(1UL, mModule->getAsyncParameters().size());
953     EXPECT_EQ(1UL, mModule->getSyncParameters().size());
954     if (mModule->getSyncParameters().size() >= 1) {
955         EXPECT_EQ(TestHalAdapterVendorExtension::kModuleVendorParameterId,
956                   mModule->getSyncParameters()[0].id);
957         int value{};
958         EXPECT_EQ(android::OK, parseVendorParameter(mModule->getSyncParameters()[0], &value));
959         EXPECT_EQ(42, value);
960     }
961     if (mModule->getAsyncParameters().size() >= 1) {
962         EXPECT_EQ(TestHalAdapterVendorExtension::kModuleVendorParameterId,
963                   mModule->getAsyncParameters()[0].id);
964         int value{};
965         EXPECT_EQ(android::OK, parseVendorParameter(mModule->getAsyncParameters()[0], &value));
966         EXPECT_EQ(43, value);
967     }
968 }
969 
TEST_F(DeviceHalAidlVendorParametersTest,SetInvalidVendorParameters)970 TEST_F(DeviceHalAidlVendorParametersTest, SetInvalidVendorParameters) {
971     android::AudioParameter legacy;
972     legacy.addInt(android::String8(TestHalAdapterVendorExtension::kLegacyParameterKey.c_str()), 42);
973     legacy.addInt(android::String8(TestHalAdapterVendorExtension::kLegacyAsyncParameterKey.c_str()),
974                   43);
975     legacy.addInt(android::String8("random_name"), 44);
976     EXPECT_EQ(0UL, mModule->getAsyncParameters().size());
977     EXPECT_EQ(0UL, mModule->getSyncParameters().size());
978     // TestHalAdapterVendorExtension throws an error for unknown parameters.
979     EXPECT_EQ(android::BAD_VALUE, mDevice->setParameters(legacy.toString()));
980     EXPECT_EQ(0UL, mModule->getAsyncParameters().size());
981     EXPECT_EQ(0UL, mModule->getSyncParameters().size());
982 }
983 
984 class StreamHalAidlVendorParametersTest : public testing::Test {
985   public:
SetUp()986     void SetUp() override {
987         mStreamCommon = ndk::SharedRefBase::make<StreamCommonMock>();
988         mVendorExt = ndk::SharedRefBase::make<TestHalAdapterVendorExtension>();
989         struct audio_config config = AUDIO_CONFIG_INITIALIZER;
990         ::aidl::android::hardware::audio::core::StreamDescriptor descriptor;
991         StreamContextAidl context(descriptor, false /*isAsynchronous*/, 0);
992         mStream = sp<StreamHalAidl>::make("test", false /*isInput*/, config, 0 /*nominalLatency*/,
993                                           std::move(context), mStreamCommon, mVendorExt);
994     }
TearDown()995     void TearDown() override {
996         mStream.clear();
997         mVendorExt.reset();
998         mStreamCommon.reset();
999     }
1000 
1001   protected:
1002     std::shared_ptr<StreamCommonMock> mStreamCommon;
1003     std::shared_ptr<TestHalAdapterVendorExtension> mVendorExt;
1004     sp<StreamHalAidl> mStream;
1005 };
1006 
TEST_F(StreamHalAidlVendorParametersTest,GetVendorParameter)1007 TEST_F(StreamHalAidlVendorParametersTest, GetVendorParameter) {
1008     EXPECT_EQ(0UL, mStreamCommon->getRetrievedParameterIds().size());
1009     String8 values;
1010     EXPECT_EQ(OK, mStream->getParameters(
1011                           String8(TestHalAdapterVendorExtension::kLegacyParameterKey.c_str()),
1012                           &values));
1013     EXPECT_EQ(1UL, mStreamCommon->getRetrievedParameterIds().size());
1014     if (mStreamCommon->getRetrievedParameterIds().size() >= 1) {
1015         EXPECT_EQ(TestHalAdapterVendorExtension::kStreamVendorParameterId,
1016                   mStreamCommon->getRetrievedParameterIds()[0]);
1017     }
1018 }
1019 
TEST_F(StreamHalAidlVendorParametersTest,SetVendorParameter)1020 TEST_F(StreamHalAidlVendorParametersTest, SetVendorParameter) {
1021     EXPECT_EQ(0UL, mStreamCommon->getAsyncParameters().size());
1022     EXPECT_EQ(0UL, mStreamCommon->getSyncParameters().size());
1023     EXPECT_EQ(OK, mStream->setParameters(createParameterString(
1024                           TestHalAdapterVendorExtension::kLegacyParameterKey, 42)));
1025     EXPECT_EQ(0UL, mStreamCommon->getAsyncParameters().size());
1026     EXPECT_EQ(1UL, mStreamCommon->getSyncParameters().size());
1027     EXPECT_EQ(OK, mStream->setParameters(createParameterString(
1028                           TestHalAdapterVendorExtension::kLegacyAsyncParameterKey, 43)));
1029     EXPECT_EQ(1UL, mStreamCommon->getAsyncParameters().size());
1030     EXPECT_EQ(1UL, mStreamCommon->getSyncParameters().size());
1031     if (mStreamCommon->getSyncParameters().size() >= 1) {
1032         EXPECT_EQ(TestHalAdapterVendorExtension::kStreamVendorParameterId,
1033                   mStreamCommon->getSyncParameters()[0].id);
1034         int value{};
1035         EXPECT_EQ(android::OK, parseVendorParameter(mStreamCommon->getSyncParameters()[0], &value));
1036         EXPECT_EQ(42, value);
1037     }
1038     if (mStreamCommon->getAsyncParameters().size() >= 1) {
1039         EXPECT_EQ(TestHalAdapterVendorExtension::kStreamVendorParameterId,
1040                   mStreamCommon->getAsyncParameters()[0].id);
1041         int value{};
1042         EXPECT_EQ(android::OK,
1043                   parseVendorParameter(mStreamCommon->getAsyncParameters()[0], &value));
1044         EXPECT_EQ(43, value);
1045     }
1046 }
1047 
TEST_F(StreamHalAidlVendorParametersTest,SetInvalidVendorParameters)1048 TEST_F(StreamHalAidlVendorParametersTest, SetInvalidVendorParameters) {
1049     android::AudioParameter legacy;
1050     legacy.addInt(android::String8(TestHalAdapterVendorExtension::kLegacyParameterKey.c_str()), 42);
1051     legacy.addInt(android::String8(TestHalAdapterVendorExtension::kLegacyAsyncParameterKey.c_str()),
1052                   43);
1053     legacy.addInt(android::String8("random_name"), 44);
1054     EXPECT_EQ(0UL, mStreamCommon->getAsyncParameters().size());
1055     EXPECT_EQ(0UL, mStreamCommon->getSyncParameters().size());
1056     // TestHalAdapterVendorExtension throws an error for unknown parameters.
1057     EXPECT_EQ(android::BAD_VALUE, mStream->setParameters(legacy.toString()));
1058     EXPECT_EQ(0UL, mStreamCommon->getAsyncParameters().size());
1059     EXPECT_EQ(0UL, mStreamCommon->getSyncParameters().size());
1060 }
1061 
1062 class Hal2AidlMapperTest : public testing::Test {
1063   public:
SetUp()1064     void SetUp() override {
1065         mModule = ndk::SharedRefBase::make<ModuleMock>(getTestConfiguration());
1066         mMapper = std::make_unique<Hal2AidlMapper>("test", mModule);
1067         ASSERT_EQ(OK, mMapper->initialize());
1068 
1069         mConnectedPort.ext = createPortDeviceExt(AudioDeviceType::OUT_DEVICE, 0,
1070                                                  AudioDeviceDescription::CONNECTION_BT_A2DP);
1071         mConnectedPort.ext.get<AudioPortExt::device>().device.address = "00:11:22:33:44:55";
1072         ASSERT_EQ(OK, mMapper->setDevicePortConnectedState(mConnectedPort, true /*connected*/));
1073 
1074         std::mutex mutex;  // Only needed for cleanups.
1075         auto mapperAccessor = std::make_unique<LockedAccessor<Hal2AidlMapper>>(*mMapper, mutex);
1076         Hal2AidlMapper::Cleanups cleanups(*mapperAccessor);
1077         AudioConfig config;
1078         config.base.channelMask = AudioChannelLayout::make<AudioChannelLayout::layoutMask>(
1079                 AudioChannelLayout::LAYOUT_STEREO);
1080         config.base.format =
1081                 AudioFormatDescription{.type = AudioFormatType::PCM, .pcm = PcmType::INT_16_BIT};
1082         config.base.sampleRate = 48000;
1083         ASSERT_EQ(OK,
1084                   mMapper->prepareToOpenStream(
1085                           42 /*ioHandle*/, mConnectedPort.ext.get<AudioPortExt::device>().device,
1086                           AudioIoFlags::make<AudioIoFlags::output>(0), AudioSource::DEFAULT,
1087                           &cleanups, &config, &mMixPortConfig, &mPatch));
1088         cleanups.disarmAll();
1089         ASSERT_NE(0, mPatch.id);
1090         ASSERT_NE(0, mMixPortConfig.id);
1091         mStream = sp<StreamHalMock>::make();
1092         mMapper->addStream(mStream, mMixPortConfig.id, mPatch.id);
1093 
1094         ASSERT_EQ(OK, mMapper->findPortConfig(mConnectedPort.ext.get<AudioPortExt::device>().device,
1095                                               &mDevicePortConfig));
1096         ASSERT_EQ(1UL, mPatch.sourcePortConfigIds.size());
1097         ASSERT_EQ(mMixPortConfig.id, mPatch.sourcePortConfigIds[0]);
1098         ASSERT_EQ(1UL, mPatch.sinkPortConfigIds.size());
1099         ASSERT_EQ(mDevicePortConfig.id, mPatch.sinkPortConfigIds[0]);
1100     }
1101 
TearDown()1102     void TearDown() override {
1103         mStream.clear();
1104         mMapper.reset();
1105         mModule.reset();
1106     }
1107 
1108   protected:
CloseDisconnectImpl()1109     void CloseDisconnectImpl() {
1110         mStream.clear();
1111         ASSERT_NO_FATAL_FAILURE(DisconnectDevice());
1112     }
1113 
ConnectAnotherDevice()1114     void ConnectAnotherDevice() {
1115         mConnectedPort.ext.get<AudioPortExt::device>().device.address = "00:11:22:33:44:66";
1116         ASSERT_EQ(OK, mMapper->setDevicePortConnectedState(mConnectedPort, true /*connected*/));
1117     }
1118 
CreateFwkPatch(int32_t * patchId)1119     void CreateFwkPatch(int32_t* patchId) {
1120         std::mutex mutex;  // Only needed for cleanups.
1121         auto mapperAccessor = std::make_unique<LockedAccessor<Hal2AidlMapper>>(*mMapper, mutex);
1122         Hal2AidlMapper::Cleanups cleanups(*mapperAccessor);
1123         ASSERT_EQ(OK, mMapper->createOrUpdatePatch({mMixPortConfig}, {mDevicePortConfig}, patchId,
1124                                                    &cleanups));
1125         cleanups.disarmAll();
1126     }
1127 
DisconnectDevice()1128     void DisconnectDevice() {
1129         ASSERT_EQ(OK, mMapper->prepareToDisconnectExternalDevice(mConnectedPort));
1130         ASSERT_EQ(OK, mMapper->setDevicePortConnectedState(mConnectedPort, false /*connected*/));
1131     }
1132 
ReleaseFwkOnlyPatch(int32_t patchId)1133     void ReleaseFwkOnlyPatch(int32_t patchId) {
1134         // The patch only exists for the framework.
1135         EXPECT_EQ(patchId, mMapper->findFwkPatch(patchId));
1136         ASSERT_EQ(BAD_VALUE, mMapper->releaseAudioPatch(patchId));
1137         mMapper->eraseFwkPatch(patchId);
1138         // The patch is now erased.
1139         EXPECT_EQ(0, mMapper->findFwkPatch(patchId));
1140     }
1141 
1142     std::shared_ptr<ModuleMock> mModule;
1143     std::unique_ptr<Hal2AidlMapper> mMapper;
1144     AudioPort mConnectedPort;
1145     AudioPortConfig mMixPortConfig;
1146     AudioPortConfig mDevicePortConfig;
1147     AudioPatch mPatch;
1148     sp<StreamHalInterface> mStream;
1149 };
1150 
1151 /**
1152  * External device connections and patches tests diagram.
1153  *
1154  * [Connect device] -> [Create Stream]
1155  *                            |-> [ (1) Close Stream] -> [Disconnect Device]
1156  *                            |-> [ (2) Disconnect Device]
1157  *                            |          |-> [ (3) Close Stream]
1158  *                            |          \-> [ (4) Connect Another Device]
1159  *                            |                    |-> (1)
1160  *                            |                    |-> (2) -> (3)
1161  *                            |                    \-> (5) -> (7)
1162  *                            \-> [ (5) Create/Update Fwk Patch]
1163  *                                       |-> [(6) Release Fwk Patch]
1164  *                                       |        |-> (1)
1165  *                                       |        \-> (2) (including reconnection)
1166  *                                       \-> [(7) Disconnect Device]
1167  *                                                |-> [Release Fwk Patch] -> [Close Stream]
1168  *                                                \-> (4) -> (5) -> (6) -> (1)
1169  *
1170  * Note that the test (acting on behalf of DeviceHalAidl) is responsible
1171  * for calling `eraseFwkPatch` and `updateFwkPatch` when needed.
1172  */
1173 
1174 // (1)
TEST_F(Hal2AidlMapperTest,CloseDisconnect)1175 TEST_F(Hal2AidlMapperTest, CloseDisconnect) {
1176     ASSERT_NO_FATAL_FAILURE(CloseDisconnectImpl());
1177     // The patch is owned by HAL, must not be listed under fwkPatches after disconnection.
1178     EXPECT_EQ(0, mMapper->findFwkPatch(mPatch.id));
1179 }
1180 
1181 // (2) -> (3)
TEST_F(Hal2AidlMapperTest,DisconnectClose)1182 TEST_F(Hal2AidlMapperTest, DisconnectClose) {
1183     ASSERT_NO_FATAL_FAILURE(DisconnectDevice());
1184     // The patch is owned by HAL, must not be listed under fwkPatches after disconnection.
1185     EXPECT_EQ(0, mMapper->findFwkPatch(mPatch.id));
1186     mStream.clear();
1187 }
1188 
1189 // (2) -> (4) -> (1)
TEST_F(Hal2AidlMapperTest,DisconnectConnectCloseDisconnect)1190 TEST_F(Hal2AidlMapperTest, DisconnectConnectCloseDisconnect) {
1191     ASSERT_NO_FATAL_FAILURE(DisconnectDevice());
1192     // The patch is owned by HAL, must not be listed under fwkPatches after disconnection.
1193     EXPECT_EQ(0, mMapper->findFwkPatch(mPatch.id));
1194     ASSERT_NO_FATAL_FAILURE(ConnectAnotherDevice());
1195     ASSERT_NO_FATAL_FAILURE(CloseDisconnectImpl());
1196     // The patch is owned by HAL, must not be listed under fwkPatches after disconnection.
1197     EXPECT_EQ(0, mMapper->findFwkPatch(mPatch.id));
1198 }
1199 
1200 // (2) -> (4) -> (2) -> (3)
TEST_F(Hal2AidlMapperTest,DisconnectConnectDisconnectClose)1201 TEST_F(Hal2AidlMapperTest, DisconnectConnectDisconnectClose) {
1202     ASSERT_NO_FATAL_FAILURE(DisconnectDevice());
1203     // The patch is owned by HAL, must not be listed under fwkPatches after disconnection.
1204     EXPECT_EQ(0, mMapper->findFwkPatch(mPatch.id));
1205     ASSERT_NO_FATAL_FAILURE(ConnectAnotherDevice());
1206     ASSERT_NO_FATAL_FAILURE(DisconnectDevice());
1207     // The patch is owned by HAL, must not be listed under fwkPatches after disconnection.
1208     EXPECT_EQ(0, mMapper->findFwkPatch(mPatch.id));
1209     mStream.clear();
1210 }
1211 
1212 // (5) -> (6) -> (1)
TEST_F(Hal2AidlMapperTest,CreateFwkPatchReleaseCloseDisconnect)1213 TEST_F(Hal2AidlMapperTest, CreateFwkPatchReleaseCloseDisconnect) {
1214     int32_t patchId;
1215     ASSERT_NO_FATAL_FAILURE(CreateFwkPatch(&patchId));
1216     // Must be the patch created during stream opening.
1217     ASSERT_EQ(mPatch.id, patchId);
1218     // The patch was not reset by HAL, must not be listed under fwkPatches.
1219     EXPECT_EQ(0, mMapper->findFwkPatch(mPatch.id));
1220 
1221     ASSERT_EQ(OK, mMapper->releaseAudioPatch(patchId));
1222     // The patch does not exist both for the fwk and the HAL, must not be listed under fwkPatches.
1223     EXPECT_EQ(0, mMapper->findFwkPatch(patchId));
1224     ASSERT_NO_FATAL_FAILURE(CloseDisconnectImpl());
1225     // The patch does not exist both for the fwk and the HAL, must not be listed under fwkPatches.
1226     EXPECT_EQ(0, mMapper->findFwkPatch(patchId));
1227 }
1228 
1229 // (5) -> (6) -> (2) -> (3)
TEST_F(Hal2AidlMapperTest,CreateFwkPatchReleaseDisconnectClose)1230 TEST_F(Hal2AidlMapperTest, CreateFwkPatchReleaseDisconnectClose) {
1231     int32_t patchId;
1232     ASSERT_NO_FATAL_FAILURE(CreateFwkPatch(&patchId));
1233     // Must be the patch created during stream opening.
1234     ASSERT_EQ(mPatch.id, patchId);
1235     // The patch was not reset by HAL, must not be listed under fwkPatches.
1236     EXPECT_EQ(0, mMapper->findFwkPatch(mPatch.id));
1237 
1238     ASSERT_EQ(OK, mMapper->releaseAudioPatch(patchId));
1239     // The patch does not exist both for the fwk and the HAL, must not be listed under fwkPatches.
1240     EXPECT_EQ(0, mMapper->findFwkPatch(patchId));
1241     ASSERT_NO_FATAL_FAILURE(DisconnectDevice());
1242     // The patch does not exist both for the fwk and the HAL, must not be listed under fwkPatches.
1243     EXPECT_EQ(0, mMapper->findFwkPatch(mPatch.id));
1244     mStream.clear();
1245 }
1246 
1247 // (5) -> (6) -> (2) -> (4) -> (2) -> (3)
TEST_F(Hal2AidlMapperTest,CreateFwkPatchReleaseDisconnectConnectDisconnectClose)1248 TEST_F(Hal2AidlMapperTest, CreateFwkPatchReleaseDisconnectConnectDisconnectClose) {
1249     int32_t patchId;
1250     ASSERT_NO_FATAL_FAILURE(CreateFwkPatch(&patchId));
1251     // Must be the patch created during stream opening.
1252     ASSERT_EQ(mPatch.id, patchId);
1253     // The patch was not reset by HAL, must not be listed under fwkPatches.
1254     EXPECT_EQ(0, mMapper->findFwkPatch(mPatch.id));
1255 
1256     ASSERT_EQ(OK, mMapper->releaseAudioPatch(patchId));
1257     // The patch does not exist both for the fwk and the HAL, must not be listed under fwkPatches.
1258     EXPECT_EQ(0, mMapper->findFwkPatch(patchId));
1259     ASSERT_NO_FATAL_FAILURE(DisconnectDevice());
1260     // The patch does not exist both for the fwk and the HAL, must not be listed under fwkPatches.
1261     EXPECT_EQ(0, mMapper->findFwkPatch(mPatch.id));
1262 
1263     ASSERT_NO_FATAL_FAILURE(ConnectAnotherDevice());
1264     ASSERT_NO_FATAL_FAILURE(DisconnectDevice());
1265     // The patch does not exist both for the fwk and the HAL, must not be listed under fwkPatches.
1266     EXPECT_EQ(0, mMapper->findFwkPatch(mPatch.id));
1267     mStream.clear();
1268 }
1269 
1270 // (5) -> (7) -> Release -> Close
TEST_F(Hal2AidlMapperTest,CreateFwkPatchDisconnectReleaseClose)1271 TEST_F(Hal2AidlMapperTest, CreateFwkPatchDisconnectReleaseClose) {
1272     int32_t patchId;
1273     ASSERT_NO_FATAL_FAILURE(CreateFwkPatch(&patchId));
1274     // Must be the patch created during stream opening.
1275     ASSERT_EQ(mPatch.id, patchId);
1276     // The patch was not reset by HAL, must not be listed under fwkPatches.
1277     EXPECT_EQ(0, mMapper->findFwkPatch(mPatch.id));
1278 
1279     ASSERT_NO_FATAL_FAILURE(DisconnectDevice());
1280     ASSERT_NO_FATAL_FAILURE(ReleaseFwkOnlyPatch(patchId));
1281 
1282     mStream.clear();
1283     EXPECT_EQ(0, mMapper->findFwkPatch(patchId));
1284 }
1285 
1286 // (5) -> (7) -> (4) -> (5) -> (6) -> (1)
TEST_F(Hal2AidlMapperTest,CreateFwkPatchDisconnectConnectUpdateReleaseCloseDisconnect)1287 TEST_F(Hal2AidlMapperTest, CreateFwkPatchDisconnectConnectUpdateReleaseCloseDisconnect) {
1288     int32_t patchId;
1289     ASSERT_NO_FATAL_FAILURE(CreateFwkPatch(&patchId));
1290     // Must be the patch created during stream opening.
1291     ASSERT_EQ(mPatch.id, patchId);
1292     // The patch was not reset by HAL, must not be listed under fwkPatches.
1293     EXPECT_EQ(0, mMapper->findFwkPatch(mPatch.id));
1294 
1295     ASSERT_NO_FATAL_FAILURE(DisconnectDevice());
1296     // The patch now only exists for the framework.
1297     EXPECT_EQ(mPatch.id, mMapper->findFwkPatch(mPatch.id));
1298 
1299     ASSERT_NO_FATAL_FAILURE(ConnectAnotherDevice());
1300     // Change the device address locally, for patch update.
1301     mDevicePortConfig.ext.get<AudioPortExt::device>().device.address =
1302             mConnectedPort.ext.get<AudioPortExt::device>().device.address;
1303     int32_t newPatchId = patchId;
1304     ASSERT_NO_FATAL_FAILURE(CreateFwkPatch(&newPatchId));
1305     EXPECT_NE(patchId, newPatchId);
1306     mMapper->updateFwkPatch(patchId, newPatchId);
1307     EXPECT_EQ(newPatchId, mMapper->findFwkPatch(patchId));
1308     // Just in case, check that HAL patch ID is not listed as a fwk patch.
1309     EXPECT_EQ(0, mMapper->findFwkPatch(newPatchId));
1310     // Verify that device port config was updated.
1311     ASSERT_EQ(OK, mMapper->findPortConfig(mConnectedPort.ext.get<AudioPortExt::device>().device,
1312                                           &mDevicePortConfig));
1313 
1314     ASSERT_EQ(OK, mMapper->releaseAudioPatch(newPatchId));
1315     // The patch does not exist both for the fwk and the HAL, must not be listed under fwkPatches.
1316     EXPECT_EQ(0, mMapper->findFwkPatch(patchId));
1317     // Just in case, check that HAL patch ID is not listed.
1318     EXPECT_EQ(0, mMapper->findFwkPatch(newPatchId));
1319 
1320     ASSERT_NO_FATAL_FAILURE(CloseDisconnectImpl());
1321     EXPECT_EQ(0, mMapper->findFwkPatch(mPatch.id));
1322     EXPECT_EQ(0, mMapper->findFwkPatch(patchId));
1323     EXPECT_EQ(0, mMapper->findFwkPatch(newPatchId));
1324 }
1325 
1326 // (2) -> (4) -> (5) -> (7) -> Release -> Close
TEST_F(Hal2AidlMapperTest,DisconnectConnectCreateFwkPatchDisconnectReleaseClose)1327 TEST_F(Hal2AidlMapperTest, DisconnectConnectCreateFwkPatchDisconnectReleaseClose) {
1328     const int32_t patchId = mPatch.id;
1329     ASSERT_NO_FATAL_FAILURE(DisconnectDevice());
1330     // The patch is owned by HAL, must not be listed under fwkPatches after disconnection.
1331     EXPECT_EQ(0, mMapper->findFwkPatch(mPatch.id));
1332 
1333     ASSERT_NO_FATAL_FAILURE(ConnectAnotherDevice());
1334     // Change the device address locally, for patch update.
1335     mDevicePortConfig.ext.get<AudioPortExt::device>().device.address =
1336             mConnectedPort.ext.get<AudioPortExt::device>().device.address;
1337     int32_t newPatchId = 0;  // Use 0 since the fwk does not know about the HAL patch.
1338     EXPECT_EQ(0, mMapper->findFwkPatch(newPatchId));
1339     ASSERT_NO_FATAL_FAILURE(CreateFwkPatch(&newPatchId));
1340     EXPECT_NE(0, newPatchId);
1341     EXPECT_NE(patchId, newPatchId);
1342     // Just in case, check that HAL patch ID is not listed as a fwk patch.
1343     EXPECT_EQ(0, mMapper->findFwkPatch(newPatchId));
1344     // Verify that device port config was updated.
1345     ASSERT_EQ(OK, mMapper->findPortConfig(mConnectedPort.ext.get<AudioPortExt::device>().device,
1346                                           &mDevicePortConfig));
1347 
1348     ASSERT_NO_FATAL_FAILURE(DisconnectDevice());
1349     ASSERT_NO_FATAL_FAILURE(ReleaseFwkOnlyPatch(newPatchId));
1350 
1351     mStream.clear();
1352     EXPECT_EQ(0, mMapper->findFwkPatch(mPatch.id));
1353     EXPECT_EQ(0, mMapper->findFwkPatch(newPatchId));
1354 }
1355 
TEST_F(Hal2AidlMapperTest,ChangeTransientPatchDevice)1356 TEST_F(Hal2AidlMapperTest, ChangeTransientPatchDevice) {
1357     std::mutex mutex;  // Only needed for cleanups.
1358     auto mapperAccessor = std::make_unique<LockedAccessor<Hal2AidlMapper>>(*mMapper, mutex);
1359     Hal2AidlMapper::Cleanups cleanups(*mapperAccessor);
1360     AudioConfig config;
1361     config.base.channelMask = AudioChannelLayout::make<AudioChannelLayout::layoutMask>(
1362             AudioChannelLayout::LAYOUT_STEREO);
1363     config.base.format =
1364             AudioFormatDescription{.type = AudioFormatType::PCM, .pcm = PcmType::INT_16_BIT};
1365     config.base.sampleRate = 48000;
1366     AudioDevice defaultDevice;
1367     defaultDevice.type.type = AudioDeviceType::IN_DEFAULT;
1368     AudioPortConfig mixPortConfig;
1369     AudioPatch transientPatch;
1370     ASSERT_EQ(OK, mMapper->prepareToOpenStream(43 /*ioHandle*/, defaultDevice,
1371                                                AudioIoFlags::make<AudioIoFlags::input>(0),
1372                                                AudioSource::DEFAULT, &cleanups, &config,
1373                                                &mixPortConfig, &transientPatch));
1374     cleanups.disarmAll();
1375     ASSERT_NE(0, transientPatch.id);
1376     ASSERT_NE(0, mixPortConfig.id);
1377     sp<StreamHalInterface> stream = sp<StreamHalMock>::make();
1378     mMapper->addStream(stream, mixPortConfig.id, transientPatch.id);
1379 
1380     AudioPatch patch{};
1381     int32_t patchId;
1382     AudioPortConfig backMicPortConfig;
1383     backMicPortConfig.channelMask = config.base.channelMask;
1384     backMicPortConfig.format = config.base.format;
1385     backMicPortConfig.sampleRate = aidl::android::media::audio::common::Int{config.base.sampleRate};
1386     backMicPortConfig.flags = AudioIoFlags::make<AudioIoFlags::input>(0);
1387     backMicPortConfig.ext = createPortDeviceExt(AudioDeviceType::IN_MICROPHONE_BACK, 0);
1388     ASSERT_EQ(OK, mMapper->createOrUpdatePatch({backMicPortConfig}, {mixPortConfig}, &patchId,
1389                                                &cleanups));
1390     cleanups.disarmAll();
1391     ASSERT_EQ(android::OK,
1392               mMapper->findPortConfig(backMicPortConfig.ext.get<AudioPortExt::device>().device,
1393                                       &backMicPortConfig));
1394     EXPECT_NE(0, backMicPortConfig.id);
1395 
1396     EXPECT_EQ(transientPatch.id, patchId);
1397     auto patches = mModule->getPatches();
1398     auto patchIt = findById(patches, patchId);
1399     ASSERT_NE(patchIt, patches.end());
1400     EXPECT_EQ(std::vector<int32_t>{backMicPortConfig.id}, patchIt->sourcePortConfigIds);
1401     EXPECT_EQ(std::vector<int32_t>{mixPortConfig.id}, patchIt->sinkPortConfigIds);
1402 }
1403 
TEST_F(Hal2AidlMapperTest,SetAudioPortConfigGainChangeExistingPortConfig)1404 TEST_F(Hal2AidlMapperTest, SetAudioPortConfigGainChangeExistingPortConfig) {
1405     // First set config, then update gain.
1406     AudioPortConfig speakerPortConfig;
1407     speakerPortConfig.ext = createPortDeviceExt(AudioDeviceType::OUT_SPEAKER, 0);
1408     speakerPortConfig.channelMask = AudioChannelLayout::make<AudioChannelLayout::layoutMask>(
1409             AudioChannelLayout::LAYOUT_STEREO);
1410     speakerPortConfig.format =
1411             AudioFormatDescription{.type = AudioFormatType::PCM, .pcm = PcmType::INT_16_BIT};
1412     speakerPortConfig.sampleRate = ::aidl::android::media::audio::common::Int(48000);
1413     AudioPortConfig resultingPortConfig;
1414     ASSERT_EQ(OK,
1415               mMapper->setPortConfig(speakerPortConfig, std::set<int32_t>(), &resultingPortConfig));
1416     EXPECT_NE(0, resultingPortConfig.id);
1417     EXPECT_NE(0, resultingPortConfig.portId);
1418 
1419     AudioPortConfig gainUpdate;
1420     gainUpdate.ext = createPortDeviceExt(AudioDeviceType::OUT_SPEAKER, 0);
1421     AudioGainConfig gainConfig{.index = -1,
1422                                .mode = 1 << static_cast<int>(AudioGainMode::JOINT),
1423                                .channelMask = AudioChannelLayout{},
1424                                .values = std::vector<int32_t>{-3200},
1425                                .rampDurationMs = 0};
1426     gainUpdate.gain = gainConfig;
1427     AudioPortConfig resultingGainUpdate;
1428     ASSERT_EQ(OK, mMapper->setPortConfig(gainUpdate, std::set<int32_t>(), &resultingGainUpdate));
1429     EXPECT_EQ(resultingPortConfig.id, resultingGainUpdate.id);
1430     auto updatedPortConfig = mModule->getPortConfig(resultingGainUpdate.id);
1431     ASSERT_TRUE(updatedPortConfig.has_value());
1432     ASSERT_TRUE(updatedPortConfig->gain.has_value());
1433     EXPECT_EQ(gainConfig, updatedPortConfig->gain);
1434 }
1435 
TEST_F(Hal2AidlMapperTest,SetAudioPortConfigGainChangeFromScratch)1436 TEST_F(Hal2AidlMapperTest, SetAudioPortConfigGainChangeFromScratch) {
1437     // Set gain as the first operation, the HAL should suggest the rest of the configuration.
1438     AudioPortConfig gainSet;
1439     gainSet.ext = createPortDeviceExt(AudioDeviceType::OUT_SPEAKER, 0);
1440     AudioGainConfig gainConfig{.index = -1,
1441                                .mode = 1 << static_cast<int>(AudioGainMode::JOINT),
1442                                .channelMask = AudioChannelLayout{},
1443                                .values = std::vector<int32_t>{-3200},
1444                                .rampDurationMs = 0};
1445     gainSet.gain = gainConfig;
1446     AudioPortConfig resultingPortConfig;
1447     ASSERT_EQ(OK, mMapper->setPortConfig(gainSet, std::set<int32_t>(), &resultingPortConfig));
1448     EXPECT_NE(0, resultingPortConfig.id);
1449     EXPECT_NE(0, resultingPortConfig.portId);
1450     auto portConfig = mModule->getPortConfig(resultingPortConfig.id);
1451     ASSERT_TRUE(portConfig.has_value());
1452     ASSERT_TRUE(portConfig->gain.has_value());
1453     EXPECT_EQ(gainConfig, portConfig->gain);
1454 }
1455