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