• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <algorithm>
18 #include <chrono>
19 #include <cmath>
20 #include <condition_variable>
21 #include <forward_list>
22 #include <limits>
23 #include <memory>
24 #include <mutex>
25 #include <optional>
26 #include <set>
27 #include <string>
28 #include <string_view>
29 #include <variant>
30 #include <vector>
31 
32 #define LOG_TAG "VtsHalAudioCore.Module"
33 #include <android-base/logging.h>
34 
35 #include <StreamWorker.h>
36 #include <Utils.h>
37 #include <aidl/Gtest.h>
38 #include <aidl/Vintf.h>
39 #include <aidl/android/hardware/audio/core/BnStreamCallback.h>
40 #include <aidl/android/hardware/audio/core/IModule.h>
41 #include <aidl/android/hardware/audio/core/ITelephony.h>
42 #include <aidl/android/hardware/audio/core/sounddose/ISoundDose.h>
43 #include <aidl/android/media/audio/common/AudioIoFlags.h>
44 #include <aidl/android/media/audio/common/AudioMMapPolicyInfo.h>
45 #include <aidl/android/media/audio/common/AudioMMapPolicyType.h>
46 #include <aidl/android/media/audio/common/AudioOutputFlags.h>
47 #include <android-base/chrono_utils.h>
48 #include <android/binder_enums.h>
49 #include <fmq/AidlMessageQueue.h>
50 
51 #include "AudioHalBinderServiceUtil.h"
52 #include "ModuleConfig.h"
53 #include "TestUtils.h"
54 
55 using namespace android;
56 using aidl::android::hardware::audio::common::AudioOffloadMetadata;
57 using aidl::android::hardware::audio::common::getChannelCount;
58 using aidl::android::hardware::audio::common::isBitPositionFlagSet;
59 using aidl::android::hardware::audio::common::isTelephonyDeviceType;
60 using aidl::android::hardware::audio::common::isValidAudioMode;
61 using aidl::android::hardware::audio::common::PlaybackTrackMetadata;
62 using aidl::android::hardware::audio::common::RecordTrackMetadata;
63 using aidl::android::hardware::audio::common::SinkMetadata;
64 using aidl::android::hardware::audio::common::SourceMetadata;
65 using aidl::android::hardware::audio::core::AudioPatch;
66 using aidl::android::hardware::audio::core::AudioRoute;
67 using aidl::android::hardware::audio::core::IBluetooth;
68 using aidl::android::hardware::audio::core::IBluetoothA2dp;
69 using aidl::android::hardware::audio::core::IBluetoothLe;
70 using aidl::android::hardware::audio::core::IModule;
71 using aidl::android::hardware::audio::core::IStreamCommon;
72 using aidl::android::hardware::audio::core::IStreamIn;
73 using aidl::android::hardware::audio::core::IStreamOut;
74 using aidl::android::hardware::audio::core::ITelephony;
75 using aidl::android::hardware::audio::core::ModuleDebug;
76 using aidl::android::hardware::audio::core::StreamDescriptor;
77 using aidl::android::hardware::audio::core::VendorParameter;
78 using aidl::android::hardware::audio::core::sounddose::ISoundDose;
79 using aidl::android::hardware::common::fmq::SynchronizedReadWrite;
80 using aidl::android::media::audio::common::AudioContentType;
81 using aidl::android::media::audio::common::AudioDevice;
82 using aidl::android::media::audio::common::AudioDeviceAddress;
83 using aidl::android::media::audio::common::AudioDeviceDescription;
84 using aidl::android::media::audio::common::AudioDeviceType;
85 using aidl::android::media::audio::common::AudioDualMonoMode;
86 using aidl::android::media::audio::common::AudioFormatType;
87 using aidl::android::media::audio::common::AudioIoFlags;
88 using aidl::android::media::audio::common::AudioLatencyMode;
89 using aidl::android::media::audio::common::AudioMMapPolicyInfo;
90 using aidl::android::media::audio::common::AudioMMapPolicyType;
91 using aidl::android::media::audio::common::AudioMode;
92 using aidl::android::media::audio::common::AudioOutputFlags;
93 using aidl::android::media::audio::common::AudioPlaybackRate;
94 using aidl::android::media::audio::common::AudioPort;
95 using aidl::android::media::audio::common::AudioPortConfig;
96 using aidl::android::media::audio::common::AudioPortDeviceExt;
97 using aidl::android::media::audio::common::AudioPortExt;
98 using aidl::android::media::audio::common::AudioPortMixExt;
99 using aidl::android::media::audio::common::AudioSource;
100 using aidl::android::media::audio::common::AudioUsage;
101 using aidl::android::media::audio::common::Boolean;
102 using aidl::android::media::audio::common::Float;
103 using aidl::android::media::audio::common::Int;
104 using aidl::android::media::audio::common::MicrophoneDynamicInfo;
105 using aidl::android::media::audio::common::MicrophoneInfo;
106 using aidl::android::media::audio::common::Void;
107 using android::hardware::audio::common::StreamLogic;
108 using android::hardware::audio::common::StreamWorker;
109 using ndk::enum_range;
110 using ndk::ScopedAStatus;
111 
112 template <typename T>
findById(std::vector<T> & v,int32_t id)113 auto findById(std::vector<T>& v, int32_t id) {
114     return std::find_if(v.begin(), v.end(), [&](const auto& e) { return e.id == id; });
115 }
116 
117 template <typename C>
GetNonExistentIds(const C & allIds)118 std::vector<int32_t> GetNonExistentIds(const C& allIds) {
119     if (allIds.empty()) {
120         return std::vector<int32_t>{-1, 0, 1};
121     }
122     std::vector<int32_t> nonExistentIds;
123     nonExistentIds.push_back(*std::min_element(allIds.begin(), allIds.end()) - 1);
124     nonExistentIds.push_back(*std::max_element(allIds.begin(), allIds.end()) + 1);
125     return nonExistentIds;
126 }
127 
suggestDeviceAddressTag(const AudioDeviceDescription & description)128 AudioDeviceAddress::Tag suggestDeviceAddressTag(const AudioDeviceDescription& description) {
129     using Tag = AudioDeviceAddress::Tag;
130     if (std::string_view connection = description.connection;
131         connection == AudioDeviceDescription::CONNECTION_BT_A2DP ||
132         // Note: BT LE Broadcast uses a "group id".
133         (description.type != AudioDeviceType::OUT_BROADCAST &&
134          connection == AudioDeviceDescription::CONNECTION_BT_LE) ||
135         connection == AudioDeviceDescription::CONNECTION_BT_SCO ||
136         connection == AudioDeviceDescription::CONNECTION_WIRELESS) {
137         return Tag::mac;
138     } else if (connection == AudioDeviceDescription::CONNECTION_IP_V4) {
139         return Tag::ipv4;
140     } else if (connection == AudioDeviceDescription::CONNECTION_USB) {
141         return Tag::alsa;
142     }
143     return Tag::id;
144 }
145 
GenerateUniqueDeviceAddress(const AudioPort & port)146 AudioPort GenerateUniqueDeviceAddress(const AudioPort& port) {
147     // Point-to-point connections do not use addresses.
148     static const std::set<std::string> kPointToPointConnections = {
149             AudioDeviceDescription::CONNECTION_ANALOG, AudioDeviceDescription::CONNECTION_HDMI,
150             AudioDeviceDescription::CONNECTION_HDMI_ARC,
151             AudioDeviceDescription::CONNECTION_HDMI_EARC, AudioDeviceDescription::CONNECTION_SPDIF};
152     static int nextId = 0;
153     using Tag = AudioDeviceAddress::Tag;
154     const auto& deviceDescription = port.ext.get<AudioPortExt::Tag::device>().device.type;
155     AudioDeviceAddress address;
156     if (kPointToPointConnections.count(deviceDescription.connection) == 0) {
157         switch (suggestDeviceAddressTag(deviceDescription)) {
158             case Tag::id:
159                 address = AudioDeviceAddress::make<Tag::id>(std::to_string(++nextId));
160                 break;
161             case Tag::mac:
162                 address = AudioDeviceAddress::make<Tag::mac>(
163                         std::vector<uint8_t>{1, 2, 3, 4, 5, static_cast<uint8_t>(++nextId & 0xff)});
164                 break;
165             case Tag::ipv4:
166                 address = AudioDeviceAddress::make<Tag::ipv4>(
167                         std::vector<uint8_t>{192, 168, 0, static_cast<uint8_t>(++nextId & 0xff)});
168                 break;
169             case Tag::ipv6:
170                 address = AudioDeviceAddress::make<Tag::ipv6>(std::vector<int32_t>{
171                         0xfc00, 0x0123, 0x4567, 0x89ab, 0xcdef, 0, 0, ++nextId & 0xffff});
172                 break;
173             case Tag::alsa:
174                 address = AudioDeviceAddress::make<Tag::alsa>(std::vector<int32_t>{1, ++nextId});
175                 break;
176         }
177     }
178     AudioPort result = port;
179     result.ext.get<AudioPortExt::Tag::device>().device.address = std::move(address);
180     return result;
181 }
182 
183 // All 'With*' classes are move-only because they are associated with some
184 // resource or state of a HAL module.
185 class WithDebugFlags {
186   public:
createNested(const WithDebugFlags & parent)187     static WithDebugFlags createNested(const WithDebugFlags& parent) {
188         return WithDebugFlags(parent.mFlags);
189     }
190 
191     WithDebugFlags() = default;
WithDebugFlags(const ModuleDebug & initial)192     explicit WithDebugFlags(const ModuleDebug& initial) : mInitial(initial), mFlags(initial) {}
193     WithDebugFlags(const WithDebugFlags&) = delete;
194     WithDebugFlags& operator=(const WithDebugFlags&) = delete;
~WithDebugFlags()195     ~WithDebugFlags() {
196         if (mModule != nullptr) {
197             EXPECT_IS_OK(mModule->setModuleDebug(mInitial));
198         }
199     }
SetUp(IModule * module)200     void SetUp(IModule* module) {
201         ASSERT_IS_OK(module->setModuleDebug(mFlags));
202         mModule = module;
203     }
flags()204     ModuleDebug& flags() { return mFlags; }
205 
206   private:
207     ModuleDebug mInitial;
208     ModuleDebug mFlags;
209     IModule* mModule = nullptr;
210 };
211 
212 template <typename T>
213 class WithModuleParameter {
214   public:
WithModuleParameter(const std::string parameterId,const T & value)215     WithModuleParameter(const std::string parameterId, const T& value)
216         : mParameterId(parameterId), mValue(value) {}
217     WithModuleParameter(const WithModuleParameter&) = delete;
218     WithModuleParameter& operator=(const WithModuleParameter&) = delete;
~WithModuleParameter()219     ~WithModuleParameter() {
220         if (mModule != nullptr) {
221             VendorParameter parameter{.id = mParameterId};
222             parameter.ext.setParcelable(mInitial);
223             EXPECT_IS_OK(mModule->setVendorParameters({parameter}, false));
224         }
225     }
SetUpNoChecks(IModule * module,bool failureExpected)226     ScopedAStatus SetUpNoChecks(IModule* module, bool failureExpected) {
227         std::vector<VendorParameter> parameters;
228         ScopedAStatus result = module->getVendorParameters({mParameterId}, &parameters);
229         if (result.isOk() && parameters.size() == 1) {
230             std::optional<T> maybeInitial;
231             binder_status_t status = parameters[0].ext.getParcelable(&maybeInitial);
232             if (status == STATUS_OK && maybeInitial.has_value()) {
233                 mInitial = maybeInitial.value();
234                 VendorParameter parameter{.id = mParameterId};
235                 parameter.ext.setParcelable(mValue);
236                 result = module->setVendorParameters({parameter}, false);
237                 if (result.isOk()) {
238                     LOG(INFO) << __func__ << ": overriding parameter \"" << mParameterId
239                               << "\" with " << mValue.toString()
240                               << ", old value: " << mInitial.toString();
241                     mModule = module;
242                 }
243             } else {
244                 LOG(ERROR) << __func__ << ": error while retrieving the value of \"" << mParameterId
245                            << "\"";
246                 return ScopedAStatus::fromStatus(status);
247             }
248         }
249         if (!result.isOk()) {
250             LOG(failureExpected ? INFO : ERROR)
251                     << __func__ << ": can not override vendor parameter \"" << mParameterId << "\""
252                     << result;
253         }
254         return result;
255     }
256 
257   private:
258     const std::string mParameterId;
259     const T mValue;
260     IModule* mModule = nullptr;
261     T mInitial;
262 };
263 
264 // For consistency, WithAudioPortConfig can start both with a non-existent
265 // port config, and with an existing one. Existence is determined by the
266 // id of the provided config. If it's not 0, then WithAudioPortConfig is
267 // essentially a no-op wrapper.
268 class WithAudioPortConfig {
269   public:
270     WithAudioPortConfig() = default;
WithAudioPortConfig(const AudioPortConfig & config)271     explicit WithAudioPortConfig(const AudioPortConfig& config) : mInitialConfig(config) {}
272     WithAudioPortConfig(const WithAudioPortConfig&) = delete;
273     WithAudioPortConfig& operator=(const WithAudioPortConfig&) = delete;
~WithAudioPortConfig()274     ~WithAudioPortConfig() {
275         if (mModule != nullptr) {
276             EXPECT_IS_OK(mModule->resetAudioPortConfig(getId())) << "port config id " << getId();
277         }
278     }
SetUp(IModule * module)279     void SetUp(IModule* module) {
280         ASSERT_NE(AudioPortExt::Tag::unspecified, mInitialConfig.ext.getTag())
281                 << "config: " << mInitialConfig.toString();
282         // Negotiation is allowed for device ports because the HAL module is
283         // allowed to provide an empty profiles list for attached devices.
284         ASSERT_NO_FATAL_FAILURE(
285                 SetUpImpl(module, mInitialConfig.ext.getTag() == AudioPortExt::Tag::device));
286     }
getId() const287     int32_t getId() const { return mConfig.id; }
get() const288     const AudioPortConfig& get() const { return mConfig; }
289 
290   private:
SetUpImpl(IModule * module,bool negotiate)291     void SetUpImpl(IModule* module, bool negotiate) {
292         if (mInitialConfig.id == 0) {
293             AudioPortConfig suggested;
294             bool applied = false;
295             ASSERT_IS_OK(module->setAudioPortConfig(mInitialConfig, &suggested, &applied))
296                     << "Config: " << mInitialConfig.toString();
297             if (!applied && negotiate) {
298                 mInitialConfig = suggested;
299                 ASSERT_NO_FATAL_FAILURE(SetUpImpl(module, false))
300                         << " while applying suggested config: " << suggested.toString();
301             } else {
302                 ASSERT_TRUE(applied) << "Suggested: " << suggested.toString();
303                 mConfig = suggested;
304                 mModule = module;
305             }
306         } else {
307             mConfig = mInitialConfig;
308         }
309     }
310 
311     AudioPortConfig mInitialConfig;
312     IModule* mModule = nullptr;
313     AudioPortConfig mConfig;
314 };
315 
316 template <typename T>
GenerateTestArrays(size_t validElementCount,T validMin,T validMax,std::vector<std::vector<T>> * validValues,std::vector<std::vector<T>> * invalidValues)317 void GenerateTestArrays(size_t validElementCount, T validMin, T validMax,
318                         std::vector<std::vector<T>>* validValues,
319                         std::vector<std::vector<T>>* invalidValues) {
320     validValues->emplace_back(validElementCount, validMin);
321     validValues->emplace_back(validElementCount, validMax);
322     validValues->emplace_back(validElementCount, (validMin + validMax) / 2.f);
323     if (validElementCount > 0) {
324         invalidValues->emplace_back(validElementCount - 1, validMin);
325     }
326     invalidValues->emplace_back(validElementCount + 1, validMin);
327     for (auto m : {-2, -1, 2}) {
328         const auto invalidMin = m * validMin;
329         if (invalidMin < validMin || invalidMin > validMax) {
330             invalidValues->emplace_back(validElementCount, invalidMin);
331         }
332         const auto invalidMax = m * validMax;
333         if (invalidMax < validMin || invalidMax > validMax) {
334             invalidValues->emplace_back(validElementCount, invalidMax);
335         }
336     }
337 }
338 
339 template <typename PropType, class Instance, typename Getter, typename Setter>
TestAccessors(Instance * inst,Getter getter,Setter setter,const std::vector<PropType> & validValues,const std::vector<PropType> & invalidValues,bool * isSupported)340 void TestAccessors(Instance* inst, Getter getter, Setter setter,
341                    const std::vector<PropType>& validValues,
342                    const std::vector<PropType>& invalidValues, bool* isSupported) {
343     PropType initialValue{};
344     ScopedAStatus status = (inst->*getter)(&initialValue);
345     if (status.getExceptionCode() == EX_UNSUPPORTED_OPERATION) {
346         *isSupported = false;
347         return;
348     }
349     ASSERT_TRUE(status.isOk()) << "Unexpected status from a getter: " << status;
350     *isSupported = true;
351     for (const auto v : validValues) {
352         EXPECT_IS_OK((inst->*setter)(v)) << "for a valid value: " << ::testing::PrintToString(v);
353         PropType currentValue{};
354         EXPECT_IS_OK((inst->*getter)(&currentValue));
355         EXPECT_EQ(v, currentValue);
356     }
357     for (const auto v : invalidValues) {
358         EXPECT_STATUS(EX_ILLEGAL_ARGUMENT, (inst->*setter)(v))
359                 << "for an invalid value: " << ::testing::PrintToString(v);
360     }
361     EXPECT_IS_OK((inst->*setter)(initialValue)) << "Failed to restore the initial value";
362 }
363 
364 template <class Instance>
TestGetVendorParameters(Instance * inst,bool * isSupported)365 void TestGetVendorParameters(Instance* inst, bool* isSupported) {
366     static const std::vector<std::vector<std::string>> kIdsLists = {{}, {"zero"}, {"one", "two"}};
367     static const auto kStatuses = {EX_ILLEGAL_ARGUMENT, EX_ILLEGAL_STATE, EX_UNSUPPORTED_OPERATION};
368     for (const auto& ids : kIdsLists) {
369         std::vector<VendorParameter> params;
370         if (ndk::ScopedAStatus status = inst->getVendorParameters(ids, &params); status.isOk()) {
371             EXPECT_EQ(ids.size(), params.size()) << "Size of the returned parameters list must "
372                                                  << "match the size of the provided ids list";
373             for (const auto& param : params) {
374                 EXPECT_NE(ids.end(), std::find(ids.begin(), ids.end(), param.id))
375                         << "Returned parameter id \"" << param.id << "\" is unexpected";
376             }
377             for (const auto& id : ids) {
378                 EXPECT_NE(params.end(),
379                           std::find_if(params.begin(), params.end(),
380                                        [&](const auto& param) { return param.id == id; }))
381                         << "Requested parameter with id \"" << id << "\" was not returned";
382             }
383         } else {
384             EXPECT_STATUS(kStatuses, status);
385             if (status.getExceptionCode() == EX_UNSUPPORTED_OPERATION) {
386                 *isSupported = false;
387                 return;
388             }
389         }
390     }
391     *isSupported = true;
392 }
393 
394 template <class Instance>
TestSetVendorParameters(Instance * inst,bool * isSupported)395 void TestSetVendorParameters(Instance* inst, bool* isSupported) {
396     static const auto kStatuses = {EX_NONE, EX_ILLEGAL_ARGUMENT, EX_ILLEGAL_STATE,
397                                    EX_UNSUPPORTED_OPERATION};
398     static const std::vector<std::vector<VendorParameter>> kParamsLists = {
399             {}, {VendorParameter{"zero"}}, {VendorParameter{"one"}, VendorParameter{"two"}}};
400     for (const auto& params : kParamsLists) {
401         ndk::ScopedAStatus status = inst->setVendorParameters(params, false);
402         if (status.getExceptionCode() == EX_UNSUPPORTED_OPERATION) {
403             *isSupported = false;
404             return;
405         }
406         EXPECT_STATUS(kStatuses, status)
407                 << ::android::internal::ToString(params) << ", async: false";
408         EXPECT_STATUS(kStatuses, inst->setVendorParameters(params, true))
409                 << ::android::internal::ToString(params) << ", async: true";
410     }
411     *isSupported = true;
412 }
413 
414 // Can be used as a base for any test here, does not depend on the fixture GTest parameters.
415 class AudioCoreModuleBase {
416   public:
417     // Default buffer sizes are used mostly for negative tests.
418     static constexpr int kDefaultBufferSizeFrames = 256;
419     static constexpr int kDefaultLargeBufferSizeFrames = 48000;
420 
SetUpImpl(const std::string & moduleName)421     void SetUpImpl(const std::string& moduleName) {
422         ASSERT_NO_FATAL_FAILURE(ConnectToService(moduleName));
423     }
424 
TearDownImpl()425     void TearDownImpl() { debug.reset(); }
426 
ConnectToService(const std::string & moduleName)427     void ConnectToService(const std::string& moduleName) {
428         ASSERT_EQ(module, nullptr);
429         ASSERT_EQ(debug, nullptr);
430         module = IModule::fromBinder(binderUtil.connectToService(moduleName));
431         ASSERT_NE(module, nullptr);
432         ASSERT_NO_FATAL_FAILURE(SetUpDebug());
433     }
434 
RestartService()435     void RestartService() {
436         ASSERT_NE(module, nullptr);
437         moduleConfig.reset();
438         debug.reset();
439         module = IModule::fromBinder(binderUtil.restartService());
440         ASSERT_NE(module, nullptr);
441         ASSERT_NO_FATAL_FAILURE(SetUpDebug());
442     }
443 
SetUpDebug()444     void SetUpDebug() {
445         debug.reset(new WithDebugFlags());
446         debug->flags().simulateDeviceConnections = true;
447         ASSERT_NO_FATAL_FAILURE(debug->SetUp(module.get()));
448     }
449 
ApplyEveryConfig(const std::vector<AudioPortConfig> & configs)450     void ApplyEveryConfig(const std::vector<AudioPortConfig>& configs) {
451         for (const auto& config : configs) {
452             ASSERT_NE(0, config.portId);
453             WithAudioPortConfig portConfig(config);
454             ASSERT_NO_FATAL_FAILURE(portConfig.SetUp(module.get()));  // calls setAudioPortConfig
455             EXPECT_EQ(config.portId, portConfig.get().portId);
456             std::vector<AudioPortConfig> retrievedPortConfigs;
457             ASSERT_IS_OK(module->getAudioPortConfigs(&retrievedPortConfigs));
458             const int32_t portConfigId = portConfig.getId();
459             auto configIt = std::find_if(
460                     retrievedPortConfigs.begin(), retrievedPortConfigs.end(),
461                     [&portConfigId](const auto& retrConf) { return retrConf.id == portConfigId; });
462             EXPECT_NE(configIt, retrievedPortConfigs.end())
463                     << "Port config id returned by setAudioPortConfig: " << portConfigId
464                     << " is not found in the list returned by getAudioPortConfigs";
465             if (configIt != retrievedPortConfigs.end()) {
466                 EXPECT_EQ(portConfig.get(), *configIt)
467                         << "Applied port config returned by setAudioPortConfig: "
468                         << portConfig.get().toString()
469                         << " is not the same as retrieved via getAudioPortConfigs: "
470                         << configIt->toString();
471             }
472         }
473     }
474 
475     template <typename Entity>
GetAllEntityIds(std::set<int32_t> * entityIds,ScopedAStatus (IModule::* getter)(std::vector<Entity> *),const std::string & errorMessage)476     void GetAllEntityIds(std::set<int32_t>* entityIds,
477                          ScopedAStatus (IModule::*getter)(std::vector<Entity>*),
478                          const std::string& errorMessage) {
479         std::vector<Entity> entities;
480         { ASSERT_IS_OK((module.get()->*getter)(&entities)); }
481         std::transform(entities.begin(), entities.end(),
482                        std::inserter(*entityIds, entityIds->begin()),
483                        [](const auto& entity) { return entity.id; });
484         EXPECT_EQ(entities.size(), entityIds->size()) << errorMessage;
485     }
486 
GetAllPatchIds(std::set<int32_t> * patchIds)487     void GetAllPatchIds(std::set<int32_t>* patchIds) {
488         return GetAllEntityIds<AudioPatch>(
489                 patchIds, &IModule::getAudioPatches,
490                 "IDs of audio patches returned by IModule.getAudioPatches are not unique");
491     }
492 
GetAllPortIds(std::set<int32_t> * portIds)493     void GetAllPortIds(std::set<int32_t>* portIds) {
494         return GetAllEntityIds<AudioPort>(
495                 portIds, &IModule::getAudioPorts,
496                 "IDs of audio ports returned by IModule.getAudioPorts are not unique");
497     }
498 
GetAllPortConfigIds(std::set<int32_t> * portConfigIds)499     void GetAllPortConfigIds(std::set<int32_t>* portConfigIds) {
500         return GetAllEntityIds<AudioPortConfig>(
501                 portConfigIds, &IModule::getAudioPortConfigs,
502                 "IDs of audio port configs returned by IModule.getAudioPortConfigs are not unique");
503     }
504 
SetUpModuleConfig()505     void SetUpModuleConfig() {
506         if (moduleConfig == nullptr) {
507             moduleConfig = std::make_unique<ModuleConfig>(module.get());
508             ASSERT_EQ(EX_NONE, moduleConfig->getStatus().getExceptionCode())
509                     << "ModuleConfig init error: " << moduleConfig->getError();
510         }
511     }
512 
513     std::shared_ptr<IModule> module;
514     std::unique_ptr<ModuleConfig> moduleConfig;
515     AudioHalBinderServiceUtil binderUtil;
516     std::unique_ptr<WithDebugFlags> debug;
517 };
518 
519 class AudioCoreModule : public AudioCoreModuleBase, public testing::TestWithParam<std::string> {
520   public:
SetUp()521     void SetUp() override { ASSERT_NO_FATAL_FAILURE(SetUpImpl(GetParam())); }
522 
TearDown()523     void TearDown() override { ASSERT_NO_FATAL_FAILURE(TearDownImpl()); }
524 };
525 
526 class WithDevicePortConnectedState {
527   public:
WithDevicePortConnectedState(const AudioPort & idAndData)528     explicit WithDevicePortConnectedState(const AudioPort& idAndData) : mIdAndData(idAndData) {}
529     WithDevicePortConnectedState(const WithDevicePortConnectedState&) = delete;
530     WithDevicePortConnectedState& operator=(const WithDevicePortConnectedState&) = delete;
~WithDevicePortConnectedState()531     ~WithDevicePortConnectedState() {
532         if (mModule != nullptr) {
533             EXPECT_IS_OK(mModule->disconnectExternalDevice(getId()))
534                     << "when disconnecting device port ID " << getId();
535         }
536         if (mModuleConfig != nullptr) {
537             EXPECT_IS_OK(mModuleConfig->onExternalDeviceDisconnected(mModule, mConnectedPort))
538                     << "when external device disconnected";
539         }
540     }
SetUp(IModule * module,ModuleConfig * moduleConfig)541     void SetUp(IModule* module, ModuleConfig* moduleConfig) {
542         ASSERT_IS_OK(module->connectExternalDevice(mIdAndData, &mConnectedPort))
543                 << "when connecting device port ID & data " << mIdAndData.toString();
544         ASSERT_NE(mIdAndData.id, getId())
545                 << "ID of the connected port must not be the same as the ID of the template port";
546         ASSERT_NE(moduleConfig, nullptr);
547         ASSERT_IS_OK(moduleConfig->onExternalDeviceConnected(module, mConnectedPort))
548                 << "when external device connected";
549         mModule = module;
550         mModuleConfig = moduleConfig;
551     }
getId() const552     int32_t getId() const { return mConnectedPort.id; }
get()553     const AudioPort& get() { return mConnectedPort; }
554 
555   private:
556     const AudioPort mIdAndData;
557     IModule* mModule = nullptr;
558     ModuleConfig* mModuleConfig = nullptr;
559     AudioPort mConnectedPort;
560 };
561 
562 class StreamContext {
563   public:
564     typedef AidlMessageQueue<StreamDescriptor::Command, SynchronizedReadWrite> CommandMQ;
565     typedef AidlMessageQueue<StreamDescriptor::Reply, SynchronizedReadWrite> ReplyMQ;
566     typedef AidlMessageQueue<int8_t, SynchronizedReadWrite> DataMQ;
567 
StreamContext(const StreamDescriptor & descriptor)568     explicit StreamContext(const StreamDescriptor& descriptor)
569         : mFrameSizeBytes(descriptor.frameSizeBytes),
570           mCommandMQ(new CommandMQ(descriptor.command)),
571           mReplyMQ(new ReplyMQ(descriptor.reply)),
572           mBufferSizeFrames(descriptor.bufferSizeFrames),
573           mDataMQ(maybeCreateDataMQ(descriptor)) {}
checkIsValid() const574     void checkIsValid() const {
575         EXPECT_NE(0UL, mFrameSizeBytes);
576         ASSERT_NE(nullptr, mCommandMQ);
577         EXPECT_TRUE(mCommandMQ->isValid());
578         ASSERT_NE(nullptr, mReplyMQ);
579         EXPECT_TRUE(mReplyMQ->isValid());
580         if (mDataMQ != nullptr) {
581             EXPECT_TRUE(mDataMQ->isValid());
582             EXPECT_GE(mDataMQ->getQuantumCount() * mDataMQ->getQuantumSize(),
583                       mFrameSizeBytes * mBufferSizeFrames)
584                     << "Data MQ actual buffer size is "
585                        "less than the buffer size as specified by the descriptor";
586         }
587     }
getBufferSizeBytes() const588     size_t getBufferSizeBytes() const { return mFrameSizeBytes * mBufferSizeFrames; }
getBufferSizeFrames() const589     size_t getBufferSizeFrames() const { return mBufferSizeFrames; }
getCommandMQ() const590     CommandMQ* getCommandMQ() const { return mCommandMQ.get(); }
getDataMQ() const591     DataMQ* getDataMQ() const { return mDataMQ.get(); }
getFrameSizeBytes() const592     size_t getFrameSizeBytes() const { return mFrameSizeBytes; }
getReplyMQ() const593     ReplyMQ* getReplyMQ() const { return mReplyMQ.get(); }
594 
595   private:
maybeCreateDataMQ(const StreamDescriptor & descriptor)596     static std::unique_ptr<DataMQ> maybeCreateDataMQ(const StreamDescriptor& descriptor) {
597         using Tag = StreamDescriptor::AudioBuffer::Tag;
598         if (descriptor.audio.getTag() == Tag::fmq) {
599             return std::make_unique<DataMQ>(descriptor.audio.get<Tag::fmq>());
600         }
601         return nullptr;
602     }
603 
604     const size_t mFrameSizeBytes;
605     std::unique_ptr<CommandMQ> mCommandMQ;
606     std::unique_ptr<ReplyMQ> mReplyMQ;
607     const size_t mBufferSizeFrames;
608     std::unique_ptr<DataMQ> mDataMQ;
609 };
610 
611 struct StreamEventReceiver {
612     virtual ~StreamEventReceiver() = default;
613     enum class Event { None, DrainReady, Error, TransferReady };
614     virtual std::tuple<int, Event> getLastEvent() const = 0;
615     virtual std::tuple<int, Event> waitForEvent(int clientEventSeq) = 0;
616     static constexpr int kEventSeqInit = -1;
617 };
toString(StreamEventReceiver::Event event)618 std::string toString(StreamEventReceiver::Event event) {
619     switch (event) {
620         case StreamEventReceiver::Event::None:
621             return "None";
622         case StreamEventReceiver::Event::DrainReady:
623             return "DrainReady";
624         case StreamEventReceiver::Event::Error:
625             return "Error";
626         case StreamEventReceiver::Event::TransferReady:
627             return "TransferReady";
628     }
629     return std::to_string(static_cast<int32_t>(event));
630 }
631 
632 // Note: we use a reference wrapper, not a pointer, because methods of std::*list
633 // return references to inserted elements. This way, we can put a returned reference
634 // into the children vector without any type conversions, and this makes DAG creation
635 // code more clear.
636 template <typename T>
637 struct DagNode : public std::pair<T, std::vector<std::reference_wrapper<DagNode<T>>>> {
638     using Children = std::vector<std::reference_wrapper<DagNode>>;
DagNodeDagNode639     DagNode(const T& t, const Children& c) : std::pair<T, Children>(t, c) {}
DagNodeDagNode640     DagNode(T&& t, Children&& c) : std::pair<T, Children>(std::move(t), std::move(c)) {}
datumDagNode641     const T& datum() const { return this->first; }
childrenDagNode642     Children& children() { return this->second; }
childrenDagNode643     const Children& children() const { return this->second; }
644 };
645 // Since DagNodes do contain references to next nodes, node links provided
646 // by the list are not used. Thus, the order of the nodes in the list is not
647 // important, except that the starting node must be at the front of the list,
648 // which means, it must always be added last.
649 template <typename T>
650 struct Dag : public std::forward_list<DagNode<T>> {
651     Dag() = default;
652     // We prohibit copying and moving Dag instances because implementing that
653     // is not trivial due to references between nodes.
654     Dag(const Dag&) = delete;
655     Dag(Dag&&) = delete;
656     Dag& operator=(const Dag&) = delete;
657     Dag& operator=(Dag&&) = delete;
658 };
659 
660 // Transition to the next state happens either due to a command from the client,
661 // or after an event received from the server.
662 using TransitionTrigger = std::variant<StreamDescriptor::Command, StreamEventReceiver::Event>;
toString(const TransitionTrigger & trigger)663 std::string toString(const TransitionTrigger& trigger) {
664     if (std::holds_alternative<StreamDescriptor::Command>(trigger)) {
665         return std::string("'")
666                 .append(toString(std::get<StreamDescriptor::Command>(trigger).getTag()))
667                 .append("' command");
668     }
669     return std::string("'")
670             .append(toString(std::get<StreamEventReceiver::Event>(trigger)))
671             .append("' event");
672 }
673 
674 struct StateSequence {
675     virtual ~StateSequence() = default;
676     virtual void rewind() = 0;
677     virtual bool done() const = 0;
678     virtual TransitionTrigger getTrigger() = 0;
679     virtual std::set<StreamDescriptor::State> getExpectedStates() = 0;
680     virtual void advance(StreamDescriptor::State state) = 0;
681 };
682 
683 // Defines the current state and the trigger to transfer to the next one,
684 // thus "state" is the "from" state.
685 using StateTransitionFrom = std::pair<StreamDescriptor::State, TransitionTrigger>;
686 
687 static const StreamDescriptor::Command kGetStatusCommand =
688         StreamDescriptor::Command::make<StreamDescriptor::Command::Tag::getStatus>(Void{});
689 static const StreamDescriptor::Command kStartCommand =
690         StreamDescriptor::Command::make<StreamDescriptor::Command::Tag::start>(Void{});
691 static const StreamDescriptor::Command kBurstCommand =
692         StreamDescriptor::Command::make<StreamDescriptor::Command::Tag::burst>(0);
693 static const StreamDescriptor::Command kDrainInCommand =
694         StreamDescriptor::Command::make<StreamDescriptor::Command::Tag::drain>(
695                 StreamDescriptor::DrainMode::DRAIN_UNSPECIFIED);
696 static const StreamDescriptor::Command kDrainOutAllCommand =
697         StreamDescriptor::Command::make<StreamDescriptor::Command::Tag::drain>(
698                 StreamDescriptor::DrainMode::DRAIN_ALL);
699 static const StreamDescriptor::Command kDrainOutEarlyCommand =
700         StreamDescriptor::Command::make<StreamDescriptor::Command::Tag::drain>(
701                 StreamDescriptor::DrainMode::DRAIN_EARLY_NOTIFY);
702 static const StreamDescriptor::Command kStandbyCommand =
703         StreamDescriptor::Command::make<StreamDescriptor::Command::Tag::standby>(Void{});
704 static const StreamDescriptor::Command kPauseCommand =
705         StreamDescriptor::Command::make<StreamDescriptor::Command::Tag::pause>(Void{});
706 static const StreamDescriptor::Command kFlushCommand =
707         StreamDescriptor::Command::make<StreamDescriptor::Command::Tag::flush>(Void{});
708 static const StreamEventReceiver::Event kTransferReadyEvent =
709         StreamEventReceiver::Event::TransferReady;
710 static const StreamEventReceiver::Event kDrainReadyEvent = StreamEventReceiver::Event::DrainReady;
711 
712 struct StateDag : public Dag<StateTransitionFrom> {
713     using Node = StateDag::reference;
714     using NextStates = StateDag::value_type::Children;
715 
716     template <typename... Next>
makeNodeStateDag717     Node makeNode(StreamDescriptor::State s, TransitionTrigger t, Next&&... next) {
718         return emplace_front(std::make_pair(s, t), NextStates{std::forward<Next>(next)...});
719     }
makeNodesStateDag720     Node makeNodes(const std::vector<StateTransitionFrom>& v, Node last) {
721         auto helper = [&](auto i, auto&& h) -> Node {
722             if (i == v.end()) return last;
723             return makeNode(i->first, i->second, h(++i, h));
724         };
725         return helper(v.begin(), helper);
726     }
makeNodesStateDag727     Node makeNodes(const std::vector<StateTransitionFrom>& v, StreamDescriptor::State f) {
728         return makeNodes(v, makeFinalNode(f));
729     }
makeFinalNodeStateDag730     Node makeFinalNode(StreamDescriptor::State s) {
731         // The actual command used here is irrelevant. Since it's the final node
732         // in the test sequence, no commands sent after reaching it.
733         return emplace_front(std::make_pair(s, kGetStatusCommand), NextStates{});
734     }
735 };
736 
737 class StateSequenceFollower : public StateSequence {
738   public:
StateSequenceFollower(std::unique_ptr<StateDag> steps)739     explicit StateSequenceFollower(std::unique_ptr<StateDag> steps)
740         : mSteps(std::move(steps)), mCurrent(mSteps->front()) {}
rewind()741     void rewind() override { mCurrent = mSteps->front(); }
done() const742     bool done() const override { return current().children().empty(); }
getTrigger()743     TransitionTrigger getTrigger() override { return current().datum().second; }
getExpectedStates()744     std::set<StreamDescriptor::State> getExpectedStates() override {
745         std::set<StreamDescriptor::State> result;
746         std::transform(current().children().cbegin(), current().children().cend(),
747                        std::inserter(result, result.begin()),
748                        [](const auto& node) { return node.get().datum().first; });
749         LOG(DEBUG) << __func__ << ": " << ::android::internal::ToString(result);
750         return result;
751     }
advance(StreamDescriptor::State state)752     void advance(StreamDescriptor::State state) override {
753         if (auto it = std::find_if(
754                     current().children().cbegin(), current().children().cend(),
755                     [&](const auto& node) { return node.get().datum().first == state; });
756             it != current().children().cend()) {
757             LOG(DEBUG) << __func__ << ": " << toString(mCurrent.get().datum().first) << " -> "
758                        << toString(it->get().datum().first);
759             mCurrent = *it;
760         } else {
761             LOG(FATAL) << __func__ << ": state " << toString(state) << " is unexpected";
762         }
763     }
764 
765   private:
current() const766     StateDag::const_reference current() const { return mCurrent.get(); }
767     std::unique_ptr<StateDag> mSteps;
768     std::reference_wrapper<StateDag::value_type> mCurrent;
769 };
770 
771 struct StreamLogicDriver {
772     virtual ~StreamLogicDriver() = default;
773     // Return 'true' to stop the worker.
774     virtual bool done() = 0;
775     // For 'Writer' logic, if the 'actualSize' is 0, write is skipped.
776     // The 'fmqByteCount' from the returned command is passed as is to the HAL.
777     virtual TransitionTrigger getNextTrigger(int maxDataSize, int* actualSize = nullptr) = 0;
778     // Return 'true' to indicate that no further processing is needed,
779     // for example, the driver is expecting a bad status to be returned.
780     // The logic cycle will return with 'CONTINUE' status. Otherwise,
781     // the reply will be validated and then passed to 'processValidReply'.
782     virtual bool interceptRawReply(const StreamDescriptor::Reply& reply) = 0;
783     // Return 'false' to indicate that the contents of the reply are unexpected.
784     // Will abort the logic cycle.
785     virtual bool processValidReply(const StreamDescriptor::Reply& reply) = 0;
786 };
787 
788 class StreamCommonLogic : public StreamLogic {
789   protected:
StreamCommonLogic(const StreamContext & context,StreamLogicDriver * driver,StreamEventReceiver * eventReceiver)790     StreamCommonLogic(const StreamContext& context, StreamLogicDriver* driver,
791                       StreamEventReceiver* eventReceiver)
792         : mCommandMQ(context.getCommandMQ()),
793           mReplyMQ(context.getReplyMQ()),
794           mDataMQ(context.getDataMQ()),
795           mData(context.getBufferSizeBytes()),
796           mDriver(driver),
797           mEventReceiver(eventReceiver) {}
getCommandMQ() const798     StreamContext::CommandMQ* getCommandMQ() const { return mCommandMQ; }
getReplyMQ() const799     StreamContext::ReplyMQ* getReplyMQ() const { return mReplyMQ; }
getDataMQ() const800     StreamContext::DataMQ* getDataMQ() const { return mDataMQ; }
getDriver() const801     StreamLogicDriver* getDriver() const { return mDriver; }
getEventReceiver() const802     StreamEventReceiver* getEventReceiver() const { return mEventReceiver; }
803 
init()804     std::string init() override {
805         LOG(DEBUG) << __func__;
806         return "";
807     }
maybeGetNextCommand(int * actualSize=nullptr)808     std::optional<StreamDescriptor::Command> maybeGetNextCommand(int* actualSize = nullptr) {
809         TransitionTrigger trigger = mDriver->getNextTrigger(mData.size(), actualSize);
810         if (StreamEventReceiver::Event* expEvent =
811                     std::get_if<StreamEventReceiver::Event>(&trigger);
812             expEvent != nullptr) {
813             auto [eventSeq, event] = mEventReceiver->waitForEvent(mLastEventSeq);
814             mLastEventSeq = eventSeq;
815             if (event != *expEvent) {
816                 LOG(ERROR) << __func__ << ": expected event " << toString(*expEvent) << ", got "
817                            << toString(event);
818                 return {};
819             }
820             // If we were waiting for an event, the new stream state must be retrieved
821             // via 'getStatus'.
822             return StreamDescriptor::Command::make<StreamDescriptor::Command::Tag::getStatus>(
823                     Void{});
824         }
825         return std::get<StreamDescriptor::Command>(trigger);
826     }
readDataFromMQ(size_t readCount)827     bool readDataFromMQ(size_t readCount) {
828         std::vector<int8_t> data(readCount);
829         if (mDataMQ->read(data.data(), readCount)) {
830             memcpy(mData.data(), data.data(), std::min(mData.size(), data.size()));
831             return true;
832         }
833         LOG(ERROR) << __func__ << ": reading of " << readCount << " bytes from MQ failed";
834         return false;
835     }
writeDataToMQ()836     bool writeDataToMQ() {
837         if (mDataMQ->write(mData.data(), mData.size())) {
838             return true;
839         }
840         LOG(ERROR) << __func__ << ": writing of " << mData.size() << " bytes to MQ failed";
841         return false;
842     }
843 
844   private:
845     StreamContext::CommandMQ* mCommandMQ;
846     StreamContext::ReplyMQ* mReplyMQ;
847     StreamContext::DataMQ* mDataMQ;
848     std::vector<int8_t> mData;
849     StreamLogicDriver* const mDriver;
850     StreamEventReceiver* const mEventReceiver;
851     int mLastEventSeq = StreamEventReceiver::kEventSeqInit;
852 };
853 
854 class StreamReaderLogic : public StreamCommonLogic {
855   public:
StreamReaderLogic(const StreamContext & context,StreamLogicDriver * driver,StreamEventReceiver * eventReceiver)856     StreamReaderLogic(const StreamContext& context, StreamLogicDriver* driver,
857                       StreamEventReceiver* eventReceiver)
858         : StreamCommonLogic(context, driver, eventReceiver) {}
859 
860   protected:
cycle()861     Status cycle() override {
862         if (getDriver()->done()) {
863             LOG(DEBUG) << __func__ << ": clean exit";
864             return Status::EXIT;
865         }
866         StreamDescriptor::Command command;
867         if (auto maybeCommand = maybeGetNextCommand(); maybeCommand.has_value()) {
868             command = std::move(maybeCommand.value());
869         } else {
870             LOG(ERROR) << __func__ << ": no next command";
871             return Status::ABORT;
872         }
873         LOG(DEBUG) << "Writing command: " << command.toString();
874         if (!getCommandMQ()->writeBlocking(&command, 1)) {
875             LOG(ERROR) << __func__ << ": writing of command into MQ failed";
876             return Status::ABORT;
877         }
878         StreamDescriptor::Reply reply{};
879         LOG(DEBUG) << "Reading reply...";
880         if (!getReplyMQ()->readBlocking(&reply, 1)) {
881             return Status::ABORT;
882         }
883         LOG(DEBUG) << "Reply received: " << reply.toString();
884         if (getDriver()->interceptRawReply(reply)) {
885             LOG(DEBUG) << __func__ << ": reply has been intercepted by the driver";
886             return Status::CONTINUE;
887         }
888         if (reply.status != STATUS_OK) {
889             LOG(ERROR) << __func__ << ": received error status: " << statusToString(reply.status);
890             return Status::ABORT;
891         }
892         if (reply.fmqByteCount < 0 ||
893             (command.getTag() == StreamDescriptor::Command::Tag::burst &&
894              reply.fmqByteCount > command.get<StreamDescriptor::Command::Tag::burst>())) {
895             LOG(ERROR) << __func__
896                        << ": received invalid byte count in the reply: " << reply.fmqByteCount;
897             return Status::ABORT;
898         }
899         if (static_cast<size_t>(reply.fmqByteCount) != getDataMQ()->availableToRead()) {
900             LOG(ERROR) << __func__
901                        << ": the byte count in the reply is not the same as the amount of "
902                        << "data available in the MQ: " << reply.fmqByteCount
903                        << " != " << getDataMQ()->availableToRead();
904         }
905         if (reply.latencyMs < 0 && reply.latencyMs != StreamDescriptor::LATENCY_UNKNOWN) {
906             LOG(ERROR) << __func__ << ": received invalid latency value: " << reply.latencyMs;
907             return Status::ABORT;
908         }
909         if (reply.xrunFrames < 0) {
910             LOG(ERROR) << __func__ << ": received invalid xrunFrames value: " << reply.xrunFrames;
911             return Status::ABORT;
912         }
913         if (std::find(enum_range<StreamDescriptor::State>().begin(),
914                       enum_range<StreamDescriptor::State>().end(),
915                       reply.state) == enum_range<StreamDescriptor::State>().end()) {
916             LOG(ERROR) << __func__ << ": received invalid stream state: " << toString(reply.state);
917             return Status::ABORT;
918         }
919         const bool acceptedReply = getDriver()->processValidReply(reply);
920         if (const size_t readCount = getDataMQ()->availableToRead(); readCount > 0) {
921             if (readDataFromMQ(readCount)) {
922                 goto checkAcceptedReply;
923             }
924             LOG(ERROR) << __func__ << ": reading of " << readCount << " data bytes from MQ failed";
925             return Status::ABORT;
926         }  // readCount == 0
927     checkAcceptedReply:
928         if (acceptedReply) {
929             return Status::CONTINUE;
930         }
931         LOG(ERROR) << __func__ << ": unacceptable reply: " << reply.toString();
932         return Status::ABORT;
933     }
934 };
935 using StreamReader = StreamWorker<StreamReaderLogic>;
936 
937 class StreamWriterLogic : public StreamCommonLogic {
938   public:
StreamWriterLogic(const StreamContext & context,StreamLogicDriver * driver,StreamEventReceiver * eventReceiver)939     StreamWriterLogic(const StreamContext& context, StreamLogicDriver* driver,
940                       StreamEventReceiver* eventReceiver)
941         : StreamCommonLogic(context, driver, eventReceiver) {}
942 
943   protected:
cycle()944     Status cycle() override {
945         if (getDriver()->done()) {
946             LOG(DEBUG) << __func__ << ": clean exit";
947             return Status::EXIT;
948         }
949         int actualSize = 0;
950         StreamDescriptor::Command command;
951         if (auto maybeCommand = maybeGetNextCommand(&actualSize); maybeCommand.has_value()) {
952             command = std::move(maybeCommand.value());
953         } else {
954             LOG(ERROR) << __func__ << ": no next command";
955             return Status::ABORT;
956         }
957         if (actualSize != 0 && !writeDataToMQ()) {
958             return Status::ABORT;
959         }
960         LOG(DEBUG) << "Writing command: " << command.toString();
961         if (!getCommandMQ()->writeBlocking(&command, 1)) {
962             LOG(ERROR) << __func__ << ": writing of command into MQ failed";
963             return Status::ABORT;
964         }
965         StreamDescriptor::Reply reply{};
966         LOG(DEBUG) << "Reading reply...";
967         if (!getReplyMQ()->readBlocking(&reply, 1)) {
968             LOG(ERROR) << __func__ << ": reading of reply from MQ failed";
969             return Status::ABORT;
970         }
971         LOG(DEBUG) << "Reply received: " << reply.toString();
972         if (getDriver()->interceptRawReply(reply)) {
973             return Status::CONTINUE;
974         }
975         if (reply.status != STATUS_OK) {
976             LOG(ERROR) << __func__ << ": received error status: " << statusToString(reply.status);
977             return Status::ABORT;
978         }
979         if (reply.fmqByteCount < 0 ||
980             (command.getTag() == StreamDescriptor::Command::Tag::burst &&
981              reply.fmqByteCount > command.get<StreamDescriptor::Command::Tag::burst>())) {
982             LOG(ERROR) << __func__
983                        << ": received invalid byte count in the reply: " << reply.fmqByteCount;
984             return Status::ABORT;
985         }
986         if (getDataMQ()->availableToWrite() != getDataMQ()->getQuantumCount()) {
987             LOG(ERROR) << __func__ << ": the HAL module did not consume all data from the data MQ: "
988                        << "available to write " << getDataMQ()->availableToWrite()
989                        << ", total size: " << getDataMQ()->getQuantumCount();
990             return Status::ABORT;
991         }
992         if (reply.latencyMs < 0 && reply.latencyMs != StreamDescriptor::LATENCY_UNKNOWN) {
993             LOG(ERROR) << __func__ << ": received invalid latency value: " << reply.latencyMs;
994             return Status::ABORT;
995         }
996         if (reply.xrunFrames < 0) {
997             LOG(ERROR) << __func__ << ": received invalid xrunFrames value: " << reply.xrunFrames;
998             return Status::ABORT;
999         }
1000         if (std::find(enum_range<StreamDescriptor::State>().begin(),
1001                       enum_range<StreamDescriptor::State>().end(),
1002                       reply.state) == enum_range<StreamDescriptor::State>().end()) {
1003             LOG(ERROR) << __func__ << ": received invalid stream state: " << toString(reply.state);
1004             return Status::ABORT;
1005         }
1006         if (getDriver()->processValidReply(reply)) {
1007             return Status::CONTINUE;
1008         }
1009         LOG(ERROR) << __func__ << ": unacceptable reply: " << reply.toString();
1010         return Status::ABORT;
1011     }
1012 };
1013 using StreamWriter = StreamWorker<StreamWriterLogic>;
1014 
1015 class DefaultStreamCallback : public ::aidl::android::hardware::audio::core::BnStreamCallback,
1016                               public StreamEventReceiver {
onTransferReady()1017     ndk::ScopedAStatus onTransferReady() override {
1018         LOG(DEBUG) << __func__;
1019         putLastEvent(Event::TransferReady);
1020         return ndk::ScopedAStatus::ok();
1021     }
onError()1022     ndk::ScopedAStatus onError() override {
1023         LOG(DEBUG) << __func__;
1024         putLastEvent(Event::Error);
1025         return ndk::ScopedAStatus::ok();
1026     }
onDrainReady()1027     ndk::ScopedAStatus onDrainReady() override {
1028         LOG(DEBUG) << __func__;
1029         putLastEvent(Event::DrainReady);
1030         return ndk::ScopedAStatus::ok();
1031     }
1032 
1033   public:
1034     // To avoid timing out the whole test suite in case no event is received
1035     // from the HAL, use a local timeout for event waiting.
1036     static constexpr auto kEventTimeoutMs = std::chrono::milliseconds(1000);
1037 
getEventReceiver()1038     StreamEventReceiver* getEventReceiver() { return this; }
getLastEvent() const1039     std::tuple<int, Event> getLastEvent() const override {
1040         std::lock_guard l(mLock);
1041         return getLastEvent_l();
1042     }
waitForEvent(int clientEventSeq)1043     std::tuple<int, Event> waitForEvent(int clientEventSeq) override {
1044         std::unique_lock l(mLock);
1045         android::base::ScopedLockAssertion lock_assertion(mLock);
1046         LOG(DEBUG) << __func__ << ": client " << clientEventSeq << ", last " << mLastEventSeq;
1047         if (mCv.wait_for(l, kEventTimeoutMs, [&]() {
1048                 android::base::ScopedLockAssertion lock_assertion(mLock);
1049                 return clientEventSeq < mLastEventSeq;
1050             })) {
1051         } else {
1052             LOG(WARNING) << __func__ << ": timed out waiting for an event";
1053             putLastEvent_l(Event::None);
1054         }
1055         return getLastEvent_l();
1056     }
1057 
1058   private:
getLastEvent_l() const1059     std::tuple<int, Event> getLastEvent_l() const REQUIRES(mLock) {
1060         return std::make_tuple(mLastEventSeq, mLastEvent);
1061     }
putLastEvent(Event event)1062     void putLastEvent(Event event) {
1063         {
1064             std::lock_guard l(mLock);
1065             putLastEvent_l(event);
1066         }
1067         mCv.notify_one();
1068     }
putLastEvent_l(Event event)1069     void putLastEvent_l(Event event) REQUIRES(mLock) {
1070         mLastEventSeq++;
1071         mLastEvent = event;
1072     }
1073 
1074     mutable std::mutex mLock;
1075     std::condition_variable mCv;
1076     int mLastEventSeq GUARDED_BY(mLock) = kEventSeqInit;
1077     Event mLastEvent GUARDED_BY(mLock) = Event::None;
1078 };
1079 
1080 template <typename T>
1081 struct IOTraits {
1082     static constexpr bool is_input = std::is_same_v<T, IStreamIn>;
1083     using Worker = std::conditional_t<is_input, StreamReader, StreamWriter>;
1084 };
1085 
1086 template <typename Stream>
1087 class WithStream {
1088   public:
callClose(std::shared_ptr<Stream> stream)1089     static ndk::ScopedAStatus callClose(std::shared_ptr<Stream> stream) {
1090         std::shared_ptr<IStreamCommon> common;
1091         ndk::ScopedAStatus status = stream->getStreamCommon(&common);
1092         if (!status.isOk()) return status;
1093         status = common->prepareToClose();
1094         if (!status.isOk()) return status;
1095         return common->close();
1096     }
1097 
1098     WithStream() = default;
WithStream(const AudioPortConfig & portConfig)1099     explicit WithStream(const AudioPortConfig& portConfig) : mPortConfig(portConfig) {}
1100     WithStream(const WithStream&) = delete;
1101     WithStream& operator=(const WithStream&) = delete;
~WithStream()1102     ~WithStream() {
1103         if (mStream != nullptr) {
1104             mContext.reset();
1105             EXPECT_IS_OK(callClose(mStream)) << "port config id " << getPortId();
1106         }
1107     }
SetUpPortConfig(IModule * module)1108     void SetUpPortConfig(IModule* module) { ASSERT_NO_FATAL_FAILURE(mPortConfig.SetUp(module)); }
SetUpNoChecks(IModule * module,long bufferSizeFrames)1109     ScopedAStatus SetUpNoChecks(IModule* module, long bufferSizeFrames) {
1110         return SetUpNoChecks(module, mPortConfig.get(), bufferSizeFrames);
1111     }
1112     ScopedAStatus SetUpNoChecks(IModule* module, const AudioPortConfig& portConfig,
1113                                 long bufferSizeFrames);
SetUp(IModule * module,long bufferSizeFrames)1114     void SetUp(IModule* module, long bufferSizeFrames) {
1115         ASSERT_NO_FATAL_FAILURE(SetUpPortConfig(module));
1116         ASSERT_IS_OK(SetUpNoChecks(module, bufferSizeFrames)) << "port config id " << getPortId();
1117         ASSERT_NE(nullptr, mStream) << "port config id " << getPortId();
1118         EXPECT_GE(mDescriptor.bufferSizeFrames, bufferSizeFrames)
1119                 << "actual buffer size must be no less than requested";
1120         mContext.emplace(mDescriptor);
1121         ASSERT_NO_FATAL_FAILURE(mContext.value().checkIsValid());
1122     }
get() const1123     Stream* get() const { return mStream.get(); }
getContext() const1124     const StreamContext* getContext() const { return mContext ? &(mContext.value()) : nullptr; }
getEventReceiver()1125     StreamEventReceiver* getEventReceiver() { return mStreamCallback->getEventReceiver(); }
getSharedPointer() const1126     std::shared_ptr<Stream> getSharedPointer() const { return mStream; }
getPortConfig() const1127     const AudioPortConfig& getPortConfig() const { return mPortConfig.get(); }
getPortId() const1128     int32_t getPortId() const { return mPortConfig.getId(); }
1129 
1130   private:
1131     WithAudioPortConfig mPortConfig;
1132     std::shared_ptr<Stream> mStream;
1133     StreamDescriptor mDescriptor;
1134     std::optional<StreamContext> mContext;
1135     std::shared_ptr<DefaultStreamCallback> mStreamCallback;
1136 };
1137 
GenerateSinkMetadata(const AudioPortConfig & portConfig)1138 SinkMetadata GenerateSinkMetadata(const AudioPortConfig& portConfig) {
1139     RecordTrackMetadata trackMeta;
1140     trackMeta.source = AudioSource::MIC;
1141     trackMeta.gain = 1.0;
1142     trackMeta.channelMask = portConfig.channelMask.value();
1143     SinkMetadata metadata;
1144     metadata.tracks.push_back(trackMeta);
1145     return metadata;
1146 }
1147 
1148 template <>
SetUpNoChecks(IModule * module,const AudioPortConfig & portConfig,long bufferSizeFrames)1149 ScopedAStatus WithStream<IStreamIn>::SetUpNoChecks(IModule* module,
1150                                                    const AudioPortConfig& portConfig,
1151                                                    long bufferSizeFrames) {
1152     aidl::android::hardware::audio::core::IModule::OpenInputStreamArguments args;
1153     args.portConfigId = portConfig.id;
1154     args.sinkMetadata = GenerateSinkMetadata(portConfig);
1155     args.bufferSizeFrames = bufferSizeFrames;
1156     auto callback = ndk::SharedRefBase::make<DefaultStreamCallback>();
1157     // TODO: Uncomment when support for asynchronous input is implemented.
1158     // args.callback = callback;
1159     aidl::android::hardware::audio::core::IModule::OpenInputStreamReturn ret;
1160     ScopedAStatus status = module->openInputStream(args, &ret);
1161     if (status.isOk()) {
1162         mStream = std::move(ret.stream);
1163         mDescriptor = std::move(ret.desc);
1164         mStreamCallback = std::move(callback);
1165     }
1166     return status;
1167 }
1168 
GenerateSourceMetadata(const AudioPortConfig & portConfig)1169 SourceMetadata GenerateSourceMetadata(const AudioPortConfig& portConfig) {
1170     PlaybackTrackMetadata trackMeta;
1171     trackMeta.usage = AudioUsage::MEDIA;
1172     trackMeta.contentType = AudioContentType::MUSIC;
1173     trackMeta.gain = 1.0;
1174     trackMeta.channelMask = portConfig.channelMask.value();
1175     SourceMetadata metadata;
1176     metadata.tracks.push_back(trackMeta);
1177     return metadata;
1178 }
1179 
1180 template <>
SetUpNoChecks(IModule * module,const AudioPortConfig & portConfig,long bufferSizeFrames)1181 ScopedAStatus WithStream<IStreamOut>::SetUpNoChecks(IModule* module,
1182                                                     const AudioPortConfig& portConfig,
1183                                                     long bufferSizeFrames) {
1184     aidl::android::hardware::audio::core::IModule::OpenOutputStreamArguments args;
1185     args.portConfigId = portConfig.id;
1186     args.sourceMetadata = GenerateSourceMetadata(portConfig);
1187     args.offloadInfo = ModuleConfig::generateOffloadInfoIfNeeded(portConfig);
1188     args.bufferSizeFrames = bufferSizeFrames;
1189     auto callback = ndk::SharedRefBase::make<DefaultStreamCallback>();
1190     args.callback = callback;
1191     aidl::android::hardware::audio::core::IModule::OpenOutputStreamReturn ret;
1192     ScopedAStatus status = module->openOutputStream(args, &ret);
1193     if (status.isOk()) {
1194         mStream = std::move(ret.stream);
1195         mDescriptor = std::move(ret.desc);
1196         mStreamCallback = std::move(callback);
1197     }
1198     return status;
1199 }
1200 
1201 class WithAudioPatch {
1202   public:
1203     WithAudioPatch() = default;
WithAudioPatch(const AudioPortConfig & srcPortConfig,const AudioPortConfig & sinkPortConfig)1204     WithAudioPatch(const AudioPortConfig& srcPortConfig, const AudioPortConfig& sinkPortConfig)
1205         : mSrcPortConfig(srcPortConfig), mSinkPortConfig(sinkPortConfig) {}
WithAudioPatch(bool sinkIsCfg1,const AudioPortConfig & portConfig1,const AudioPortConfig & portConfig2)1206     WithAudioPatch(bool sinkIsCfg1, const AudioPortConfig& portConfig1,
1207                    const AudioPortConfig& portConfig2)
1208         : mSrcPortConfig(sinkIsCfg1 ? portConfig2 : portConfig1),
1209           mSinkPortConfig(sinkIsCfg1 ? portConfig1 : portConfig2) {}
1210     WithAudioPatch(const WithAudioPatch&) = delete;
1211     WithAudioPatch& operator=(const WithAudioPatch&) = delete;
~WithAudioPatch()1212     ~WithAudioPatch() {
1213         if (mModule != nullptr && mPatch.id != 0) {
1214             EXPECT_IS_OK(mModule->resetAudioPatch(mPatch.id)) << "patch id " << getId();
1215         }
1216     }
SetUpPortConfigs(IModule * module)1217     void SetUpPortConfigs(IModule* module) {
1218         ASSERT_NO_FATAL_FAILURE(mSrcPortConfig.SetUp(module));
1219         ASSERT_NO_FATAL_FAILURE(mSinkPortConfig.SetUp(module));
1220     }
SetUpNoChecks(IModule * module)1221     ScopedAStatus SetUpNoChecks(IModule* module) {
1222         mModule = module;
1223         mPatch.sourcePortConfigIds = std::vector<int32_t>{mSrcPortConfig.getId()};
1224         mPatch.sinkPortConfigIds = std::vector<int32_t>{mSinkPortConfig.getId()};
1225         return mModule->setAudioPatch(mPatch, &mPatch);
1226     }
SetUp(IModule * module)1227     void SetUp(IModule* module) {
1228         ASSERT_NO_FATAL_FAILURE(SetUpPortConfigs(module));
1229         ASSERT_IS_OK(SetUpNoChecks(module)) << "source port config id " << mSrcPortConfig.getId()
1230                                             << "; sink port config id " << mSinkPortConfig.getId();
1231         EXPECT_GT(mPatch.minimumStreamBufferSizeFrames, 0) << "patch id " << getId();
1232         for (auto latencyMs : mPatch.latenciesMs) {
1233             EXPECT_GT(latencyMs, 0) << "patch id " << getId();
1234         }
1235     }
getId() const1236     int32_t getId() const { return mPatch.id; }
get() const1237     const AudioPatch& get() const { return mPatch; }
getSinkPortConfig() const1238     const AudioPortConfig& getSinkPortConfig() const { return mSinkPortConfig.get(); }
getSrcPortConfig() const1239     const AudioPortConfig& getSrcPortConfig() const { return mSrcPortConfig.get(); }
getPortConfig(bool getSink) const1240     const AudioPortConfig& getPortConfig(bool getSink) const {
1241         return getSink ? getSinkPortConfig() : getSrcPortConfig();
1242     }
1243 
1244   private:
1245     WithAudioPortConfig mSrcPortConfig;
1246     WithAudioPortConfig mSinkPortConfig;
1247     IModule* mModule = nullptr;
1248     AudioPatch mPatch;
1249 };
1250 
TEST_P(AudioCoreModule,Published)1251 TEST_P(AudioCoreModule, Published) {
1252     // SetUp must complete with no failures.
1253 }
1254 
TEST_P(AudioCoreModule,CanBeRestarted)1255 TEST_P(AudioCoreModule, CanBeRestarted) {
1256     ASSERT_NO_FATAL_FAILURE(RestartService());
1257 }
1258 
TEST_P(AudioCoreModule,PortIdsAreUnique)1259 TEST_P(AudioCoreModule, PortIdsAreUnique) {
1260     std::set<int32_t> portIds;
1261     ASSERT_NO_FATAL_FAILURE(GetAllPortIds(&portIds));
1262 }
1263 
TEST_P(AudioCoreModule,GetAudioPortsIsStable)1264 TEST_P(AudioCoreModule, GetAudioPortsIsStable) {
1265     std::vector<AudioPort> ports1;
1266     ASSERT_IS_OK(module->getAudioPorts(&ports1));
1267     std::vector<AudioPort> ports2;
1268     ASSERT_IS_OK(module->getAudioPorts(&ports2));
1269     ASSERT_EQ(ports1.size(), ports2.size())
1270             << "Sizes of audio port arrays do not match across consequent calls to getAudioPorts";
1271     std::sort(ports1.begin(), ports1.end());
1272     std::sort(ports2.begin(), ports2.end());
1273     EXPECT_EQ(ports1, ports2);
1274 }
1275 
TEST_P(AudioCoreModule,GetAudioRoutesIsStable)1276 TEST_P(AudioCoreModule, GetAudioRoutesIsStable) {
1277     std::vector<AudioRoute> routes1;
1278     ASSERT_IS_OK(module->getAudioRoutes(&routes1));
1279     std::vector<AudioRoute> routes2;
1280     ASSERT_IS_OK(module->getAudioRoutes(&routes2));
1281     ASSERT_EQ(routes1.size(), routes2.size())
1282             << "Sizes of audio route arrays do not match across consequent calls to getAudioRoutes";
1283     std::sort(routes1.begin(), routes1.end());
1284     std::sort(routes2.begin(), routes2.end());
1285     EXPECT_EQ(routes1, routes2);
1286 }
1287 
TEST_P(AudioCoreModule,GetAudioRoutesAreValid)1288 TEST_P(AudioCoreModule, GetAudioRoutesAreValid) {
1289     std::vector<AudioRoute> routes;
1290     ASSERT_IS_OK(module->getAudioRoutes(&routes));
1291     for (const auto& route : routes) {
1292         std::set<int32_t> sources(route.sourcePortIds.begin(), route.sourcePortIds.end());
1293         EXPECT_NE(0UL, sources.size())
1294                 << "empty audio port sinks in the audio route: " << route.toString();
1295         EXPECT_EQ(sources.size(), route.sourcePortIds.size())
1296                 << "IDs of audio port sinks are not unique in the audio route: "
1297                 << route.toString();
1298     }
1299 }
1300 
TEST_P(AudioCoreModule,GetAudioRoutesPortIdsAreValid)1301 TEST_P(AudioCoreModule, GetAudioRoutesPortIdsAreValid) {
1302     std::set<int32_t> portIds;
1303     ASSERT_NO_FATAL_FAILURE(GetAllPortIds(&portIds));
1304     std::vector<AudioRoute> routes;
1305     ASSERT_IS_OK(module->getAudioRoutes(&routes));
1306     for (const auto& route : routes) {
1307         EXPECT_EQ(1UL, portIds.count(route.sinkPortId))
1308                 << route.sinkPortId << " sink port id is unknown";
1309         for (const auto& source : route.sourcePortIds) {
1310             EXPECT_EQ(1UL, portIds.count(source)) << source << " source port id is unknown";
1311         }
1312     }
1313 }
1314 
TEST_P(AudioCoreModule,GetAudioRoutesForAudioPort)1315 TEST_P(AudioCoreModule, GetAudioRoutesForAudioPort) {
1316     std::set<int32_t> portIds;
1317     ASSERT_NO_FATAL_FAILURE(GetAllPortIds(&portIds));
1318     if (portIds.empty()) {
1319         GTEST_SKIP() << "No ports in the module.";
1320     }
1321     for (const auto portId : portIds) {
1322         std::vector<AudioRoute> routes;
1323         EXPECT_IS_OK(module->getAudioRoutesForAudioPort(portId, &routes));
1324         for (const auto& r : routes) {
1325             if (r.sinkPortId != portId) {
1326                 const auto& srcs = r.sourcePortIds;
1327                 EXPECT_TRUE(std::find(srcs.begin(), srcs.end(), portId) != srcs.end())
1328                         << " port ID " << portId << " does not used by the route " << r.toString();
1329             }
1330         }
1331     }
1332     for (const auto portId : GetNonExistentIds(portIds)) {
1333         std::vector<AudioRoute> routes;
1334         EXPECT_STATUS(EX_ILLEGAL_ARGUMENT, module->getAudioRoutesForAudioPort(portId, &routes))
1335                 << "port ID " << portId;
1336     }
1337 }
1338 
TEST_P(AudioCoreModule,CheckDevicePorts)1339 TEST_P(AudioCoreModule, CheckDevicePorts) {
1340     std::vector<AudioPort> ports;
1341     ASSERT_IS_OK(module->getAudioPorts(&ports));
1342     std::optional<int32_t> defaultOutput, defaultInput;
1343     std::set<AudioDevice> inputs, outputs;
1344     const int defaultDeviceFlag = 1 << AudioPortDeviceExt::FLAG_INDEX_DEFAULT_DEVICE;
1345     for (const auto& port : ports) {
1346         if (port.ext.getTag() != AudioPortExt::Tag::device) continue;
1347         const auto& devicePort = port.ext.get<AudioPortExt::Tag::device>();
1348         EXPECT_NE(AudioDeviceType::NONE, devicePort.device.type.type);
1349         EXPECT_NE(AudioDeviceType::IN_DEFAULT, devicePort.device.type.type);
1350         EXPECT_NE(AudioDeviceType::OUT_DEFAULT, devicePort.device.type.type);
1351         if (devicePort.device.type.type > AudioDeviceType::IN_DEFAULT &&
1352             devicePort.device.type.type < AudioDeviceType::OUT_DEFAULT) {
1353             EXPECT_EQ(AudioIoFlags::Tag::input, port.flags.getTag());
1354         } else if (devicePort.device.type.type > AudioDeviceType::OUT_DEFAULT) {
1355             EXPECT_EQ(AudioIoFlags::Tag::output, port.flags.getTag());
1356         }
1357         EXPECT_FALSE((devicePort.flags & defaultDeviceFlag) != 0 &&
1358                      !devicePort.device.type.connection.empty())
1359                 << "Device port " << port.id
1360                 << " must be permanently attached to be set as default";
1361         if ((devicePort.flags & defaultDeviceFlag) != 0) {
1362             if (port.flags.getTag() == AudioIoFlags::Tag::output) {
1363                 EXPECT_FALSE(defaultOutput.has_value())
1364                         << "At least two output device ports are declared as default: "
1365                         << defaultOutput.value() << " and " << port.id;
1366                 defaultOutput = port.id;
1367                 EXPECT_EQ(0UL, outputs.count(devicePort.device))
1368                         << "Non-unique output device: " << devicePort.device.toString();
1369                 outputs.insert(devicePort.device);
1370             } else if (port.flags.getTag() == AudioIoFlags::Tag::input) {
1371                 EXPECT_FALSE(defaultInput.has_value())
1372                         << "At least two input device ports are declared as default: "
1373                         << defaultInput.value() << " and " << port.id;
1374                 defaultInput = port.id;
1375                 EXPECT_EQ(0UL, inputs.count(devicePort.device))
1376                         << "Non-unique input device: " << devicePort.device.toString();
1377                 inputs.insert(devicePort.device);
1378             } else {
1379                 FAIL() << "Invalid AudioIoFlags Tag: " << toString(port.flags.getTag());
1380             }
1381         }
1382     }
1383 }
1384 
TEST_P(AudioCoreModule,CheckMixPorts)1385 TEST_P(AudioCoreModule, CheckMixPorts) {
1386     std::vector<AudioPort> ports;
1387     ASSERT_IS_OK(module->getAudioPorts(&ports));
1388     std::optional<int32_t> primaryMixPort;
1389     for (const auto& port : ports) {
1390         if (port.ext.getTag() != AudioPortExt::Tag::mix) continue;
1391         const auto& mixPort = port.ext.get<AudioPortExt::Tag::mix>();
1392         if (port.flags.getTag() == AudioIoFlags::Tag::output &&
1393             isBitPositionFlagSet(port.flags.get<AudioIoFlags::Tag::output>(),
1394                                  AudioOutputFlags::PRIMARY)) {
1395             EXPECT_FALSE(primaryMixPort.has_value())
1396                     << "At least two mix ports have PRIMARY flag set: " << primaryMixPort.value()
1397                     << " and " << port.id;
1398             primaryMixPort = port.id;
1399             EXPECT_GE(mixPort.maxOpenStreamCount, 0)
1400                     << "Primary mix port " << port.id << " can not have maxOpenStreamCount "
1401                     << mixPort.maxOpenStreamCount;
1402         }
1403     }
1404 }
1405 
TEST_P(AudioCoreModule,GetAudioPort)1406 TEST_P(AudioCoreModule, GetAudioPort) {
1407     std::set<int32_t> portIds;
1408     ASSERT_NO_FATAL_FAILURE(GetAllPortIds(&portIds));
1409     if (portIds.empty()) {
1410         GTEST_SKIP() << "No ports in the module.";
1411     }
1412     for (const auto portId : portIds) {
1413         AudioPort port;
1414         EXPECT_IS_OK(module->getAudioPort(portId, &port));
1415         EXPECT_EQ(portId, port.id);
1416     }
1417     for (const auto portId : GetNonExistentIds(portIds)) {
1418         AudioPort port;
1419         EXPECT_STATUS(EX_ILLEGAL_ARGUMENT, module->getAudioPort(portId, &port))
1420                 << "port ID " << portId;
1421     }
1422 }
1423 
TEST_P(AudioCoreModule,SetUpModuleConfig)1424 TEST_P(AudioCoreModule, SetUpModuleConfig) {
1425     ASSERT_NO_FATAL_FAILURE(SetUpModuleConfig());
1426     // Send the module config to logcat to facilitate failures investigation.
1427     LOG(INFO) << "SetUpModuleConfig: " << moduleConfig->toString();
1428 }
1429 
1430 // Verify that HAL module reports for a connected device port at least one non-dynamic profile,
1431 // that is, a profile with actual supported configuration.
1432 // Note: This test relies on simulation of external device connections by the HAL module.
TEST_P(AudioCoreModule,GetAudioPortWithExternalDevices)1433 TEST_P(AudioCoreModule, GetAudioPortWithExternalDevices) {
1434     ASSERT_NO_FATAL_FAILURE(SetUpModuleConfig());
1435     std::vector<AudioPort> ports = moduleConfig->getExternalDevicePorts();
1436     if (ports.empty()) {
1437         GTEST_SKIP() << "No external devices in the module.";
1438     }
1439     for (const auto& port : ports) {
1440         AudioPort portWithData = GenerateUniqueDeviceAddress(port);
1441         WithDevicePortConnectedState portConnected(portWithData);
1442         ASSERT_NO_FATAL_FAILURE(portConnected.SetUp(module.get(), moduleConfig.get()));
1443         const int32_t connectedPortId = portConnected.getId();
1444         ASSERT_NE(portWithData.id, connectedPortId);
1445         ASSERT_EQ(portWithData.ext.getTag(), portConnected.get().ext.getTag());
1446         EXPECT_EQ(portWithData.ext.get<AudioPortExt::Tag::device>().device,
1447                   portConnected.get().ext.get<AudioPortExt::Tag::device>().device);
1448         // Verify that 'getAudioPort' and 'getAudioPorts' return the same connected port.
1449         AudioPort connectedPort;
1450         EXPECT_IS_OK(module->getAudioPort(connectedPortId, &connectedPort))
1451                 << "port ID " << connectedPortId;
1452         EXPECT_EQ(portConnected.get(), connectedPort);
1453         const auto& portProfiles = connectedPort.profiles;
1454         EXPECT_NE(0UL, portProfiles.size())
1455                 << "Connected port has no profiles: " << connectedPort.toString();
1456         const auto dynamicProfileIt =
1457                 std::find_if(portProfiles.begin(), portProfiles.end(), [](const auto& profile) {
1458                     return profile.format.type == AudioFormatType::DEFAULT;
1459                 });
1460         EXPECT_EQ(portProfiles.end(), dynamicProfileIt) << "Connected port contains dynamic "
1461                                                         << "profiles: " << connectedPort.toString();
1462 
1463         std::vector<AudioPort> allPorts;
1464         ASSERT_IS_OK(module->getAudioPorts(&allPorts));
1465         const auto allPortsIt = findById(allPorts, connectedPortId);
1466         EXPECT_NE(allPorts.end(), allPortsIt);
1467         if (allPortsIt != allPorts.end()) {
1468             EXPECT_EQ(portConnected.get(), *allPortsIt);
1469         }
1470     }
1471 }
1472 
TEST_P(AudioCoreModule,OpenStreamInvalidPortConfigId)1473 TEST_P(AudioCoreModule, OpenStreamInvalidPortConfigId) {
1474     std::set<int32_t> portConfigIds;
1475     ASSERT_NO_FATAL_FAILURE(GetAllPortConfigIds(&portConfigIds));
1476     for (const auto portConfigId : GetNonExistentIds(portConfigIds)) {
1477         {
1478             aidl::android::hardware::audio::core::IModule::OpenInputStreamArguments args;
1479             args.portConfigId = portConfigId;
1480             args.bufferSizeFrames = kDefaultBufferSizeFrames;
1481             aidl::android::hardware::audio::core::IModule::OpenInputStreamReturn ret;
1482             EXPECT_STATUS(EX_ILLEGAL_ARGUMENT, module->openInputStream(args, &ret))
1483                     << "port config ID " << portConfigId;
1484             EXPECT_EQ(nullptr, ret.stream);
1485         }
1486         {
1487             aidl::android::hardware::audio::core::IModule::OpenOutputStreamArguments args;
1488             args.portConfigId = portConfigId;
1489             args.bufferSizeFrames = kDefaultBufferSizeFrames;
1490             aidl::android::hardware::audio::core::IModule::OpenOutputStreamReturn ret;
1491             EXPECT_STATUS(EX_ILLEGAL_ARGUMENT, module->openOutputStream(args, &ret))
1492                     << "port config ID " << portConfigId;
1493             EXPECT_EQ(nullptr, ret.stream);
1494         }
1495     }
1496 }
1497 
TEST_P(AudioCoreModule,PortConfigIdsAreUnique)1498 TEST_P(AudioCoreModule, PortConfigIdsAreUnique) {
1499     std::set<int32_t> portConfigIds;
1500     ASSERT_NO_FATAL_FAILURE(GetAllPortConfigIds(&portConfigIds));
1501 }
1502 
TEST_P(AudioCoreModule,PortConfigPortIdsAreValid)1503 TEST_P(AudioCoreModule, PortConfigPortIdsAreValid) {
1504     std::set<int32_t> portIds;
1505     ASSERT_NO_FATAL_FAILURE(GetAllPortIds(&portIds));
1506     std::vector<AudioPortConfig> portConfigs;
1507     ASSERT_IS_OK(module->getAudioPortConfigs(&portConfigs));
1508     for (const auto& config : portConfigs) {
1509         EXPECT_EQ(1UL, portIds.count(config.portId))
1510                 << config.portId << " port id is unknown, config id " << config.id;
1511     }
1512 }
1513 
TEST_P(AudioCoreModule,ResetAudioPortConfigInvalidId)1514 TEST_P(AudioCoreModule, ResetAudioPortConfigInvalidId) {
1515     std::set<int32_t> portConfigIds;
1516     ASSERT_NO_FATAL_FAILURE(GetAllPortConfigIds(&portConfigIds));
1517     for (const auto portConfigId : GetNonExistentIds(portConfigIds)) {
1518         EXPECT_STATUS(EX_ILLEGAL_ARGUMENT, module->resetAudioPortConfig(portConfigId))
1519                 << "port config ID " << portConfigId;
1520     }
1521 }
1522 
1523 // Verify that for the audio port configs provided by the HAL after init, resetting
1524 // the config does not delete it, but brings it back to the initial config.
TEST_P(AudioCoreModule,ResetAudioPortConfigToInitialValue)1525 TEST_P(AudioCoreModule, ResetAudioPortConfigToInitialValue) {
1526     std::vector<AudioPortConfig> portConfigsBefore;
1527     ASSERT_IS_OK(module->getAudioPortConfigs(&portConfigsBefore));
1528     // TODO: Change port configs according to port profiles.
1529     for (const auto& c : portConfigsBefore) {
1530         EXPECT_IS_OK(module->resetAudioPortConfig(c.id)) << "port config ID " << c.id;
1531     }
1532     std::vector<AudioPortConfig> portConfigsAfter;
1533     ASSERT_IS_OK(module->getAudioPortConfigs(&portConfigsAfter));
1534     for (const auto& c : portConfigsBefore) {
1535         auto afterIt = findById<AudioPortConfig>(portConfigsAfter, c.id);
1536         EXPECT_NE(portConfigsAfter.end(), afterIt)
1537                 << " port config ID " << c.id << " was removed by reset";
1538         if (afterIt != portConfigsAfter.end()) {
1539             EXPECT_EQ(c, *afterIt);
1540         }
1541     }
1542 }
1543 
TEST_P(AudioCoreModule,SetAudioPortConfigSuggestedConfig)1544 TEST_P(AudioCoreModule, SetAudioPortConfigSuggestedConfig) {
1545     ASSERT_NO_FATAL_FAILURE(SetUpModuleConfig());
1546     auto srcMixPort = moduleConfig->getSourceMixPortForConnectedDevice();
1547     if (!srcMixPort.has_value()) {
1548         GTEST_SKIP() << "No mix port for attached output devices";
1549     }
1550     AudioPortConfig portConfig;
1551     AudioPortConfig suggestedConfig;
1552     portConfig.portId = srcMixPort.value().id;
1553     const int32_t kIoHandle = 42;
1554     portConfig.ext = AudioPortMixExt{.handle = kIoHandle};
1555     {
1556         bool applied = true;
1557         ASSERT_IS_OK(module->setAudioPortConfig(portConfig, &suggestedConfig, &applied))
1558                 << "Config: " << portConfig.toString();
1559         EXPECT_FALSE(applied);
1560     }
1561     EXPECT_EQ(0, suggestedConfig.id);
1562     EXPECT_TRUE(suggestedConfig.sampleRate.has_value());
1563     EXPECT_TRUE(suggestedConfig.channelMask.has_value());
1564     EXPECT_TRUE(suggestedConfig.format.has_value());
1565     EXPECT_TRUE(suggestedConfig.flags.has_value());
1566     ASSERT_EQ(AudioPortExt::Tag::mix, suggestedConfig.ext.getTag());
1567     EXPECT_EQ(kIoHandle, suggestedConfig.ext.get<AudioPortExt::Tag::mix>().handle);
1568     WithAudioPortConfig applied(suggestedConfig);
1569     ASSERT_NO_FATAL_FAILURE(applied.SetUp(module.get()));
1570     const AudioPortConfig& appliedConfig = applied.get();
1571     EXPECT_NE(0, appliedConfig.id);
1572     ASSERT_TRUE(appliedConfig.sampleRate.has_value());
1573     EXPECT_EQ(suggestedConfig.sampleRate.value(), appliedConfig.sampleRate.value());
1574     ASSERT_TRUE(appliedConfig.channelMask.has_value());
1575     EXPECT_EQ(suggestedConfig.channelMask.value(), appliedConfig.channelMask.value());
1576     ASSERT_TRUE(appliedConfig.format.has_value());
1577     EXPECT_EQ(suggestedConfig.format.value(), appliedConfig.format.value());
1578     ASSERT_TRUE(appliedConfig.flags.has_value());
1579     EXPECT_EQ(suggestedConfig.flags.value(), appliedConfig.flags.value());
1580     ASSERT_EQ(AudioPortExt::Tag::mix, appliedConfig.ext.getTag());
1581     EXPECT_EQ(kIoHandle, appliedConfig.ext.get<AudioPortExt::Tag::mix>().handle);
1582 }
1583 
TEST_P(AudioCoreModule,SetAllAttachedDevicePortConfigs)1584 TEST_P(AudioCoreModule, SetAllAttachedDevicePortConfigs) {
1585     ASSERT_NO_FATAL_FAILURE(SetUpModuleConfig());
1586     ASSERT_NO_FATAL_FAILURE(ApplyEveryConfig(moduleConfig->getPortConfigsForAttachedDevicePorts()));
1587 }
1588 
1589 // Note: This test relies on simulation of external device connections by the HAL module.
TEST_P(AudioCoreModule,SetAllExternalDevicePortConfigs)1590 TEST_P(AudioCoreModule, SetAllExternalDevicePortConfigs) {
1591     ASSERT_NO_FATAL_FAILURE(SetUpModuleConfig());
1592     std::vector<AudioPort> ports = moduleConfig->getExternalDevicePorts();
1593     if (ports.empty()) {
1594         GTEST_SKIP() << "No external devices in the module.";
1595     }
1596     for (const auto& port : ports) {
1597         WithDevicePortConnectedState portConnected(GenerateUniqueDeviceAddress(port));
1598         ASSERT_NO_FATAL_FAILURE(portConnected.SetUp(module.get(), moduleConfig.get()));
1599         ASSERT_NO_FATAL_FAILURE(
1600                 ApplyEveryConfig(moduleConfig->getPortConfigsForDevicePort(portConnected.get())));
1601     }
1602 }
1603 
TEST_P(AudioCoreModule,SetAllStaticAudioPortConfigs)1604 TEST_P(AudioCoreModule, SetAllStaticAudioPortConfigs) {
1605     ASSERT_NO_FATAL_FAILURE(SetUpModuleConfig());
1606     ASSERT_NO_FATAL_FAILURE(ApplyEveryConfig(moduleConfig->getPortConfigsForMixPorts()));
1607 }
1608 
TEST_P(AudioCoreModule,SetAudioPortConfigInvalidPortId)1609 TEST_P(AudioCoreModule, SetAudioPortConfigInvalidPortId) {
1610     std::set<int32_t> portIds;
1611     ASSERT_NO_FATAL_FAILURE(GetAllPortIds(&portIds));
1612     for (const auto portId : GetNonExistentIds(portIds)) {
1613         AudioPortConfig portConfig, suggestedConfig;
1614         bool applied;
1615         portConfig.portId = portId;
1616         EXPECT_STATUS(EX_ILLEGAL_ARGUMENT,
1617                       module->setAudioPortConfig(portConfig, &suggestedConfig, &applied))
1618                 << "port ID " << portId;
1619         EXPECT_FALSE(suggestedConfig.format.has_value());
1620         EXPECT_FALSE(suggestedConfig.channelMask.has_value());
1621         EXPECT_FALSE(suggestedConfig.sampleRate.has_value());
1622     }
1623 }
1624 
TEST_P(AudioCoreModule,SetAudioPortConfigInvalidPortConfigId)1625 TEST_P(AudioCoreModule, SetAudioPortConfigInvalidPortConfigId) {
1626     std::set<int32_t> portConfigIds;
1627     ASSERT_NO_FATAL_FAILURE(GetAllPortConfigIds(&portConfigIds));
1628     for (const auto portConfigId : GetNonExistentIds(portConfigIds)) {
1629         AudioPortConfig portConfig, suggestedConfig;
1630         bool applied;
1631         portConfig.id = portConfigId;
1632         EXPECT_STATUS(EX_ILLEGAL_ARGUMENT,
1633                       module->setAudioPortConfig(portConfig, &suggestedConfig, &applied))
1634                 << "port config ID " << portConfigId;
1635         EXPECT_FALSE(suggestedConfig.format.has_value());
1636         EXPECT_FALSE(suggestedConfig.channelMask.has_value());
1637         EXPECT_FALSE(suggestedConfig.sampleRate.has_value());
1638     }
1639 }
1640 
TEST_P(AudioCoreModule,TryConnectMissingDevice)1641 TEST_P(AudioCoreModule, TryConnectMissingDevice) {
1642     ASSERT_NO_FATAL_FAILURE(SetUpModuleConfig());
1643     std::vector<AudioPort> ports = moduleConfig->getExternalDevicePorts();
1644     if (ports.empty()) {
1645         GTEST_SKIP() << "No external devices in the module.";
1646     }
1647     WithDebugFlags doNotSimulateConnections = WithDebugFlags::createNested(*debug);
1648     doNotSimulateConnections.flags().simulateDeviceConnections = false;
1649     ASSERT_NO_FATAL_FAILURE(doNotSimulateConnections.SetUp(module.get()));
1650     for (const auto& port : ports) {
1651         AudioPort portWithData = GenerateUniqueDeviceAddress(port), connectedPort;
1652         ScopedAStatus status = module->connectExternalDevice(portWithData, &connectedPort);
1653         EXPECT_STATUS(EX_ILLEGAL_STATE, status) << "static port " << portWithData.toString();
1654         if (status.isOk()) {
1655             EXPECT_IS_OK(module->disconnectExternalDevice(connectedPort.id))
1656                     << "when disconnecting device port ID " << connectedPort.id;
1657         }
1658     }
1659 }
1660 
TEST_P(AudioCoreModule,TryChangingConnectionSimulationMidway)1661 TEST_P(AudioCoreModule, TryChangingConnectionSimulationMidway) {
1662     ASSERT_NO_FATAL_FAILURE(SetUpModuleConfig());
1663     std::vector<AudioPort> ports = moduleConfig->getExternalDevicePorts();
1664     if (ports.empty()) {
1665         GTEST_SKIP() << "No external devices in the module.";
1666     }
1667     WithDevicePortConnectedState portConnected(GenerateUniqueDeviceAddress(*ports.begin()));
1668     ASSERT_NO_FATAL_FAILURE(portConnected.SetUp(module.get(), moduleConfig.get()));
1669     ModuleDebug midwayDebugChange = debug->flags();
1670     midwayDebugChange.simulateDeviceConnections = false;
1671     EXPECT_STATUS(EX_ILLEGAL_STATE, module->setModuleDebug(midwayDebugChange))
1672             << "when trying to disable connections simulation while having a connected device";
1673 }
1674 
TEST_P(AudioCoreModule,ConnectDisconnectExternalDeviceInvalidPorts)1675 TEST_P(AudioCoreModule, ConnectDisconnectExternalDeviceInvalidPorts) {
1676     AudioPort ignored;
1677     std::set<int32_t> portIds;
1678     ASSERT_NO_FATAL_FAILURE(GetAllPortIds(&portIds));
1679     for (const auto portId : GetNonExistentIds(portIds)) {
1680         AudioPort invalidPort;
1681         invalidPort.id = portId;
1682         EXPECT_STATUS(EX_ILLEGAL_ARGUMENT, module->connectExternalDevice(invalidPort, &ignored))
1683                 << "port ID " << portId << ", when setting CONNECTED state";
1684         EXPECT_STATUS(EX_ILLEGAL_ARGUMENT, module->disconnectExternalDevice(portId))
1685                 << "port ID " << portId << ", when setting DISCONNECTED state";
1686     }
1687 
1688     std::vector<AudioPort> ports;
1689     ASSERT_IS_OK(module->getAudioPorts(&ports));
1690     for (const auto& port : ports) {
1691         if (port.ext.getTag() != AudioPortExt::Tag::device) {
1692             EXPECT_STATUS(EX_ILLEGAL_ARGUMENT, module->connectExternalDevice(port, &ignored))
1693                     << "non-device port ID " << port.id << " when setting CONNECTED state";
1694             EXPECT_STATUS(EX_ILLEGAL_ARGUMENT, module->disconnectExternalDevice(port.id))
1695                     << "non-device port ID " << port.id << " when setting DISCONNECTED state";
1696         } else {
1697             const auto& devicePort = port.ext.get<AudioPortExt::Tag::device>();
1698             if (devicePort.device.type.connection.empty()) {
1699                 EXPECT_STATUS(EX_ILLEGAL_ARGUMENT, module->connectExternalDevice(port, &ignored))
1700                         << "for a permanently attached device port ID " << port.id
1701                         << " when setting CONNECTED state";
1702                 EXPECT_STATUS(EX_ILLEGAL_ARGUMENT, module->disconnectExternalDevice(port.id))
1703                         << "for a permanently attached device port ID " << port.id
1704                         << " when setting DISCONNECTED state";
1705             }
1706         }
1707     }
1708 }
1709 
1710 // Note: This test relies on simulation of external device connections by the HAL module.
TEST_P(AudioCoreModule,ConnectDisconnectExternalDeviceTwice)1711 TEST_P(AudioCoreModule, ConnectDisconnectExternalDeviceTwice) {
1712     ASSERT_NO_FATAL_FAILURE(SetUpModuleConfig());
1713     AudioPort ignored;
1714     std::vector<AudioPort> ports = moduleConfig->getExternalDevicePorts();
1715     if (ports.empty()) {
1716         GTEST_SKIP() << "No external devices in the module.";
1717     }
1718     for (const auto& port : ports) {
1719         EXPECT_STATUS(EX_ILLEGAL_ARGUMENT, module->disconnectExternalDevice(port.id))
1720                 << "when disconnecting already disconnected device port ID " << port.id;
1721         AudioPort portWithData = GenerateUniqueDeviceAddress(port);
1722         WithDevicePortConnectedState portConnected(portWithData);
1723         ASSERT_NO_FATAL_FAILURE(portConnected.SetUp(module.get(), moduleConfig.get()));
1724         EXPECT_STATUS(EX_ILLEGAL_ARGUMENT,
1725                       module->connectExternalDevice(portConnected.get(), &ignored))
1726                 << "when trying to connect a connected device port "
1727                 << portConnected.get().toString();
1728         EXPECT_STATUS(EX_ILLEGAL_STATE, module->connectExternalDevice(portWithData, &ignored))
1729                 << "when connecting again the external device "
1730                 << portWithData.ext.get<AudioPortExt::Tag::device>().device.toString()
1731                 << "; Returned connected port " << ignored.toString() << " for template "
1732                 << portWithData.toString();
1733     }
1734 }
1735 
1736 // Note: This test relies on simulation of external device connections by the HAL module.
TEST_P(AudioCoreModule,DisconnectExternalDeviceNonResetPortConfig)1737 TEST_P(AudioCoreModule, DisconnectExternalDeviceNonResetPortConfig) {
1738     ASSERT_NO_FATAL_FAILURE(SetUpModuleConfig());
1739     std::vector<AudioPort> ports = moduleConfig->getExternalDevicePorts();
1740     if (ports.empty()) {
1741         GTEST_SKIP() << "No external devices in the module.";
1742     }
1743     for (const auto& port : ports) {
1744         WithDevicePortConnectedState portConnected(GenerateUniqueDeviceAddress(port));
1745         ASSERT_NO_FATAL_FAILURE(portConnected.SetUp(module.get(), moduleConfig.get()));
1746         const auto portConfig = moduleConfig->getSingleConfigForDevicePort(portConnected.get());
1747         {
1748             WithAudioPortConfig config(portConfig);
1749             // Note: if SetUp fails, check the status of 'GetAudioPortWithExternalDevices' test.
1750             // Our test assumes that 'getAudioPort' returns at least one profile, and it
1751             // is not a dynamic profile.
1752             ASSERT_NO_FATAL_FAILURE(config.SetUp(module.get()));
1753             EXPECT_STATUS(EX_ILLEGAL_STATE, module->disconnectExternalDevice(portConnected.getId()))
1754                     << "when trying to disconnect device port ID " << port.id
1755                     << " with active configuration " << config.getId();
1756         }
1757     }
1758 }
1759 
TEST_P(AudioCoreModule,ExternalDevicePortRoutes)1760 TEST_P(AudioCoreModule, ExternalDevicePortRoutes) {
1761     ASSERT_NO_FATAL_FAILURE(SetUpModuleConfig());
1762     std::vector<AudioPort> ports = moduleConfig->getExternalDevicePorts();
1763     if (ports.empty()) {
1764         GTEST_SKIP() << "No external devices in the module.";
1765     }
1766     for (const auto& port : ports) {
1767         std::vector<AudioRoute> routesBefore;
1768         ASSERT_IS_OK(module->getAudioRoutes(&routesBefore));
1769 
1770         int32_t connectedPortId;
1771         {
1772             WithDevicePortConnectedState portConnected(GenerateUniqueDeviceAddress(port));
1773             ASSERT_NO_FATAL_FAILURE(portConnected.SetUp(module.get(), moduleConfig.get()));
1774             connectedPortId = portConnected.getId();
1775             std::vector<AudioRoute> connectedPortRoutes;
1776             ASSERT_IS_OK(module->getAudioRoutesForAudioPort(connectedPortId, &connectedPortRoutes))
1777                     << "when retrieving routes for connected port id " << connectedPortId;
1778             // There must be routes for the port to be useful.
1779             if (connectedPortRoutes.empty()) {
1780                 std::vector<AudioRoute> allRoutes;
1781                 ASSERT_IS_OK(module->getAudioRoutes(&allRoutes));
1782                 ADD_FAILURE() << " no routes returned for the connected port "
1783                               << portConnected.get().toString()
1784                               << "; all routes: " << android::internal::ToString(allRoutes);
1785             }
1786         }
1787         std::vector<AudioRoute> ignored;
1788         ASSERT_STATUS(EX_ILLEGAL_ARGUMENT,
1789                       module->getAudioRoutesForAudioPort(connectedPortId, &ignored))
1790                 << "when retrieving routes for released connected port id " << connectedPortId;
1791 
1792         std::vector<AudioRoute> routesAfter;
1793         ASSERT_IS_OK(module->getAudioRoutes(&routesAfter));
1794         ASSERT_EQ(routesBefore.size(), routesAfter.size())
1795                 << "Sizes of audio route arrays do not match after creating and "
1796                 << "releasing a connected port";
1797         std::sort(routesBefore.begin(), routesBefore.end());
1798         std::sort(routesAfter.begin(), routesAfter.end());
1799         EXPECT_EQ(routesBefore, routesAfter);
1800     }
1801 }
1802 
1803 // Note: This test relies on simulation of external device connections by the HAL module.
TEST_P(AudioCoreModule,ExternalDeviceMixPortConfigs)1804 TEST_P(AudioCoreModule, ExternalDeviceMixPortConfigs) {
1805     // After an external device has been connected, all mix ports that can be routed
1806     // to the device port for the connected device must have non-empty profiles.
1807     ASSERT_NO_FATAL_FAILURE(SetUpModuleConfig());
1808     std::vector<AudioPort> externalDevicePorts = moduleConfig->getExternalDevicePorts();
1809     if (externalDevicePorts.empty()) {
1810         GTEST_SKIP() << "No external devices in the module.";
1811     }
1812     for (const auto& port : externalDevicePorts) {
1813         WithDevicePortConnectedState portConnected(GenerateUniqueDeviceAddress(port));
1814         ASSERT_NO_FATAL_FAILURE(portConnected.SetUp(module.get(), moduleConfig.get()));
1815         std::vector<AudioRoute> routes;
1816         ASSERT_IS_OK(module->getAudioRoutesForAudioPort(portConnected.getId(), &routes));
1817         std::vector<AudioPort> allPorts;
1818         ASSERT_IS_OK(module->getAudioPorts(&allPorts));
1819         for (const auto& r : routes) {
1820             if (r.sinkPortId == portConnected.getId()) {
1821                 for (const auto& srcPortId : r.sourcePortIds) {
1822                     const auto srcPortIt = findById(allPorts, srcPortId);
1823                     ASSERT_NE(allPorts.end(), srcPortIt) << "port ID " << srcPortId;
1824                     EXPECT_NE(0UL, srcPortIt->profiles.size())
1825                             << " source port " << srcPortIt->toString() << " must have its profiles"
1826                             << " populated following external device connection";
1827                 }
1828             } else {
1829                 const auto sinkPortIt = findById(allPorts, r.sinkPortId);
1830                 ASSERT_NE(allPorts.end(), sinkPortIt) << "port ID " << r.sinkPortId;
1831                 EXPECT_NE(0UL, sinkPortIt->profiles.size())
1832                         << " source port " << sinkPortIt->toString() << " must have its"
1833                         << " profiles populated following external device connection";
1834             }
1835         }
1836     }
1837 }
1838 
TEST_P(AudioCoreModule,MasterMute)1839 TEST_P(AudioCoreModule, MasterMute) {
1840     bool isSupported = false;
1841     EXPECT_NO_FATAL_FAILURE(TestAccessors<bool>(module.get(), &IModule::getMasterMute,
1842                                                 &IModule::setMasterMute, {false, true}, {},
1843                                                 &isSupported));
1844     if (!isSupported) {
1845         GTEST_SKIP() << "Master mute is not supported";
1846     }
1847     // TODO: Test that master mute actually mutes output.
1848 }
1849 
TEST_P(AudioCoreModule,MasterVolume)1850 TEST_P(AudioCoreModule, MasterVolume) {
1851     bool isSupported = false;
1852     EXPECT_NO_FATAL_FAILURE(TestAccessors<float>(
1853             module.get(), &IModule::getMasterVolume, &IModule::setMasterVolume, {0.0f, 0.5f, 1.0f},
1854             {-0.1, 1.1, NAN, INFINITY, -INFINITY, 1 + std::numeric_limits<float>::epsilon()},
1855             &isSupported));
1856     if (!isSupported) {
1857         GTEST_SKIP() << "Master volume is not supported";
1858     }
1859     // TODO: Test that master volume actually attenuates output.
1860 }
1861 
TEST_P(AudioCoreModule,MicMute)1862 TEST_P(AudioCoreModule, MicMute) {
1863     bool isSupported = false;
1864     EXPECT_NO_FATAL_FAILURE(TestAccessors<bool>(module.get(), &IModule::getMicMute,
1865                                                 &IModule::setMicMute, {false, true}, {},
1866                                                 &isSupported));
1867     if (!isSupported) {
1868         GTEST_SKIP() << "Mic mute is not supported";
1869     }
1870     // TODO: Test that mic mute actually mutes input.
1871 }
1872 
TEST_P(AudioCoreModule,GetMicrophones)1873 TEST_P(AudioCoreModule, GetMicrophones) {
1874     ASSERT_NO_FATAL_FAILURE(SetUpModuleConfig());
1875     const std::vector<AudioPort> builtInMicPorts = moduleConfig->getAttachedMicrophonePorts();
1876     std::vector<MicrophoneInfo> micInfos;
1877     ScopedAStatus status = module->getMicrophones(&micInfos);
1878     if (!status.isOk()) {
1879         EXPECT_EQ(EX_UNSUPPORTED_OPERATION, status.getExceptionCode());
1880         ASSERT_FALSE(builtInMicPorts.empty())
1881                 << "When the HAL module does not have built-in microphones, IModule.getMicrophones"
1882                 << " must complete with no error and return an empty list";
1883         GTEST_SKIP() << "Microphone info is not supported";
1884     }
1885     std::set<int32_t> micPortIdsWithInfo;
1886     for (const auto& micInfo : micInfos) {
1887         const auto& micDevice = micInfo.device;
1888         const auto it =
1889                 std::find_if(builtInMicPorts.begin(), builtInMicPorts.end(), [&](const auto& port) {
1890                     return port.ext.template get<AudioPortExt::Tag::device>().device == micDevice;
1891                 });
1892         if (it != builtInMicPorts.end()) {
1893             micPortIdsWithInfo.insert(it->id);
1894         } else {
1895             ADD_FAILURE() << "No device port found with a device specified for the microphone \""
1896                           << micInfo.id << "\": " << micDevice.toString();
1897         }
1898     }
1899     if (micPortIdsWithInfo.size() != builtInMicPorts.size()) {
1900         std::vector<AudioPort> micPortsNoInfo;
1901         std::copy_if(builtInMicPorts.begin(), builtInMicPorts.end(),
1902                      std::back_inserter(micPortsNoInfo),
1903                      [&](const auto& port) { return micPortIdsWithInfo.count(port.id) == 0; });
1904         ADD_FAILURE() << "No MicrophoneInfo is provided for the following microphone device ports: "
1905                       << ::android::internal::ToString(micPortsNoInfo);
1906     }
1907 }
1908 
TEST_P(AudioCoreModule,UpdateAudioMode)1909 TEST_P(AudioCoreModule, UpdateAudioMode) {
1910     for (const auto mode : ::ndk::enum_range<AudioMode>()) {
1911         if (isValidAudioMode(mode)) {
1912             EXPECT_IS_OK(module->updateAudioMode(mode)) << toString(mode);
1913         } else {
1914             EXPECT_STATUS(EX_ILLEGAL_ARGUMENT, module->updateAudioMode(mode)) << toString(mode);
1915         }
1916     }
1917     EXPECT_IS_OK(module->updateAudioMode(AudioMode::NORMAL));
1918 }
1919 
TEST_P(AudioCoreModule,UpdateScreenRotation)1920 TEST_P(AudioCoreModule, UpdateScreenRotation) {
1921     for (const auto rotation : ::ndk::enum_range<IModule::ScreenRotation>()) {
1922         EXPECT_IS_OK(module->updateScreenRotation(rotation)) << toString(rotation);
1923     }
1924     EXPECT_IS_OK(module->updateScreenRotation(IModule::ScreenRotation::DEG_0));
1925 }
1926 
TEST_P(AudioCoreModule,UpdateScreenState)1927 TEST_P(AudioCoreModule, UpdateScreenState) {
1928     EXPECT_IS_OK(module->updateScreenState(false));
1929     EXPECT_IS_OK(module->updateScreenState(true));
1930 }
1931 
TEST_P(AudioCoreModule,GenerateHwAvSyncId)1932 TEST_P(AudioCoreModule, GenerateHwAvSyncId) {
1933     const auto kStatuses = {EX_NONE, EX_ILLEGAL_STATE};
1934     int32_t id1;
1935     ndk::ScopedAStatus status = module->generateHwAvSyncId(&id1);
1936     if (status.getExceptionCode() == EX_UNSUPPORTED_OPERATION) {
1937         GTEST_SKIP() << "HW AV Sync is not supported";
1938     }
1939     EXPECT_STATUS(kStatuses, status);
1940     if (status.isOk()) {
1941         int32_t id2;
1942         ASSERT_IS_OK(module->generateHwAvSyncId(&id2));
1943         EXPECT_NE(id1, id2) << "HW AV Sync IDs must be unique";
1944     }
1945 }
1946 
TEST_P(AudioCoreModule,GetVendorParameters)1947 TEST_P(AudioCoreModule, GetVendorParameters) {
1948     bool isGetterSupported = false;
1949     EXPECT_NO_FATAL_FAILURE(TestGetVendorParameters(module.get(), &isGetterSupported));
1950     ndk::ScopedAStatus status = module->setVendorParameters({}, false);
1951     EXPECT_EQ(isGetterSupported, status.getExceptionCode() != EX_UNSUPPORTED_OPERATION)
1952             << "Support for getting and setting of vendor parameters must be consistent";
1953     if (!isGetterSupported) {
1954         GTEST_SKIP() << "Vendor parameters are not supported";
1955     }
1956 }
1957 
TEST_P(AudioCoreModule,SetVendorParameters)1958 TEST_P(AudioCoreModule, SetVendorParameters) {
1959     bool isSupported = false;
1960     EXPECT_NO_FATAL_FAILURE(TestSetVendorParameters(module.get(), &isSupported));
1961     if (!isSupported) {
1962         GTEST_SKIP() << "Vendor parameters are not supported";
1963     }
1964 }
1965 
1966 // See b/262930731. In the absence of offloaded effect implementations,
1967 // currently we can only pass a nullptr, and the HAL module must either reject
1968 // it as an invalid argument, or say that offloaded effects are not supported.
TEST_P(AudioCoreModule,AddRemoveEffectInvalidArguments)1969 TEST_P(AudioCoreModule, AddRemoveEffectInvalidArguments) {
1970     ndk::ScopedAStatus addEffectStatus = module->addDeviceEffect(-1, nullptr);
1971     ndk::ScopedAStatus removeEffectStatus = module->removeDeviceEffect(-1, nullptr);
1972     if (addEffectStatus.getExceptionCode() != EX_UNSUPPORTED_OPERATION) {
1973         EXPECT_EQ(EX_ILLEGAL_ARGUMENT, addEffectStatus.getExceptionCode());
1974         EXPECT_EQ(EX_ILLEGAL_ARGUMENT, removeEffectStatus.getExceptionCode());
1975     } else if (removeEffectStatus.getExceptionCode() != EX_UNSUPPORTED_OPERATION) {
1976         GTEST_FAIL() << "addDeviceEffect and removeDeviceEffect must be either supported or "
1977                      << "not supported together";
1978     } else {
1979         GTEST_SKIP() << "Offloaded effects not supported";
1980     }
1981     // Test rejection of a nullptr effect with a valid device port Id.
1982     ASSERT_NO_FATAL_FAILURE(SetUpModuleConfig());
1983     const auto configs = moduleConfig->getPortConfigsForAttachedDevicePorts();
1984     for (const auto& config : configs) {
1985         WithAudioPortConfig portConfig(config);
1986         ASSERT_NO_FATAL_FAILURE(portConfig.SetUp(module.get()));
1987         EXPECT_STATUS(EX_ILLEGAL_ARGUMENT, module->addDeviceEffect(portConfig.getId(), nullptr));
1988         EXPECT_STATUS(EX_ILLEGAL_ARGUMENT, module->removeDeviceEffect(portConfig.getId(), nullptr));
1989     }
1990 }
1991 
TEST_P(AudioCoreModule,GetMmapPolicyInfos)1992 TEST_P(AudioCoreModule, GetMmapPolicyInfos) {
1993     ASSERT_NO_FATAL_FAILURE(SetUpModuleConfig());
1994     const bool isMmapSupported = moduleConfig->isMmapSupported();
1995     for (const auto mmapPolicyType :
1996          {AudioMMapPolicyType::DEFAULT, AudioMMapPolicyType::EXCLUSIVE}) {
1997         std::vector<AudioMMapPolicyInfo> policyInfos;
1998         EXPECT_IS_OK(module->getMmapPolicyInfos(mmapPolicyType, &policyInfos))
1999                 << toString(mmapPolicyType);
2000         EXPECT_EQ(isMmapSupported, !policyInfos.empty());
2001     }
2002 }
2003 
TEST_P(AudioCoreModule,BluetoothVariableLatency)2004 TEST_P(AudioCoreModule, BluetoothVariableLatency) {
2005     bool isSupported = false;
2006     EXPECT_IS_OK(module->supportsVariableLatency(&isSupported));
2007     LOG(INFO) << "supportsVariableLatency: " << isSupported;
2008 }
2009 
TEST_P(AudioCoreModule,GetAAudioMixerBurstCount)2010 TEST_P(AudioCoreModule, GetAAudioMixerBurstCount) {
2011     ASSERT_NO_FATAL_FAILURE(SetUpModuleConfig());
2012     const bool isMmapSupported = moduleConfig->isMmapSupported();
2013     int32_t mixerBursts = 0;
2014     ndk::ScopedAStatus status = module->getAAudioMixerBurstCount(&mixerBursts);
2015     EXPECT_EQ(isMmapSupported, status.getExceptionCode() != EX_UNSUPPORTED_OPERATION)
2016             << "Support for AAudio MMAP and getting AAudio mixer burst count must be consistent";
2017     if (!isMmapSupported) {
2018         GTEST_SKIP() << "AAudio MMAP is not supported";
2019     }
2020     EXPECT_GE(mixerBursts, 0);
2021 }
2022 
TEST_P(AudioCoreModule,GetAAudioHardwareBurstMinUsec)2023 TEST_P(AudioCoreModule, GetAAudioHardwareBurstMinUsec) {
2024     ASSERT_NO_FATAL_FAILURE(SetUpModuleConfig());
2025     const bool isMmapSupported = moduleConfig->isMmapSupported();
2026     int32_t aaudioHardwareBurstMinUsec = 0;
2027     ndk::ScopedAStatus status = module->getAAudioHardwareBurstMinUsec(&aaudioHardwareBurstMinUsec);
2028     EXPECT_EQ(isMmapSupported, status.getExceptionCode() != EX_UNSUPPORTED_OPERATION)
2029             << "Support for AAudio MMAP and getting AAudio hardware burst minimum usec "
2030             << "must be consistent";
2031     if (!isMmapSupported) {
2032         GTEST_SKIP() << "AAudio MMAP is not supported";
2033     }
2034     EXPECT_GE(aaudioHardwareBurstMinUsec, 0);
2035 }
2036 
2037 class AudioCoreBluetooth : public AudioCoreModuleBase, public testing::TestWithParam<std::string> {
2038   public:
SetUp()2039     void SetUp() override {
2040         ASSERT_NO_FATAL_FAILURE(SetUpImpl(GetParam()));
2041         ASSERT_IS_OK(module->getBluetooth(&bluetooth));
2042     }
2043 
TearDown()2044     void TearDown() override { ASSERT_NO_FATAL_FAILURE(TearDownImpl()); }
2045 
2046     std::shared_ptr<IBluetooth> bluetooth;
2047 };
2048 
TEST_P(AudioCoreBluetooth,SameInstance)2049 TEST_P(AudioCoreBluetooth, SameInstance) {
2050     if (bluetooth == nullptr) {
2051         GTEST_SKIP() << "Bluetooth is not supported";
2052     }
2053     std::shared_ptr<IBluetooth> bluetooth2;
2054     EXPECT_IS_OK(module->getBluetooth(&bluetooth2));
2055     ASSERT_NE(nullptr, bluetooth2.get());
2056     EXPECT_EQ(bluetooth->asBinder(), bluetooth2->asBinder())
2057             << "getBluetooth must return the same interface instance across invocations";
2058 }
2059 
TEST_P(AudioCoreBluetooth,ScoConfig)2060 TEST_P(AudioCoreBluetooth, ScoConfig) {
2061     static const auto kStatuses = {EX_NONE, EX_UNSUPPORTED_OPERATION};
2062     if (bluetooth == nullptr) {
2063         GTEST_SKIP() << "Bluetooth is not supported";
2064     }
2065     ndk::ScopedAStatus status;
2066     IBluetooth::ScoConfig scoConfig;
2067     ASSERT_STATUS(kStatuses, status = bluetooth->setScoConfig({}, &scoConfig));
2068     if (status.getExceptionCode() == EX_UNSUPPORTED_OPERATION) {
2069         GTEST_SKIP() << "BT SCO is not supported";
2070     }
2071     EXPECT_TRUE(scoConfig.isEnabled.has_value());
2072     EXPECT_TRUE(scoConfig.isNrecEnabled.has_value());
2073     EXPECT_NE(IBluetooth::ScoConfig::Mode::UNSPECIFIED, scoConfig.mode);
2074     IBluetooth::ScoConfig scoConfig2;
2075     ASSERT_IS_OK(bluetooth->setScoConfig(scoConfig, &scoConfig2));
2076     EXPECT_EQ(scoConfig, scoConfig2);
2077 }
2078 
TEST_P(AudioCoreBluetooth,HfpConfig)2079 TEST_P(AudioCoreBluetooth, HfpConfig) {
2080     static const auto kStatuses = {EX_NONE, EX_UNSUPPORTED_OPERATION};
2081     if (bluetooth == nullptr) {
2082         GTEST_SKIP() << "Bluetooth is not supported";
2083     }
2084     ndk::ScopedAStatus status;
2085     IBluetooth::HfpConfig hfpConfig;
2086     ASSERT_STATUS(kStatuses, status = bluetooth->setHfpConfig({}, &hfpConfig));
2087     if (status.getExceptionCode() == EX_UNSUPPORTED_OPERATION) {
2088         GTEST_SKIP() << "BT HFP is not supported";
2089     }
2090     EXPECT_TRUE(hfpConfig.isEnabled.has_value());
2091     EXPECT_TRUE(hfpConfig.sampleRate.has_value());
2092     EXPECT_TRUE(hfpConfig.volume.has_value());
2093     IBluetooth::HfpConfig hfpConfig2;
2094     ASSERT_IS_OK(bluetooth->setHfpConfig(hfpConfig, &hfpConfig2));
2095     EXPECT_EQ(hfpConfig, hfpConfig2);
2096 }
2097 
TEST_P(AudioCoreBluetooth,HfpConfigInvalid)2098 TEST_P(AudioCoreBluetooth, HfpConfigInvalid) {
2099     static const auto kStatuses = {EX_NONE, EX_UNSUPPORTED_OPERATION};
2100     if (bluetooth == nullptr) {
2101         GTEST_SKIP() << "Bluetooth is not supported";
2102     }
2103     ndk::ScopedAStatus status;
2104     IBluetooth::HfpConfig hfpConfig;
2105     ASSERT_STATUS(kStatuses, status = bluetooth->setHfpConfig({}, &hfpConfig));
2106     if (status.getExceptionCode() == EX_UNSUPPORTED_OPERATION) {
2107         GTEST_SKIP() << "BT HFP is not supported";
2108     }
2109     EXPECT_STATUS(EX_ILLEGAL_ARGUMENT,
2110                   bluetooth->setHfpConfig({.sampleRate = Int{-1}}, &hfpConfig));
2111     EXPECT_STATUS(EX_ILLEGAL_ARGUMENT, bluetooth->setHfpConfig({.sampleRate = Int{0}}, &hfpConfig));
2112     EXPECT_STATUS(EX_ILLEGAL_ARGUMENT,
2113                   bluetooth->setHfpConfig({.volume = Float{IBluetooth::HfpConfig::VOLUME_MIN - 1}},
2114                                           &hfpConfig));
2115     EXPECT_STATUS(EX_ILLEGAL_ARGUMENT,
2116                   bluetooth->setHfpConfig({.volume = Float{IBluetooth::HfpConfig::VOLUME_MAX + 1}},
2117                                           &hfpConfig));
2118 }
2119 
2120 class AudioCoreBluetoothA2dp : public AudioCoreModuleBase,
2121                                public testing::TestWithParam<std::string> {
2122   public:
SetUp()2123     void SetUp() override {
2124         ASSERT_NO_FATAL_FAILURE(SetUpImpl(GetParam()));
2125         ASSERT_IS_OK(module->getBluetoothA2dp(&bluetooth));
2126     }
2127 
TearDown()2128     void TearDown() override { ASSERT_NO_FATAL_FAILURE(TearDownImpl()); }
2129 
2130     std::shared_ptr<IBluetoothA2dp> bluetooth;
2131 };
2132 
TEST_P(AudioCoreBluetoothA2dp,SameInstance)2133 TEST_P(AudioCoreBluetoothA2dp, SameInstance) {
2134     if (bluetooth == nullptr) {
2135         GTEST_SKIP() << "BluetoothA2dp is not supported";
2136     }
2137     std::shared_ptr<IBluetoothA2dp> bluetooth2;
2138     EXPECT_IS_OK(module->getBluetoothA2dp(&bluetooth2));
2139     ASSERT_NE(nullptr, bluetooth2.get());
2140     EXPECT_EQ(bluetooth->asBinder(), bluetooth2->asBinder())
2141             << "getBluetoothA2dp must return the same interface instance across invocations";
2142 }
2143 
TEST_P(AudioCoreBluetoothA2dp,Enabled)2144 TEST_P(AudioCoreBluetoothA2dp, Enabled) {
2145     if (bluetooth == nullptr) {
2146         GTEST_SKIP() << "BluetoothA2dp is not supported";
2147     }
2148     // Since enabling A2DP may require having an actual device connection,
2149     // limit testing to setting back the current value.
2150     bool enabled;
2151     ASSERT_IS_OK(bluetooth->isEnabled(&enabled));
2152     EXPECT_IS_OK(bluetooth->setEnabled(enabled))
2153             << "setEnabled without actual state change must not fail";
2154 }
2155 
TEST_P(AudioCoreBluetoothA2dp,OffloadReconfiguration)2156 TEST_P(AudioCoreBluetoothA2dp, OffloadReconfiguration) {
2157     if (bluetooth == nullptr) {
2158         GTEST_SKIP() << "BluetoothA2dp is not supported";
2159     }
2160     bool isSupported;
2161     ASSERT_IS_OK(bluetooth->supportsOffloadReconfiguration(&isSupported));
2162     bool isSupported2;
2163     ASSERT_IS_OK(bluetooth->supportsOffloadReconfiguration(&isSupported2));
2164     EXPECT_EQ(isSupported, isSupported2);
2165     if (isSupported) {
2166         static const auto kStatuses = {EX_NONE, EX_ILLEGAL_STATE};
2167         EXPECT_STATUS(kStatuses, bluetooth->reconfigureOffload({}));
2168     } else {
2169         EXPECT_STATUS(EX_UNSUPPORTED_OPERATION, bluetooth->reconfigureOffload({}));
2170     }
2171 }
2172 
2173 class AudioCoreBluetoothLe : public AudioCoreModuleBase,
2174                              public testing::TestWithParam<std::string> {
2175   public:
SetUp()2176     void SetUp() override {
2177         ASSERT_NO_FATAL_FAILURE(SetUpImpl(GetParam()));
2178         ASSERT_IS_OK(module->getBluetoothLe(&bluetooth));
2179     }
2180 
TearDown()2181     void TearDown() override { ASSERT_NO_FATAL_FAILURE(TearDownImpl()); }
2182 
2183     std::shared_ptr<IBluetoothLe> bluetooth;
2184 };
2185 
TEST_P(AudioCoreBluetoothLe,SameInstance)2186 TEST_P(AudioCoreBluetoothLe, SameInstance) {
2187     if (bluetooth == nullptr) {
2188         GTEST_SKIP() << "BluetoothLe is not supported";
2189     }
2190     std::shared_ptr<IBluetoothLe> bluetooth2;
2191     EXPECT_IS_OK(module->getBluetoothLe(&bluetooth2));
2192     ASSERT_NE(nullptr, bluetooth2.get());
2193     EXPECT_EQ(bluetooth->asBinder(), bluetooth2->asBinder())
2194             << "getBluetoothLe must return the same interface instance across invocations";
2195 }
2196 
TEST_P(AudioCoreBluetoothLe,Enabled)2197 TEST_P(AudioCoreBluetoothLe, Enabled) {
2198     if (bluetooth == nullptr) {
2199         GTEST_SKIP() << "BluetoothLe is not supported";
2200     }
2201     // Since enabling LE may require having an actual device connection,
2202     // limit testing to setting back the current value.
2203     bool enabled;
2204     ASSERT_IS_OK(bluetooth->isEnabled(&enabled));
2205     EXPECT_IS_OK(bluetooth->setEnabled(enabled))
2206             << "setEnabled without actual state change must not fail";
2207 }
2208 
TEST_P(AudioCoreBluetoothLe,OffloadReconfiguration)2209 TEST_P(AudioCoreBluetoothLe, OffloadReconfiguration) {
2210     if (bluetooth == nullptr) {
2211         GTEST_SKIP() << "BluetoothLe is not supported";
2212     }
2213     bool isSupported;
2214     ASSERT_IS_OK(bluetooth->supportsOffloadReconfiguration(&isSupported));
2215     bool isSupported2;
2216     ASSERT_IS_OK(bluetooth->supportsOffloadReconfiguration(&isSupported2));
2217     EXPECT_EQ(isSupported, isSupported2);
2218     if (isSupported) {
2219         static const auto kStatuses = {EX_NONE, EX_ILLEGAL_STATE};
2220         EXPECT_STATUS(kStatuses, bluetooth->reconfigureOffload({}));
2221     } else {
2222         EXPECT_STATUS(EX_UNSUPPORTED_OPERATION, bluetooth->reconfigureOffload({}));
2223     }
2224 }
2225 
2226 class AudioCoreTelephony : public AudioCoreModuleBase, public testing::TestWithParam<std::string> {
2227   public:
SetUp()2228     void SetUp() override {
2229         ASSERT_NO_FATAL_FAILURE(SetUpImpl(GetParam()));
2230         ASSERT_IS_OK(module->getTelephony(&telephony));
2231     }
2232 
TearDown()2233     void TearDown() override { ASSERT_NO_FATAL_FAILURE(TearDownImpl()); }
2234 
2235     std::shared_ptr<ITelephony> telephony;
2236 };
2237 
TEST_P(AudioCoreTelephony,SameInstance)2238 TEST_P(AudioCoreTelephony, SameInstance) {
2239     if (telephony == nullptr) {
2240         GTEST_SKIP() << "Telephony is not supported";
2241     }
2242     std::shared_ptr<ITelephony> telephony2;
2243     EXPECT_IS_OK(module->getTelephony(&telephony2));
2244     ASSERT_NE(nullptr, telephony2.get());
2245     EXPECT_EQ(telephony->asBinder(), telephony2->asBinder())
2246             << "getTelephony must return the same interface instance across invocations";
2247 }
2248 
TEST_P(AudioCoreTelephony,GetSupportedAudioModes)2249 TEST_P(AudioCoreTelephony, GetSupportedAudioModes) {
2250     if (telephony == nullptr) {
2251         GTEST_SKIP() << "Telephony is not supported";
2252     }
2253     std::vector<AudioMode> modes1;
2254     ASSERT_IS_OK(telephony->getSupportedAudioModes(&modes1));
2255     for (const auto mode : modes1) {
2256         EXPECT_TRUE(isValidAudioMode(mode)) << toString(mode);
2257     }
2258     const std::vector<AudioMode> kMandatoryModes = {AudioMode::NORMAL, AudioMode::RINGTONE,
2259                                                     AudioMode::IN_CALL,
2260                                                     AudioMode::IN_COMMUNICATION};
2261     for (const auto mode : kMandatoryModes) {
2262         EXPECT_NE(modes1.end(), std::find(modes1.begin(), modes1.end(), mode))
2263                 << "Mandatory mode not supported: " << toString(mode);
2264     }
2265     std::vector<AudioMode> modes2;
2266     ASSERT_IS_OK(telephony->getSupportedAudioModes(&modes2));
2267     ASSERT_EQ(modes1.size(), modes2.size())
2268             << "Sizes of audio mode arrays do not match across consequent calls to "
2269             << "getSupportedAudioModes";
2270     std::sort(modes1.begin(), modes1.end());
2271     std::sort(modes2.begin(), modes2.end());
2272     EXPECT_EQ(modes1, modes2);
2273 };
2274 
TEST_P(AudioCoreTelephony,SwitchAudioMode)2275 TEST_P(AudioCoreTelephony, SwitchAudioMode) {
2276     if (telephony == nullptr) {
2277         GTEST_SKIP() << "Telephony is not supported";
2278     }
2279     std::vector<AudioMode> supportedModes;
2280     ASSERT_IS_OK(telephony->getSupportedAudioModes(&supportedModes));
2281     std::set<AudioMode> unsupportedModes = {
2282             // Start with all, remove supported ones
2283             ::ndk::enum_range<AudioMode>().begin(), ::ndk::enum_range<AudioMode>().end()};
2284     for (const auto mode : supportedModes) {
2285         EXPECT_IS_OK(telephony->switchAudioMode(mode)) << toString(mode);
2286         unsupportedModes.erase(mode);
2287     }
2288     for (const auto mode : unsupportedModes) {
2289         EXPECT_STATUS(isValidAudioMode(mode) ? EX_UNSUPPORTED_OPERATION : EX_ILLEGAL_ARGUMENT,
2290                       telephony->switchAudioMode(mode))
2291                 << toString(mode);
2292     }
2293 }
2294 
TEST_P(AudioCoreTelephony,TelecomConfig)2295 TEST_P(AudioCoreTelephony, TelecomConfig) {
2296     static const auto kStatuses = {EX_NONE, EX_UNSUPPORTED_OPERATION};
2297     if (telephony == nullptr) {
2298         GTEST_SKIP() << "Telephony is not supported";
2299     }
2300     ndk::ScopedAStatus status;
2301     ITelephony::TelecomConfig telecomConfig;
2302     ASSERT_STATUS(kStatuses, status = telephony->setTelecomConfig({}, &telecomConfig));
2303     if (status.getExceptionCode() == EX_UNSUPPORTED_OPERATION) {
2304         GTEST_SKIP() << "Telecom is not supported";
2305     }
2306     EXPECT_TRUE(telecomConfig.voiceVolume.has_value());
2307     EXPECT_NE(ITelephony::TelecomConfig::TtyMode::UNSPECIFIED, telecomConfig.ttyMode);
2308     EXPECT_TRUE(telecomConfig.isHacEnabled.has_value());
2309     ITelephony::TelecomConfig telecomConfig2;
2310     ASSERT_IS_OK(telephony->setTelecomConfig(telecomConfig, &telecomConfig2));
2311     EXPECT_EQ(telecomConfig, telecomConfig2);
2312 }
2313 
TEST_P(AudioCoreTelephony,TelecomConfigInvalid)2314 TEST_P(AudioCoreTelephony, TelecomConfigInvalid) {
2315     static const auto kStatuses = {EX_NONE, EX_UNSUPPORTED_OPERATION};
2316     if (telephony == nullptr) {
2317         GTEST_SKIP() << "Telephony is not supported";
2318     }
2319     ndk::ScopedAStatus status;
2320     ITelephony::TelecomConfig telecomConfig;
2321     ASSERT_STATUS(kStatuses, status = telephony->setTelecomConfig({}, &telecomConfig));
2322     if (status.getExceptionCode() == EX_UNSUPPORTED_OPERATION) {
2323         GTEST_SKIP() << "Telecom is not supported";
2324     }
2325     EXPECT_STATUS(EX_ILLEGAL_ARGUMENT,
2326                   telephony->setTelecomConfig(
2327                           {.voiceVolume = Float{ITelephony::TelecomConfig::VOICE_VOLUME_MIN - 1}},
2328                           &telecomConfig));
2329     EXPECT_STATUS(EX_ILLEGAL_ARGUMENT,
2330                   telephony->setTelecomConfig(
2331                           {.voiceVolume = Float{ITelephony::TelecomConfig::VOICE_VOLUME_MAX + 1}},
2332                           &telecomConfig));
2333 }
2334 
2335 using CommandSequence = std::vector<StreamDescriptor::Command>;
2336 class StreamLogicDriverInvalidCommand : public StreamLogicDriver {
2337   public:
StreamLogicDriverInvalidCommand(const CommandSequence & commands)2338     StreamLogicDriverInvalidCommand(const CommandSequence& commands) : mCommands(commands) {}
2339 
getUnexpectedStatuses()2340     std::string getUnexpectedStatuses() {
2341         // This method is intended to be called after the worker thread has joined,
2342         // thus no extra synchronization is needed.
2343         std::string s;
2344         if (!mStatuses.empty()) {
2345             s = std::string("Pairs of (command, actual status): ")
2346                         .append((android::internal::ToString(mStatuses)));
2347         }
2348         return s;
2349     }
2350 
done()2351     bool done() override { return mNextCommand >= mCommands.size(); }
getNextTrigger(int,int * actualSize)2352     TransitionTrigger getNextTrigger(int, int* actualSize) override {
2353         if (actualSize != nullptr) *actualSize = 0;
2354         return mCommands[mNextCommand++];
2355     }
interceptRawReply(const StreamDescriptor::Reply & reply)2356     bool interceptRawReply(const StreamDescriptor::Reply& reply) override {
2357         const size_t currentCommand = mNextCommand - 1;  // increased by getNextTrigger
2358         const bool isLastCommand = currentCommand == mCommands.size() - 1;
2359         // All but the last command should run correctly. The last command must return 'BAD_VALUE'
2360         // status.
2361         if ((!isLastCommand && reply.status != STATUS_OK) ||
2362             (isLastCommand && reply.status != STATUS_BAD_VALUE)) {
2363             std::string s = mCommands[currentCommand].toString();
2364             s.append(", ").append(statusToString(reply.status));
2365             mStatuses.push_back(std::move(s));
2366             // Process the reply, since the worker exits in case of an error.
2367             return false;
2368         }
2369         return isLastCommand;
2370     }
processValidReply(const StreamDescriptor::Reply &)2371     bool processValidReply(const StreamDescriptor::Reply&) override { return true; }
2372 
2373   private:
2374     const CommandSequence mCommands;
2375     size_t mNextCommand = 0;
2376     std::vector<std::string> mStatuses;
2377 };
2378 
2379 template <typename Stream>
2380 class AudioStream : public AudioCoreModule {
2381   public:
SetUp()2382     void SetUp() override {
2383         ASSERT_NO_FATAL_FAILURE(AudioCoreModule::SetUp());
2384         ASSERT_NO_FATAL_FAILURE(SetUpModuleConfig());
2385     }
2386 
GetStreamCommon()2387     void GetStreamCommon() {
2388         const auto portConfig = moduleConfig->getSingleConfigForMixPort(IOTraits<Stream>::is_input);
2389         if (!portConfig.has_value()) {
2390             GTEST_SKIP() << "No mix port for attached devices";
2391         }
2392         WithStream<Stream> stream(portConfig.value());
2393         ASSERT_NO_FATAL_FAILURE(stream.SetUp(module.get(), kDefaultBufferSizeFrames));
2394         std::shared_ptr<IStreamCommon> streamCommon1;
2395         EXPECT_IS_OK(stream.get()->getStreamCommon(&streamCommon1));
2396         std::shared_ptr<IStreamCommon> streamCommon2;
2397         EXPECT_IS_OK(stream.get()->getStreamCommon(&streamCommon2));
2398         ASSERT_NE(nullptr, streamCommon1);
2399         ASSERT_NE(nullptr, streamCommon2);
2400         EXPECT_EQ(streamCommon1->asBinder(), streamCommon2->asBinder())
2401                 << "getStreamCommon must return the same interface instance across invocations";
2402     }
2403 
CloseTwice()2404     void CloseTwice() {
2405         const auto portConfig = moduleConfig->getSingleConfigForMixPort(IOTraits<Stream>::is_input);
2406         if (!portConfig.has_value()) {
2407             GTEST_SKIP() << "No mix port for attached devices";
2408         }
2409         std::shared_ptr<Stream> heldStream;
2410         {
2411             WithStream<Stream> stream(portConfig.value());
2412             ASSERT_NO_FATAL_FAILURE(stream.SetUp(module.get(), kDefaultBufferSizeFrames));
2413             heldStream = stream.getSharedPointer();
2414         }
2415         EXPECT_STATUS(EX_ILLEGAL_STATE, WithStream<Stream>::callClose(heldStream))
2416                 << "when closing the stream twice";
2417     }
2418 
PrepareToCloseTwice()2419     void PrepareToCloseTwice() {
2420         const auto portConfig = moduleConfig->getSingleConfigForMixPort(IOTraits<Stream>::is_input);
2421         if (!portConfig.has_value()) {
2422             GTEST_SKIP() << "No mix port for attached devices";
2423         }
2424         std::shared_ptr<IStreamCommon> heldStreamCommon;
2425         {
2426             WithStream<Stream> stream(portConfig.value());
2427             ASSERT_NO_FATAL_FAILURE(stream.SetUp(module.get(), kDefaultBufferSizeFrames));
2428             std::shared_ptr<IStreamCommon> streamCommon;
2429             ASSERT_IS_OK(stream.get()->getStreamCommon(&streamCommon));
2430             heldStreamCommon = streamCommon;
2431             EXPECT_IS_OK(streamCommon->prepareToClose());
2432             EXPECT_IS_OK(streamCommon->prepareToClose())
2433                     << "when calling prepareToClose second time";
2434         }
2435         EXPECT_STATUS(EX_ILLEGAL_STATE, heldStreamCommon->prepareToClose())
2436                 << "when calling prepareToClose on a closed stream";
2437     }
2438 
OpenAllConfigs()2439     void OpenAllConfigs() {
2440         const auto allPortConfigs =
2441                 moduleConfig->getPortConfigsForMixPorts(IOTraits<Stream>::is_input);
2442         for (const auto& portConfig : allPortConfigs) {
2443             WithStream<Stream> stream(portConfig);
2444             ASSERT_NO_FATAL_FAILURE(stream.SetUp(module.get(), kDefaultBufferSizeFrames));
2445         }
2446     }
2447 
OpenInvalidBufferSize()2448     void OpenInvalidBufferSize() {
2449         const auto portConfig = moduleConfig->getSingleConfigForMixPort(IOTraits<Stream>::is_input);
2450         if (!portConfig.has_value()) {
2451             GTEST_SKIP() << "No mix port for attached devices";
2452         }
2453         WithStream<Stream> stream(portConfig.value());
2454         ASSERT_NO_FATAL_FAILURE(stream.SetUpPortConfig(module.get()));
2455         for (long bufferSize : std::array<long, 3>{-1, 0, std::numeric_limits<long>::max()}) {
2456             EXPECT_STATUS(EX_ILLEGAL_ARGUMENT, stream.SetUpNoChecks(module.get(), bufferSize))
2457                     << "for the buffer size " << bufferSize;
2458             EXPECT_EQ(nullptr, stream.get());
2459         }
2460     }
2461 
OpenInvalidDirection()2462     void OpenInvalidDirection() {
2463         // Important! The direction of the port config must be reversed.
2464         const auto portConfig =
2465                 moduleConfig->getSingleConfigForMixPort(!IOTraits<Stream>::is_input);
2466         if (!portConfig.has_value()) {
2467             GTEST_SKIP() << "No mix port for attached devices";
2468         }
2469         WithStream<Stream> stream(portConfig.value());
2470         ASSERT_NO_FATAL_FAILURE(stream.SetUpPortConfig(module.get()));
2471         EXPECT_STATUS(EX_ILLEGAL_ARGUMENT,
2472                       stream.SetUpNoChecks(module.get(), kDefaultBufferSizeFrames))
2473                 << "port config ID " << stream.getPortId();
2474         EXPECT_EQ(nullptr, stream.get());
2475     }
2476 
OpenOverMaxCount()2477     void OpenOverMaxCount() {
2478         constexpr bool isInput = IOTraits<Stream>::is_input;
2479         auto ports = moduleConfig->getMixPorts(isInput, true /*connectedOnly*/);
2480         bool hasSingleRun = false;
2481         for (const auto& port : ports) {
2482             const size_t maxStreamCount = port.ext.get<AudioPortExt::Tag::mix>().maxOpenStreamCount;
2483             if (maxStreamCount == 0) {
2484                 continue;
2485             }
2486             auto portConfigs = moduleConfig->getPortConfigsForMixPorts(isInput, port);
2487             if (portConfigs.size() < maxStreamCount + 1) {
2488                 // Not able to open a sufficient number of streams for this port.
2489                 continue;
2490             }
2491             hasSingleRun = true;
2492             std::optional<WithStream<Stream>> streamWraps[maxStreamCount + 1];
2493             for (size_t i = 0; i <= maxStreamCount; ++i) {
2494                 streamWraps[i].emplace(portConfigs[i]);
2495                 WithStream<Stream>& stream = streamWraps[i].value();
2496                 if (i < maxStreamCount) {
2497                     ASSERT_NO_FATAL_FAILURE(stream.SetUp(module.get(), kDefaultBufferSizeFrames));
2498                 } else {
2499                     ASSERT_NO_FATAL_FAILURE(stream.SetUpPortConfig(module.get()));
2500                     EXPECT_STATUS(EX_ILLEGAL_STATE,
2501                                   stream.SetUpNoChecks(module.get(), kDefaultBufferSizeFrames))
2502                             << "port config ID " << stream.getPortId() << ", maxOpenStreamCount is "
2503                             << maxStreamCount;
2504                 }
2505             }
2506         }
2507         if (!hasSingleRun) {
2508             GTEST_SKIP() << "Not enough ports to test max open stream count";
2509         }
2510     }
2511 
OpenTwiceSamePortConfig()2512     void OpenTwiceSamePortConfig() {
2513         const auto portConfig = moduleConfig->getSingleConfigForMixPort(IOTraits<Stream>::is_input);
2514         if (!portConfig.has_value()) {
2515             GTEST_SKIP() << "No mix port for attached devices";
2516         }
2517         EXPECT_NO_FATAL_FAILURE(OpenTwiceSamePortConfigImpl(portConfig.value()));
2518     }
2519 
ResetPortConfigWithOpenStream()2520     void ResetPortConfigWithOpenStream() {
2521         const auto portConfig = moduleConfig->getSingleConfigForMixPort(IOTraits<Stream>::is_input);
2522         if (!portConfig.has_value()) {
2523             GTEST_SKIP() << "No mix port for attached devices";
2524         }
2525         WithStream<Stream> stream(portConfig.value());
2526         ASSERT_NO_FATAL_FAILURE(stream.SetUp(module.get(), kDefaultBufferSizeFrames));
2527         EXPECT_STATUS(EX_ILLEGAL_STATE, module->resetAudioPortConfig(stream.getPortId()))
2528                 << "port config ID " << stream.getPortId();
2529     }
2530 
SendInvalidCommand()2531     void SendInvalidCommand() {
2532         const auto portConfig = moduleConfig->getSingleConfigForMixPort(IOTraits<Stream>::is_input);
2533         if (!portConfig.has_value()) {
2534             GTEST_SKIP() << "No mix port for attached devices";
2535         }
2536         EXPECT_NO_FATAL_FAILURE(SendInvalidCommandImpl(portConfig.value()));
2537     }
2538 
UpdateHwAvSyncId()2539     void UpdateHwAvSyncId() {
2540         const auto portConfig = moduleConfig->getSingleConfigForMixPort(IOTraits<Stream>::is_input);
2541         if (!portConfig.has_value()) {
2542             GTEST_SKIP() << "No mix port for attached devices";
2543         }
2544         WithStream<Stream> stream(portConfig.value());
2545         ASSERT_NO_FATAL_FAILURE(stream.SetUp(module.get(), kDefaultBufferSizeFrames));
2546         std::shared_ptr<IStreamCommon> streamCommon;
2547         ASSERT_IS_OK(stream.get()->getStreamCommon(&streamCommon));
2548         ASSERT_NE(nullptr, streamCommon);
2549         const auto kStatuses = {EX_NONE, EX_ILLEGAL_ARGUMENT, EX_ILLEGAL_STATE};
2550         for (const auto id : {-100, -1, 0, 1, 100}) {
2551             ndk::ScopedAStatus status = streamCommon->updateHwAvSyncId(id);
2552             if (status.getExceptionCode() == EX_UNSUPPORTED_OPERATION) {
2553                 GTEST_SKIP() << "HW AV Sync is not supported";
2554             }
2555             EXPECT_STATUS(kStatuses, status) << "id: " << id;
2556         }
2557     }
2558 
GetVendorParameters()2559     void GetVendorParameters() {
2560         const auto portConfig = moduleConfig->getSingleConfigForMixPort(IOTraits<Stream>::is_input);
2561         if (!portConfig.has_value()) {
2562             GTEST_SKIP() << "No mix port for attached devices";
2563         }
2564         WithStream<Stream> stream(portConfig.value());
2565         ASSERT_NO_FATAL_FAILURE(stream.SetUp(module.get(), kDefaultBufferSizeFrames));
2566         std::shared_ptr<IStreamCommon> streamCommon;
2567         ASSERT_IS_OK(stream.get()->getStreamCommon(&streamCommon));
2568         ASSERT_NE(nullptr, streamCommon);
2569 
2570         bool isGetterSupported = false;
2571         EXPECT_NO_FATAL_FAILURE(TestGetVendorParameters(module.get(), &isGetterSupported));
2572         ndk::ScopedAStatus status = module->setVendorParameters({}, false);
2573         EXPECT_EQ(isGetterSupported, status.getExceptionCode() != EX_UNSUPPORTED_OPERATION)
2574                 << "Support for getting and setting of vendor parameters must be consistent";
2575         if (!isGetterSupported) {
2576             GTEST_SKIP() << "Vendor parameters are not supported";
2577         }
2578     }
2579 
SetVendorParameters()2580     void SetVendorParameters() {
2581         const auto portConfig = moduleConfig->getSingleConfigForMixPort(IOTraits<Stream>::is_input);
2582         if (!portConfig.has_value()) {
2583             GTEST_SKIP() << "No mix port for attached devices";
2584         }
2585         WithStream<Stream> stream(portConfig.value());
2586         ASSERT_NO_FATAL_FAILURE(stream.SetUp(module.get(), kDefaultBufferSizeFrames));
2587         std::shared_ptr<IStreamCommon> streamCommon;
2588         ASSERT_IS_OK(stream.get()->getStreamCommon(&streamCommon));
2589         ASSERT_NE(nullptr, streamCommon);
2590 
2591         bool isSupported = false;
2592         EXPECT_NO_FATAL_FAILURE(TestSetVendorParameters(module.get(), &isSupported));
2593         if (!isSupported) {
2594             GTEST_SKIP() << "Vendor parameters are not supported";
2595         }
2596     }
2597 
HwGainHwVolume()2598     void HwGainHwVolume() {
2599         const auto ports =
2600                 moduleConfig->getMixPorts(IOTraits<Stream>::is_input, true /*connectedOnly*/);
2601         if (ports.empty()) {
2602             GTEST_SKIP() << "No mix ports";
2603         }
2604         bool atLeastOneSupports = false;
2605         for (const auto& port : ports) {
2606             const auto portConfig = moduleConfig->getSingleConfigForMixPort(true, port);
2607             if (!portConfig.has_value()) continue;
2608             WithStream<Stream> stream(portConfig.value());
2609             ASSERT_NO_FATAL_FAILURE(stream.SetUp(module.get(), kDefaultBufferSizeFrames));
2610             std::vector<std::vector<float>> validValues, invalidValues;
2611             bool isSupported = false;
2612             if constexpr (IOTraits<Stream>::is_input) {
2613                 GenerateTestArrays<float>(getChannelCount(portConfig.value().channelMask.value()),
2614                                           IStreamIn::HW_GAIN_MIN, IStreamIn::HW_GAIN_MAX,
2615                                           &validValues, &invalidValues);
2616                 EXPECT_NO_FATAL_FAILURE(TestAccessors<std::vector<float>>(
2617                         stream.get(), &IStreamIn::getHwGain, &IStreamIn::setHwGain, validValues,
2618                         invalidValues, &isSupported));
2619             } else {
2620                 GenerateTestArrays<float>(getChannelCount(portConfig.value().channelMask.value()),
2621                                           IStreamOut::HW_VOLUME_MIN, IStreamOut::HW_VOLUME_MAX,
2622                                           &validValues, &invalidValues);
2623                 EXPECT_NO_FATAL_FAILURE(TestAccessors<std::vector<float>>(
2624                         stream.get(), &IStreamOut::getHwVolume, &IStreamOut::setHwVolume,
2625                         validValues, invalidValues, &isSupported));
2626             }
2627             if (isSupported) atLeastOneSupports = true;
2628         }
2629         if (!atLeastOneSupports) {
2630             GTEST_SKIP() << "Hardware gain / volume is not supported";
2631         }
2632     }
2633 
2634     // See b/262930731. In the absence of offloaded effect implementations,
2635     // currently we can only pass a nullptr, and the HAL module must either reject
2636     // it as an invalid argument, or say that offloaded effects are not supported.
AddRemoveEffectInvalidArguments()2637     void AddRemoveEffectInvalidArguments() {
2638         const auto ports =
2639                 moduleConfig->getMixPorts(IOTraits<Stream>::is_input, true /*connectedOnly*/);
2640         if (ports.empty()) {
2641             GTEST_SKIP() << "No mix ports";
2642         }
2643         bool atLeastOneSupports = false;
2644         for (const auto& port : ports) {
2645             const auto portConfig = moduleConfig->getSingleConfigForMixPort(true, port);
2646             if (!portConfig.has_value()) continue;
2647             WithStream<Stream> stream(portConfig.value());
2648             ASSERT_NO_FATAL_FAILURE(stream.SetUp(module.get(), kDefaultBufferSizeFrames));
2649             std::shared_ptr<IStreamCommon> streamCommon;
2650             ASSERT_IS_OK(stream.get()->getStreamCommon(&streamCommon));
2651             ASSERT_NE(nullptr, streamCommon);
2652             ndk::ScopedAStatus addEffectStatus = streamCommon->addEffect(nullptr);
2653             ndk::ScopedAStatus removeEffectStatus = streamCommon->removeEffect(nullptr);
2654             if (addEffectStatus.getExceptionCode() != EX_UNSUPPORTED_OPERATION) {
2655                 EXPECT_EQ(EX_ILLEGAL_ARGUMENT, addEffectStatus.getExceptionCode());
2656                 EXPECT_EQ(EX_ILLEGAL_ARGUMENT, removeEffectStatus.getExceptionCode());
2657                 atLeastOneSupports = true;
2658             } else if (removeEffectStatus.getExceptionCode() != EX_UNSUPPORTED_OPERATION) {
2659                 ADD_FAILURE() << "addEffect and removeEffect must be either supported or "
2660                               << "not supported together";
2661                 atLeastOneSupports = true;
2662             }
2663         }
2664         if (!atLeastOneSupports) {
2665             GTEST_SKIP() << "Offloaded effects not supported";
2666         }
2667     }
2668 
OpenTwiceSamePortConfigImpl(const AudioPortConfig & portConfig)2669     void OpenTwiceSamePortConfigImpl(const AudioPortConfig& portConfig) {
2670         WithStream<Stream> stream1(portConfig);
2671         ASSERT_NO_FATAL_FAILURE(stream1.SetUp(module.get(), kDefaultBufferSizeFrames));
2672         WithStream<Stream> stream2;
2673         EXPECT_STATUS(EX_ILLEGAL_STATE, stream2.SetUpNoChecks(module.get(), stream1.getPortConfig(),
2674                                                               kDefaultBufferSizeFrames))
2675                 << "when opening a stream twice for the same port config ID "
2676                 << stream1.getPortId();
2677     }
2678 
SendInvalidCommandImpl(const AudioPortConfig & portConfig)2679     void SendInvalidCommandImpl(const AudioPortConfig& portConfig) {
2680         using TestSequence = std::pair<std::string, CommandSequence>;
2681         // The last command in 'CommandSequence' is the one that must trigger
2682         // an error status. All preceding commands are to put the state machine
2683         // into a state which accepts the last command.
2684         std::vector<TestSequence> sequences{
2685                 std::make_pair(std::string("HalReservedExit"),
2686                                std::vector{StreamDescriptor::Command::make<
2687                                        StreamDescriptor::Command::Tag::halReservedExit>(0)}),
2688                 std::make_pair(std::string("BurstNeg"),
2689                                std::vector{kStartCommand,
2690                                            StreamDescriptor::Command::make<
2691                                                    StreamDescriptor::Command::Tag::burst>(-1)}),
2692                 std::make_pair(
2693                         std::string("BurstMinInt"),
2694                         std::vector{kStartCommand, StreamDescriptor::Command::make<
2695                                                            StreamDescriptor::Command::Tag::burst>(
2696                                                            std::numeric_limits<int32_t>::min())})};
2697         if (IOTraits<Stream>::is_input) {
2698             sequences.emplace_back("DrainAll",
2699                                    std::vector{kStartCommand, kBurstCommand, kDrainOutAllCommand});
2700             sequences.emplace_back(
2701                     "DrainEarly", std::vector{kStartCommand, kBurstCommand, kDrainOutEarlyCommand});
2702         } else {
2703             sequences.emplace_back("DrainUnspecified",
2704                                    std::vector{kStartCommand, kBurstCommand, kDrainInCommand});
2705         }
2706         for (const auto& seq : sequences) {
2707             SCOPED_TRACE(std::string("Sequence ").append(seq.first));
2708             LOG(DEBUG) << __func__ << ": Sequence " << seq.first;
2709             WithStream<Stream> stream(portConfig);
2710             ASSERT_NO_FATAL_FAILURE(stream.SetUp(module.get(), kDefaultBufferSizeFrames));
2711             StreamLogicDriverInvalidCommand driver(seq.second);
2712             typename IOTraits<Stream>::Worker worker(*stream.getContext(), &driver,
2713                                                      stream.getEventReceiver());
2714             LOG(DEBUG) << __func__ << ": starting worker...";
2715             ASSERT_TRUE(worker.start());
2716             LOG(DEBUG) << __func__ << ": joining worker...";
2717             worker.join();
2718             EXPECT_EQ("", driver.getUnexpectedStatuses());
2719         }
2720     }
2721 };
2722 using AudioStreamIn = AudioStream<IStreamIn>;
2723 using AudioStreamOut = AudioStream<IStreamOut>;
2724 
2725 #define TEST_IN_AND_OUT_STREAM(method_name)     \
2726     TEST_P(AudioStreamIn, method_name) {        \
2727         ASSERT_NO_FATAL_FAILURE(method_name()); \
2728     }                                           \
2729     TEST_P(AudioStreamOut, method_name) {       \
2730         ASSERT_NO_FATAL_FAILURE(method_name()); \
2731     }
2732 
2733 TEST_IN_AND_OUT_STREAM(CloseTwice);
2734 TEST_IN_AND_OUT_STREAM(PrepareToCloseTwice);
2735 TEST_IN_AND_OUT_STREAM(GetStreamCommon);
2736 TEST_IN_AND_OUT_STREAM(OpenAllConfigs);
2737 TEST_IN_AND_OUT_STREAM(OpenInvalidBufferSize);
2738 TEST_IN_AND_OUT_STREAM(OpenInvalidDirection);
2739 TEST_IN_AND_OUT_STREAM(OpenOverMaxCount);
2740 TEST_IN_AND_OUT_STREAM(OpenTwiceSamePortConfig);
2741 TEST_IN_AND_OUT_STREAM(ResetPortConfigWithOpenStream);
2742 TEST_IN_AND_OUT_STREAM(SendInvalidCommand);
2743 TEST_IN_AND_OUT_STREAM(UpdateHwAvSyncId);
2744 TEST_IN_AND_OUT_STREAM(GetVendorParameters);
2745 TEST_IN_AND_OUT_STREAM(SetVendorParameters);
2746 TEST_IN_AND_OUT_STREAM(HwGainHwVolume);
2747 TEST_IN_AND_OUT_STREAM(AddRemoveEffectInvalidArguments);
2748 
2749 namespace aidl::android::hardware::audio::core {
operator <<(std::ostream & os,const IStreamIn::MicrophoneDirection & md)2750 std::ostream& operator<<(std::ostream& os, const IStreamIn::MicrophoneDirection& md) {
2751     os << toString(md);
2752     return os;
2753 }
2754 }  // namespace aidl::android::hardware::audio::core
2755 
TEST_P(AudioStreamIn,ActiveMicrophones)2756 TEST_P(AudioStreamIn, ActiveMicrophones) {
2757     std::vector<MicrophoneInfo> micInfos;
2758     ScopedAStatus status = module->getMicrophones(&micInfos);
2759     if (!status.isOk()) {
2760         GTEST_SKIP() << "Microphone info is not supported";
2761     }
2762     const auto ports = moduleConfig->getInputMixPorts(true /*connectedOnly*/);
2763     if (ports.empty()) {
2764         GTEST_SKIP() << "No input mix ports for attached devices";
2765     }
2766     for (const auto& port : ports) {
2767         const auto portConfig = moduleConfig->getSingleConfigForMixPort(true, port);
2768         ASSERT_TRUE(portConfig.has_value()) << "No profiles specified for input mix port";
2769         WithStream<IStreamIn> stream(portConfig.value());
2770         ASSERT_NO_FATAL_FAILURE(stream.SetUp(module.get(), kDefaultBufferSizeFrames));
2771         {
2772             // The port of the stream is not connected, thus the list of active mics must be empty.
2773             std::vector<MicrophoneDynamicInfo> activeMics;
2774             EXPECT_IS_OK(stream.get()->getActiveMicrophones(&activeMics));
2775             EXPECT_TRUE(activeMics.empty()) << "a stream on an unconnected port returns a "
2776                                                "non-empty list of active microphones";
2777         }
2778         if (auto micDevicePorts = ModuleConfig::getBuiltInMicPorts(
2779                     moduleConfig->getConnectedSourceDevicesPortsForMixPort(port));
2780             !micDevicePorts.empty()) {
2781             auto devicePortConfig = moduleConfig->getSingleConfigForDevicePort(micDevicePorts[0]);
2782             WithAudioPatch patch(true /*isInput*/, stream.getPortConfig(), devicePortConfig);
2783             ASSERT_NO_FATAL_FAILURE(patch.SetUp(module.get()));
2784             std::vector<MicrophoneDynamicInfo> activeMics;
2785             EXPECT_IS_OK(stream.get()->getActiveMicrophones(&activeMics));
2786             EXPECT_FALSE(activeMics.empty());
2787             for (const auto& mic : activeMics) {
2788                 EXPECT_NE(micInfos.end(),
2789                           std::find_if(micInfos.begin(), micInfos.end(),
2790                                        [&](const auto& micInfo) { return micInfo.id == mic.id; }))
2791                         << "active microphone \"" << mic.id << "\" is not listed in "
2792                         << "microphone infos returned by the module: "
2793                         << ::android::internal::ToString(micInfos);
2794                 EXPECT_NE(0UL, mic.channelMapping.size())
2795                         << "No channels specified for the microphone \"" << mic.id << "\"";
2796             }
2797         }
2798         {
2799             // Now the port of the stream is not connected again, re-check that there are no
2800             // active microphones.
2801             std::vector<MicrophoneDynamicInfo> activeMics;
2802             EXPECT_IS_OK(stream.get()->getActiveMicrophones(&activeMics));
2803             EXPECT_TRUE(activeMics.empty()) << "a stream on an unconnected port returns a "
2804                                                "non-empty list of active microphones";
2805         }
2806     }
2807 }
2808 
TEST_P(AudioStreamIn,MicrophoneDirection)2809 TEST_P(AudioStreamIn, MicrophoneDirection) {
2810     using MD = IStreamIn::MicrophoneDirection;
2811     const auto ports = moduleConfig->getInputMixPorts(true /*connectedOnly*/);
2812     if (ports.empty()) {
2813         GTEST_SKIP() << "No input mix ports for attached devices";
2814     }
2815     bool isSupported = false;
2816     for (const auto& port : ports) {
2817         const auto portConfig = moduleConfig->getSingleConfigForMixPort(true, port);
2818         ASSERT_TRUE(portConfig.has_value()) << "No profiles specified for input mix port";
2819         WithStream<IStreamIn> stream(portConfig.value());
2820         ASSERT_NO_FATAL_FAILURE(stream.SetUp(module.get(), kDefaultBufferSizeFrames));
2821         EXPECT_NO_FATAL_FAILURE(
2822                 TestAccessors<MD>(stream.get(), &IStreamIn::getMicrophoneDirection,
2823                                   &IStreamIn::setMicrophoneDirection,
2824                                   std::vector<MD>(enum_range<MD>().begin(), enum_range<MD>().end()),
2825                                   {}, &isSupported));
2826         if (!isSupported) break;
2827     }
2828     if (!isSupported) {
2829         GTEST_SKIP() << "Microphone direction is not supported";
2830     }
2831 }
2832 
TEST_P(AudioStreamIn,MicrophoneFieldDimension)2833 TEST_P(AudioStreamIn, MicrophoneFieldDimension) {
2834     const auto ports = moduleConfig->getInputMixPorts(true /*connectedOnly*/);
2835     if (ports.empty()) {
2836         GTEST_SKIP() << "No input mix ports for attached devices";
2837     }
2838     bool isSupported = false;
2839     for (const auto& port : ports) {
2840         const auto portConfig = moduleConfig->getSingleConfigForMixPort(true, port);
2841         ASSERT_TRUE(portConfig.has_value()) << "No profiles specified for input mix port";
2842         WithStream<IStreamIn> stream(portConfig.value());
2843         ASSERT_NO_FATAL_FAILURE(stream.SetUp(module.get(), kDefaultBufferSizeFrames));
2844         EXPECT_NO_FATAL_FAILURE(TestAccessors<float>(
2845                 stream.get(), &IStreamIn::getMicrophoneFieldDimension,
2846                 &IStreamIn::setMicrophoneFieldDimension,
2847                 {IStreamIn::MIC_FIELD_DIMENSION_WIDE_ANGLE,
2848                  IStreamIn::MIC_FIELD_DIMENSION_WIDE_ANGLE / 2.0f,
2849                  IStreamIn::MIC_FIELD_DIMENSION_NO_ZOOM,
2850                  IStreamIn::MIC_FIELD_DIMENSION_MAX_ZOOM / 2.0f,
2851                  IStreamIn::MIC_FIELD_DIMENSION_MAX_ZOOM},
2852                 {IStreamIn::MIC_FIELD_DIMENSION_WIDE_ANGLE * 2,
2853                  IStreamIn::MIC_FIELD_DIMENSION_MAX_ZOOM * 2,
2854                  IStreamIn::MIC_FIELD_DIMENSION_WIDE_ANGLE * 1.1f,
2855                  IStreamIn::MIC_FIELD_DIMENSION_MAX_ZOOM * 1.1f, -INFINITY, INFINITY, -NAN, NAN},
2856                 &isSupported));
2857         if (!isSupported) break;
2858     }
2859     if (!isSupported) {
2860         GTEST_SKIP() << "Microphone direction is not supported";
2861     }
2862 }
2863 
TEST_P(AudioStreamOut,OpenTwicePrimary)2864 TEST_P(AudioStreamOut, OpenTwicePrimary) {
2865     const auto mixPorts =
2866             moduleConfig->getPrimaryMixPorts(true /*connectedOnly*/, true /*singlePort*/);
2867     if (mixPorts.empty()) {
2868         GTEST_SKIP() << "No primary mix port which could be routed to attached devices";
2869     }
2870     const auto portConfig = moduleConfig->getSingleConfigForMixPort(false, *mixPorts.begin());
2871     ASSERT_TRUE(portConfig.has_value()) << "No profiles specified for the primary mix port";
2872     EXPECT_NO_FATAL_FAILURE(OpenTwiceSamePortConfigImpl(portConfig.value()));
2873 }
2874 
TEST_P(AudioStreamOut,RequireOffloadInfo)2875 TEST_P(AudioStreamOut, RequireOffloadInfo) {
2876     const auto offloadMixPorts =
2877             moduleConfig->getOffloadMixPorts(true /*connectedOnly*/, true /*singlePort*/);
2878     if (offloadMixPorts.empty()) {
2879         GTEST_SKIP()
2880                 << "No mix port for compressed offload that could be routed to attached devices";
2881     }
2882     const auto config = moduleConfig->getSingleConfigForMixPort(false, *offloadMixPorts.begin());
2883     ASSERT_TRUE(config.has_value()) << "No profiles specified for the compressed offload mix port";
2884     WithAudioPortConfig portConfig(config.value());
2885     ASSERT_NO_FATAL_FAILURE(portConfig.SetUp(module.get()));
2886     StreamDescriptor descriptor;
2887     std::shared_ptr<IStreamOut> ignored;
2888     aidl::android::hardware::audio::core::IModule::OpenOutputStreamArguments args;
2889     args.portConfigId = portConfig.getId();
2890     args.sourceMetadata = GenerateSourceMetadata(portConfig.get());
2891     args.bufferSizeFrames = kDefaultLargeBufferSizeFrames;
2892     aidl::android::hardware::audio::core::IModule::OpenOutputStreamReturn ret;
2893     EXPECT_STATUS(EX_ILLEGAL_ARGUMENT, module->openOutputStream(args, &ret))
2894             << "when no offload info is provided for a compressed offload mix port";
2895 }
2896 
TEST_P(AudioStreamOut,RequireAsyncCallback)2897 TEST_P(AudioStreamOut, RequireAsyncCallback) {
2898     const auto nonBlockingMixPorts =
2899             moduleConfig->getNonBlockingMixPorts(true /*connectedOnly*/, true /*singlePort*/);
2900     if (nonBlockingMixPorts.empty()) {
2901         GTEST_SKIP()
2902                 << "No mix port for non-blocking output that could be routed to attached devices";
2903     }
2904     const auto config =
2905             moduleConfig->getSingleConfigForMixPort(false, *nonBlockingMixPorts.begin());
2906     ASSERT_TRUE(config.has_value()) << "No profiles specified for the non-blocking mix port";
2907     WithAudioPortConfig portConfig(config.value());
2908     ASSERT_NO_FATAL_FAILURE(portConfig.SetUp(module.get()));
2909     StreamDescriptor descriptor;
2910     std::shared_ptr<IStreamOut> ignored;
2911     aidl::android::hardware::audio::core::IModule::OpenOutputStreamArguments args;
2912     args.portConfigId = portConfig.getId();
2913     args.sourceMetadata = GenerateSourceMetadata(portConfig.get());
2914     args.offloadInfo = ModuleConfig::generateOffloadInfoIfNeeded(portConfig.get());
2915     args.bufferSizeFrames = kDefaultBufferSizeFrames;
2916     aidl::android::hardware::audio::core::IModule::OpenOutputStreamReturn ret;
2917     EXPECT_STATUS(EX_ILLEGAL_ARGUMENT, module->openOutputStream(args, &ret))
2918             << "when no async callback is provided for a non-blocking mix port";
2919 }
2920 
TEST_P(AudioStreamOut,AudioDescriptionMixLevel)2921 TEST_P(AudioStreamOut, AudioDescriptionMixLevel) {
2922     const auto ports = moduleConfig->getOutputMixPorts(true /*connectedOnly*/);
2923     if (ports.empty()) {
2924         GTEST_SKIP() << "No output mix ports";
2925     }
2926     bool atLeastOneSupports = false;
2927     for (const auto& port : ports) {
2928         const auto portConfig = moduleConfig->getSingleConfigForMixPort(false, port);
2929         ASSERT_TRUE(portConfig.has_value()) << "No profiles specified for output mix port";
2930         WithStream<IStreamOut> stream(portConfig.value());
2931         ASSERT_NO_FATAL_FAILURE(stream.SetUp(module.get(), kDefaultBufferSizeFrames));
2932         bool isSupported = false;
2933         EXPECT_NO_FATAL_FAILURE(
2934                 TestAccessors<float>(stream.get(), &IStreamOut::getAudioDescriptionMixLevel,
2935                                      &IStreamOut::setAudioDescriptionMixLevel,
2936                                      {IStreamOut::AUDIO_DESCRIPTION_MIX_LEVEL_MAX,
2937                                       IStreamOut::AUDIO_DESCRIPTION_MIX_LEVEL_MAX - 1, 0,
2938                                       -INFINITY /*IStreamOut::AUDIO_DESCRIPTION_MIX_LEVEL_MIN*/},
2939                                      {IStreamOut::AUDIO_DESCRIPTION_MIX_LEVEL_MAX * 2,
2940                                       IStreamOut::AUDIO_DESCRIPTION_MIX_LEVEL_MAX * 1.1f},
2941                                      &isSupported));
2942         if (isSupported) atLeastOneSupports = true;
2943     }
2944     if (!atLeastOneSupports) {
2945         GTEST_SKIP() << "Audio description mix level is not supported";
2946     }
2947 }
2948 
TEST_P(AudioStreamOut,DualMonoMode)2949 TEST_P(AudioStreamOut, DualMonoMode) {
2950     const auto ports = moduleConfig->getOutputMixPorts(true /*connectedOnly*/);
2951     if (ports.empty()) {
2952         GTEST_SKIP() << "No output mix ports";
2953     }
2954     bool atLeastOneSupports = false;
2955     for (const auto& port : ports) {
2956         const auto portConfig = moduleConfig->getSingleConfigForMixPort(false, port);
2957         ASSERT_TRUE(portConfig.has_value()) << "No profiles specified for output mix port";
2958         WithStream<IStreamOut> stream(portConfig.value());
2959         ASSERT_NO_FATAL_FAILURE(stream.SetUp(module.get(), kDefaultBufferSizeFrames));
2960         bool isSupported = false;
2961         EXPECT_NO_FATAL_FAILURE(TestAccessors<AudioDualMonoMode>(
2962                 stream.get(), &IStreamOut::getDualMonoMode, &IStreamOut::setDualMonoMode,
2963                 std::vector<AudioDualMonoMode>(enum_range<AudioDualMonoMode>().begin(),
2964                                                enum_range<AudioDualMonoMode>().end()),
2965                 {}, &isSupported));
2966         if (isSupported) atLeastOneSupports = true;
2967     }
2968     if (!atLeastOneSupports) {
2969         GTEST_SKIP() << "Audio dual mono mode is not supported";
2970     }
2971 }
2972 
TEST_P(AudioStreamOut,LatencyMode)2973 TEST_P(AudioStreamOut, LatencyMode) {
2974     const auto ports = moduleConfig->getOutputMixPorts(true /*connectedOnly*/);
2975     if (ports.empty()) {
2976         GTEST_SKIP() << "No output mix ports";
2977     }
2978     bool atLeastOneSupports = false;
2979     for (const auto& port : ports) {
2980         const auto portConfig = moduleConfig->getSingleConfigForMixPort(false, port);
2981         ASSERT_TRUE(portConfig.has_value()) << "No profiles specified for output mix port";
2982         WithStream<IStreamOut> stream(portConfig.value());
2983         ASSERT_NO_FATAL_FAILURE(stream.SetUp(module.get(), kDefaultBufferSizeFrames));
2984         std::vector<AudioLatencyMode> supportedModes;
2985         ndk::ScopedAStatus status = stream.get()->getRecommendedLatencyModes(&supportedModes);
2986         if (status.getExceptionCode() == EX_UNSUPPORTED_OPERATION) continue;
2987         atLeastOneSupports = true;
2988         if (!status.isOk()) {
2989             ADD_FAILURE() << "When latency modes are supported, getRecommendedLatencyModes "
2990                           << "must succeed on a non-closed stream, but it failed with " << status;
2991             continue;
2992         }
2993         std::set<AudioLatencyMode> unsupportedModes(enum_range<AudioLatencyMode>().begin(),
2994                                                     enum_range<AudioLatencyMode>().end());
2995         for (const auto mode : supportedModes) {
2996             unsupportedModes.erase(mode);
2997             ndk::ScopedAStatus status = stream.get()->setLatencyMode(mode);
2998             if (status.getExceptionCode() == EX_UNSUPPORTED_OPERATION) {
2999                 ADD_FAILURE() << "When latency modes are supported, both getRecommendedLatencyModes"
3000                               << " and setLatencyMode must be supported";
3001             }
3002             EXPECT_IS_OK(status) << "Setting of supported latency mode must succeed";
3003         }
3004         for (const auto mode : unsupportedModes) {
3005             EXPECT_STATUS(EX_ILLEGAL_ARGUMENT, stream.get()->setLatencyMode(mode));
3006         }
3007     }
3008     if (!atLeastOneSupports) {
3009         GTEST_SKIP() << "Audio latency modes are not supported";
3010     }
3011 }
3012 
TEST_P(AudioStreamOut,PlaybackRate)3013 TEST_P(AudioStreamOut, PlaybackRate) {
3014     static const auto kStatuses = {EX_NONE, EX_UNSUPPORTED_OPERATION};
3015     const auto offloadMixPorts =
3016             moduleConfig->getOffloadMixPorts(true /*connectedOnly*/, false /*singlePort*/);
3017     if (offloadMixPorts.empty()) {
3018         GTEST_SKIP()
3019                 << "No mix port for compressed offload that could be routed to attached devices";
3020     }
3021     ndk::ScopedAStatus status;
3022     IModule::SupportedPlaybackRateFactors factors;
3023     EXPECT_STATUS(kStatuses, status = module.get()->getSupportedPlaybackRateFactors(&factors));
3024     if (status.getExceptionCode() == EX_UNSUPPORTED_OPERATION) {
3025         GTEST_SKIP() << "Audio playback rate configuration is not supported";
3026     }
3027     EXPECT_LE(factors.minSpeed, factors.maxSpeed);
3028     EXPECT_LE(factors.minPitch, factors.maxPitch);
3029     EXPECT_LE(factors.minSpeed, 1.0f);
3030     EXPECT_GE(factors.maxSpeed, 1.0f);
3031     EXPECT_LE(factors.minPitch, 1.0f);
3032     EXPECT_GE(factors.maxPitch, 1.0f);
3033     constexpr auto tsDefault = AudioPlaybackRate::TimestretchMode::DEFAULT;
3034     constexpr auto tsVoice = AudioPlaybackRate::TimestretchMode::VOICE;
3035     constexpr auto fbFail = AudioPlaybackRate::TimestretchFallbackMode::FAIL;
3036     constexpr auto fbMute = AudioPlaybackRate::TimestretchFallbackMode::MUTE;
3037     const std::vector<AudioPlaybackRate> validValues = {
3038             AudioPlaybackRate{1.0f, 1.0f, tsDefault, fbFail},
3039             AudioPlaybackRate{1.0f, 1.0f, tsDefault, fbMute},
3040             AudioPlaybackRate{factors.maxSpeed, factors.maxPitch, tsDefault, fbMute},
3041             AudioPlaybackRate{factors.minSpeed, factors.minPitch, tsDefault, fbMute},
3042             AudioPlaybackRate{1.0f, 1.0f, tsVoice, fbMute},
3043             AudioPlaybackRate{1.0f, 1.0f, tsVoice, fbFail},
3044             AudioPlaybackRate{factors.maxSpeed, factors.maxPitch, tsVoice, fbMute},
3045             AudioPlaybackRate{factors.minSpeed, factors.minPitch, tsVoice, fbMute},
3046             // Out of range speed / pitch values must not be rejected if the fallback mode is "mute"
3047             AudioPlaybackRate{factors.maxSpeed * 2, factors.maxPitch * 2, tsDefault, fbMute},
3048             AudioPlaybackRate{factors.minSpeed / 2, factors.minPitch / 2, tsDefault, fbMute},
3049             AudioPlaybackRate{factors.maxSpeed * 2, factors.maxPitch * 2, tsVoice, fbMute},
3050             AudioPlaybackRate{factors.minSpeed / 2, factors.minPitch / 2, tsVoice, fbMute},
3051     };
3052     const std::vector<AudioPlaybackRate> invalidValues = {
3053             AudioPlaybackRate{factors.maxSpeed, factors.maxPitch * 2, tsDefault, fbFail},
3054             AudioPlaybackRate{factors.maxSpeed * 2, factors.maxPitch, tsDefault, fbFail},
3055             AudioPlaybackRate{factors.minSpeed, factors.minPitch / 2, tsDefault, fbFail},
3056             AudioPlaybackRate{factors.minSpeed / 2, factors.minPitch, tsDefault, fbFail},
3057             AudioPlaybackRate{factors.maxSpeed, factors.maxPitch * 2, tsVoice, fbFail},
3058             AudioPlaybackRate{factors.maxSpeed * 2, factors.maxPitch, tsVoice, fbFail},
3059             AudioPlaybackRate{factors.minSpeed, factors.minPitch / 2, tsVoice, fbFail},
3060             AudioPlaybackRate{factors.minSpeed / 2, factors.minPitch, tsVoice, fbFail},
3061             AudioPlaybackRate{1.0f, 1.0f, tsDefault,
3062                               AudioPlaybackRate::TimestretchFallbackMode::SYS_RESERVED_CUT_REPEAT},
3063             AudioPlaybackRate{1.0f, 1.0f, tsDefault,
3064                               AudioPlaybackRate::TimestretchFallbackMode::SYS_RESERVED_DEFAULT},
3065     };
3066     bool atLeastOneSupports = false;
3067     for (const auto& port : offloadMixPorts) {
3068         const auto portConfig = moduleConfig->getSingleConfigForMixPort(false, port);
3069         ASSERT_TRUE(portConfig.has_value()) << "No profiles specified for output mix port";
3070         WithStream<IStreamOut> stream(portConfig.value());
3071         ASSERT_NO_FATAL_FAILURE(stream.SetUp(module.get(), kDefaultLargeBufferSizeFrames));
3072         bool isSupported = false;
3073         EXPECT_NO_FATAL_FAILURE(TestAccessors<AudioPlaybackRate>(
3074                 stream.get(), &IStreamOut::getPlaybackRateParameters,
3075                 &IStreamOut::setPlaybackRateParameters, validValues, invalidValues, &isSupported));
3076         if (isSupported) atLeastOneSupports = true;
3077     }
3078     if (!atLeastOneSupports) {
3079         GTEST_SKIP() << "Audio playback rate configuration is not supported";
3080     }
3081 }
3082 
TEST_P(AudioStreamOut,SelectPresentation)3083 TEST_P(AudioStreamOut, SelectPresentation) {
3084     static const auto kStatuses = {EX_ILLEGAL_ARGUMENT, EX_UNSUPPORTED_OPERATION};
3085     const auto offloadMixPorts =
3086             moduleConfig->getOffloadMixPorts(true /*connectedOnly*/, false /*singlePort*/);
3087     if (offloadMixPorts.empty()) {
3088         GTEST_SKIP()
3089                 << "No mix port for compressed offload that could be routed to attached devices";
3090     }
3091     bool atLeastOneSupports = false;
3092     for (const auto& port : offloadMixPorts) {
3093         const auto portConfig = moduleConfig->getSingleConfigForMixPort(false, port);
3094         ASSERT_TRUE(portConfig.has_value()) << "No profiles specified for output mix port";
3095         WithStream<IStreamOut> stream(portConfig.value());
3096         ASSERT_NO_FATAL_FAILURE(stream.SetUp(module.get(), kDefaultLargeBufferSizeFrames));
3097         ndk::ScopedAStatus status;
3098         EXPECT_STATUS(kStatuses, status = stream.get()->selectPresentation(0, 0));
3099         if (status.getExceptionCode() != EX_UNSUPPORTED_OPERATION) atLeastOneSupports = true;
3100     }
3101     if (!atLeastOneSupports) {
3102         GTEST_SKIP() << "Presentation selection is not supported";
3103     }
3104 }
3105 
TEST_P(AudioStreamOut,UpdateOffloadMetadata)3106 TEST_P(AudioStreamOut, UpdateOffloadMetadata) {
3107     const auto offloadMixPorts =
3108             moduleConfig->getOffloadMixPorts(true /*connectedOnly*/, false /*singlePort*/);
3109     if (offloadMixPorts.empty()) {
3110         GTEST_SKIP()
3111                 << "No mix port for compressed offload that could be routed to attached devices";
3112     }
3113     for (const auto& port : offloadMixPorts) {
3114         const auto portConfig = moduleConfig->getSingleConfigForMixPort(false, port);
3115         ASSERT_TRUE(portConfig.has_value()) << "No profiles specified for output mix port";
3116         WithStream<IStreamOut> stream(portConfig.value());
3117         ASSERT_NO_FATAL_FAILURE(stream.SetUp(module.get(), kDefaultLargeBufferSizeFrames));
3118         AudioOffloadMetadata validMetadata{
3119                 .sampleRate = portConfig.value().sampleRate.value().value,
3120                 .channelMask = portConfig.value().channelMask.value(),
3121                 .averageBitRatePerSecond = 256000,
3122                 .delayFrames = 0,
3123                 .paddingFrames = 0};
3124         EXPECT_IS_OK(stream.get()->updateOffloadMetadata(validMetadata));
3125         AudioOffloadMetadata invalidMetadata{.sampleRate = -1,
3126                                              .averageBitRatePerSecond = -1,
3127                                              .delayFrames = -1,
3128                                              .paddingFrames = -1};
3129         EXPECT_STATUS(EX_ILLEGAL_ARGUMENT, stream.get()->updateOffloadMetadata(invalidMetadata));
3130     }
3131 }
3132 
3133 class StreamLogicDefaultDriver : public StreamLogicDriver {
3134   public:
StreamLogicDefaultDriver(std::shared_ptr<StateSequence> commands,size_t frameSizeBytes)3135     StreamLogicDefaultDriver(std::shared_ptr<StateSequence> commands, size_t frameSizeBytes)
3136         : mCommands(commands), mFrameSizeBytes(frameSizeBytes) {
3137         mCommands->rewind();
3138     }
3139 
3140     // The three methods below is intended to be called after the worker
3141     // thread has joined, thus no extra synchronization is needed.
hasObservablePositionIncrease() const3142     bool hasObservablePositionIncrease() const { return mObservablePositionIncrease; }
hasRetrogradeObservablePosition() const3143     bool hasRetrogradeObservablePosition() const { return mRetrogradeObservablePosition; }
getUnexpectedStateTransition() const3144     std::string getUnexpectedStateTransition() const { return mUnexpectedTransition; }
3145 
done()3146     bool done() override { return mCommands->done(); }
getNextTrigger(int maxDataSize,int * actualSize)3147     TransitionTrigger getNextTrigger(int maxDataSize, int* actualSize) override {
3148         auto trigger = mCommands->getTrigger();
3149         if (StreamDescriptor::Command* command = std::get_if<StreamDescriptor::Command>(&trigger);
3150             command != nullptr) {
3151             if (command->getTag() == StreamDescriptor::Command::Tag::burst) {
3152                 if (actualSize != nullptr) {
3153                     // In the output scenario, reduce slightly the fmqByteCount to verify
3154                     // that the HAL module always consumes all data from the MQ.
3155                     if (maxDataSize > static_cast<int>(mFrameSizeBytes)) {
3156                         LOG(DEBUG) << __func__ << ": reducing data size by " << mFrameSizeBytes;
3157                         maxDataSize -= mFrameSizeBytes;
3158                     }
3159                     *actualSize = maxDataSize;
3160                 }
3161                 command->set<StreamDescriptor::Command::Tag::burst>(maxDataSize);
3162             } else {
3163                 if (actualSize != nullptr) *actualSize = 0;
3164             }
3165         }
3166         return trigger;
3167     }
interceptRawReply(const StreamDescriptor::Reply &)3168     bool interceptRawReply(const StreamDescriptor::Reply&) override { return false; }
processValidReply(const StreamDescriptor::Reply & reply)3169     bool processValidReply(const StreamDescriptor::Reply& reply) override {
3170         if (reply.observable.frames != StreamDescriptor::Position::UNKNOWN) {
3171             if (mPreviousFrames.has_value()) {
3172                 if (reply.observable.frames > mPreviousFrames.value()) {
3173                     mObservablePositionIncrease = true;
3174                 } else if (reply.observable.frames < mPreviousFrames.value()) {
3175                     mRetrogradeObservablePosition = true;
3176                 }
3177             }
3178             mPreviousFrames = reply.observable.frames;
3179         }
3180 
3181         auto expected = mCommands->getExpectedStates();
3182         if (expected.count(reply.state) == 0) {
3183             std::string s =
3184                     std::string("Unexpected transition from the state ")
3185                             .append(mPreviousState.has_value() ? toString(mPreviousState.value())
3186                                                                : "<initial state>")
3187                             .append(" to ")
3188                             .append(toString(reply.state))
3189                             .append(" (expected one of ")
3190                             .append(::android::internal::ToString(expected))
3191                             .append(") caused by the ")
3192                             .append(toString(mCommands->getTrigger()));
3193             LOG(ERROR) << __func__ << ": " << s;
3194             mUnexpectedTransition = std::move(s);
3195             return false;
3196         }
3197         mCommands->advance(reply.state);
3198         mPreviousState = reply.state;
3199         return true;
3200     }
3201 
3202   protected:
3203     std::shared_ptr<StateSequence> mCommands;
3204     const size_t mFrameSizeBytes;
3205     std::optional<StreamDescriptor::State> mPreviousState;
3206     std::optional<int64_t> mPreviousFrames;
3207     bool mObservablePositionIncrease = false;
3208     bool mRetrogradeObservablePosition = false;
3209     std::string mUnexpectedTransition;
3210 };
3211 
3212 enum {
3213     NAMED_CMD_NAME,
3214     NAMED_CMD_DELAY_MS,
3215     NAMED_CMD_STREAM_TYPE,
3216     NAMED_CMD_CMDS,
3217     NAMED_CMD_VALIDATE_POS_INCREASE
3218 };
3219 enum class StreamTypeFilter { ANY, SYNC, ASYNC };
3220 using NamedCommandSequence =
3221         std::tuple<std::string, int /*cmdDelayMs*/, StreamTypeFilter,
3222                    std::shared_ptr<StateSequence>, bool /*validatePositionIncrease*/>;
3223 enum { PARAM_MODULE_NAME, PARAM_CMD_SEQ, PARAM_SETUP_SEQ };
3224 using StreamIoTestParameters =
3225         std::tuple<std::string /*moduleName*/, NamedCommandSequence, bool /*useSetupSequence2*/>;
3226 template <typename Stream>
3227 class AudioStreamIo : public AudioCoreModuleBase,
3228                       public testing::TestWithParam<StreamIoTestParameters> {
3229   public:
SetUp()3230     void SetUp() override {
3231         ASSERT_NO_FATAL_FAILURE(SetUpImpl(std::get<PARAM_MODULE_NAME>(GetParam())));
3232         ASSERT_NO_FATAL_FAILURE(SetUpModuleConfig());
3233     }
3234 
Run()3235     void Run() {
3236         const auto allPortConfigs =
3237                 moduleConfig->getPortConfigsForMixPorts(IOTraits<Stream>::is_input);
3238         if (allPortConfigs.empty()) {
3239             GTEST_SKIP() << "No mix ports have attached devices";
3240         }
3241         for (const auto& portConfig : allPortConfigs) {
3242             SCOPED_TRACE(portConfig.toString());
3243             const bool isNonBlocking =
3244                     IOTraits<Stream>::is_input
3245                             ? false
3246                             :
3247                             // TODO: Uncomment when support for asynchronous input is implemented.
3248                             /*isBitPositionFlagSet(
3249                               portConfig.flags.value().template get<AudioIoFlags::Tag::input>(),
3250                               AudioInputFlags::NON_BLOCKING) :*/
3251                             isBitPositionFlagSet(portConfig.flags.value()
3252                                                          .template get<AudioIoFlags::Tag::output>(),
3253                                                  AudioOutputFlags::NON_BLOCKING);
3254             if (auto streamType =
3255                         std::get<NAMED_CMD_STREAM_TYPE>(std::get<PARAM_CMD_SEQ>(GetParam()));
3256                 (isNonBlocking && streamType == StreamTypeFilter::SYNC) ||
3257                 (!isNonBlocking && streamType == StreamTypeFilter::ASYNC)) {
3258                 continue;
3259             }
3260             WithDebugFlags delayTransientStates = WithDebugFlags::createNested(*debug);
3261             delayTransientStates.flags().streamTransientStateDelayMs =
3262                     std::get<NAMED_CMD_DELAY_MS>(std::get<PARAM_CMD_SEQ>(GetParam()));
3263             ASSERT_NO_FATAL_FAILURE(delayTransientStates.SetUp(module.get()));
3264             const auto& commandsAndStates =
3265                     std::get<NAMED_CMD_CMDS>(std::get<PARAM_CMD_SEQ>(GetParam()));
3266             const bool validatePositionIncrease =
3267                     std::get<NAMED_CMD_VALIDATE_POS_INCREASE>(std::get<PARAM_CMD_SEQ>(GetParam()));
3268             if (!std::get<PARAM_SETUP_SEQ>(GetParam())) {
3269                 ASSERT_NO_FATAL_FAILURE(RunStreamIoCommandsImplSeq1(portConfig, commandsAndStates,
3270                                                                     validatePositionIncrease));
3271             } else {
3272                 ASSERT_NO_FATAL_FAILURE(RunStreamIoCommandsImplSeq2(portConfig, commandsAndStates,
3273                                                                     validatePositionIncrease));
3274             }
3275             if (isNonBlocking) {
3276                 // Also try running the same sequence with "aosp.forceTransientBurst" set.
3277                 // This will only work with the default implementation. When it works, the stream
3278                 // tries always to move to the 'TRANSFERRING' state after a burst.
3279                 // This helps to check more paths for our test scenarios.
3280                 WithModuleParameter forceTransientBurst("aosp.forceTransientBurst", Boolean{true});
3281                 if (forceTransientBurst.SetUpNoChecks(module.get(), true /*failureExpected*/)
3282                             .isOk()) {
3283                     if (!std::get<PARAM_SETUP_SEQ>(GetParam())) {
3284                         ASSERT_NO_FATAL_FAILURE(RunStreamIoCommandsImplSeq1(
3285                                 portConfig, commandsAndStates, validatePositionIncrease));
3286                     } else {
3287                         ASSERT_NO_FATAL_FAILURE(RunStreamIoCommandsImplSeq2(
3288                                 portConfig, commandsAndStates, validatePositionIncrease));
3289                     }
3290                 }
3291             } else if (!IOTraits<Stream>::is_input) {
3292                 // Also try running the same sequence with "aosp.forceSynchronousDrain" set.
3293                 // This will only work with the default implementation. When it works, the stream
3294                 // tries always to move to the 'IDLE' state after a drain.
3295                 // This helps to check more paths for our test scenarios.
3296                 WithModuleParameter forceSynchronousDrain("aosp.forceSynchronousDrain",
3297                                                           Boolean{true});
3298                 if (forceSynchronousDrain.SetUpNoChecks(module.get(), true /*failureExpected*/)
3299                             .isOk()) {
3300                     if (!std::get<PARAM_SETUP_SEQ>(GetParam())) {
3301                         ASSERT_NO_FATAL_FAILURE(RunStreamIoCommandsImplSeq1(
3302                                 portConfig, commandsAndStates, validatePositionIncrease));
3303                     } else {
3304                         ASSERT_NO_FATAL_FAILURE(RunStreamIoCommandsImplSeq2(
3305                                 portConfig, commandsAndStates, validatePositionIncrease));
3306                     }
3307                 }
3308             }
3309         }
3310     }
3311 
ValidateObservablePosition(const AudioPortConfig & devicePortConfig)3312     bool ValidateObservablePosition(const AudioPortConfig& devicePortConfig) {
3313         return !isTelephonyDeviceType(
3314                 devicePortConfig.ext.get<AudioPortExt::Tag::device>().device.type.type);
3315     }
3316 
3317     // Set up a patch first, then open a stream.
RunStreamIoCommandsImplSeq1(const AudioPortConfig & portConfig,std::shared_ptr<StateSequence> commandsAndStates,bool validatePositionIncrease)3318     void RunStreamIoCommandsImplSeq1(const AudioPortConfig& portConfig,
3319                                      std::shared_ptr<StateSequence> commandsAndStates,
3320                                      bool validatePositionIncrease) {
3321         auto devicePorts = moduleConfig->getConnectedDevicesPortsForMixPort(
3322                 IOTraits<Stream>::is_input, portConfig);
3323         ASSERT_FALSE(devicePorts.empty());
3324         auto devicePortConfig = moduleConfig->getSingleConfigForDevicePort(devicePorts[0]);
3325         SCOPED_TRACE(devicePortConfig.toString());
3326         WithAudioPatch patch(IOTraits<Stream>::is_input, portConfig, devicePortConfig);
3327         ASSERT_NO_FATAL_FAILURE(patch.SetUp(module.get()));
3328 
3329         WithStream<Stream> stream(patch.getPortConfig(IOTraits<Stream>::is_input));
3330         ASSERT_NO_FATAL_FAILURE(stream.SetUp(module.get(), kDefaultBufferSizeFrames));
3331         StreamLogicDefaultDriver driver(commandsAndStates,
3332                                         stream.getContext()->getFrameSizeBytes());
3333         typename IOTraits<Stream>::Worker worker(*stream.getContext(), &driver,
3334                                                  stream.getEventReceiver());
3335 
3336         LOG(DEBUG) << __func__ << ": starting worker...";
3337         ASSERT_TRUE(worker.start());
3338         LOG(DEBUG) << __func__ << ": joining worker...";
3339         worker.join();
3340         EXPECT_FALSE(worker.hasError()) << worker.getError();
3341         EXPECT_EQ("", driver.getUnexpectedStateTransition());
3342         if (ValidateObservablePosition(devicePortConfig)) {
3343             if (validatePositionIncrease) {
3344                 EXPECT_TRUE(driver.hasObservablePositionIncrease());
3345             }
3346             EXPECT_FALSE(driver.hasRetrogradeObservablePosition());
3347         }
3348     }
3349 
3350     // Open a stream, then set up a patch for it.
RunStreamIoCommandsImplSeq2(const AudioPortConfig & portConfig,std::shared_ptr<StateSequence> commandsAndStates,bool validatePositionIncrease)3351     void RunStreamIoCommandsImplSeq2(const AudioPortConfig& portConfig,
3352                                      std::shared_ptr<StateSequence> commandsAndStates,
3353                                      bool validatePositionIncrease) {
3354         WithStream<Stream> stream(portConfig);
3355         ASSERT_NO_FATAL_FAILURE(stream.SetUp(module.get(), kDefaultBufferSizeFrames));
3356         StreamLogicDefaultDriver driver(commandsAndStates,
3357                                         stream.getContext()->getFrameSizeBytes());
3358         typename IOTraits<Stream>::Worker worker(*stream.getContext(), &driver,
3359                                                  stream.getEventReceiver());
3360 
3361         auto devicePorts = moduleConfig->getConnectedDevicesPortsForMixPort(
3362                 IOTraits<Stream>::is_input, portConfig);
3363         ASSERT_FALSE(devicePorts.empty());
3364         auto devicePortConfig = moduleConfig->getSingleConfigForDevicePort(devicePorts[0]);
3365         SCOPED_TRACE(devicePortConfig.toString());
3366         WithAudioPatch patch(IOTraits<Stream>::is_input, stream.getPortConfig(), devicePortConfig);
3367         ASSERT_NO_FATAL_FAILURE(patch.SetUp(module.get()));
3368 
3369         LOG(DEBUG) << __func__ << ": starting worker...";
3370         ASSERT_TRUE(worker.start());
3371         LOG(DEBUG) << __func__ << ": joining worker...";
3372         worker.join();
3373         EXPECT_FALSE(worker.hasError()) << worker.getError();
3374         EXPECT_EQ("", driver.getUnexpectedStateTransition());
3375         if (ValidateObservablePosition(devicePortConfig)) {
3376             if (validatePositionIncrease) {
3377                 EXPECT_TRUE(driver.hasObservablePositionIncrease());
3378             }
3379             EXPECT_FALSE(driver.hasRetrogradeObservablePosition());
3380         }
3381     }
3382 };
3383 using AudioStreamIoIn = AudioStreamIo<IStreamIn>;
3384 using AudioStreamIoOut = AudioStreamIo<IStreamOut>;
3385 
3386 #define TEST_IN_AND_OUT_STREAM_IO(method_name)  \
3387     TEST_P(AudioStreamIoIn, method_name) {      \
3388         ASSERT_NO_FATAL_FAILURE(method_name()); \
3389     }                                           \
3390     TEST_P(AudioStreamIoOut, method_name) {     \
3391         ASSERT_NO_FATAL_FAILURE(method_name()); \
3392     }
3393 
3394 TEST_IN_AND_OUT_STREAM_IO(Run);
3395 
3396 // Tests specific to audio patches. The fixure class is named 'AudioModulePatch'
3397 // to avoid clashing with 'AudioPatch' class.
3398 class AudioModulePatch : public AudioCoreModule {
3399   public:
direction(bool isInput,bool capitalize)3400     static std::string direction(bool isInput, bool capitalize) {
3401         return isInput ? (capitalize ? "Input" : "input") : (capitalize ? "Output" : "output");
3402     }
3403 
SetUp()3404     void SetUp() override {
3405         ASSERT_NO_FATAL_FAILURE(AudioCoreModule::SetUp());
3406         ASSERT_NO_FATAL_FAILURE(SetUpModuleConfig());
3407     }
3408 
SetInvalidPatchHelper(int32_t expectedException,const std::vector<int32_t> & sources,const std::vector<int32_t> & sinks)3409     void SetInvalidPatchHelper(int32_t expectedException, const std::vector<int32_t>& sources,
3410                                const std::vector<int32_t>& sinks) {
3411         AudioPatch patch;
3412         patch.sourcePortConfigIds = sources;
3413         patch.sinkPortConfigIds = sinks;
3414         ASSERT_STATUS(expectedException, module->setAudioPatch(patch, &patch))
3415                 << "patch source ids: " << android::internal::ToString(sources)
3416                 << "; sink ids: " << android::internal::ToString(sinks);
3417     }
3418 
ResetPortConfigUsedByPatch(bool isInput)3419     void ResetPortConfigUsedByPatch(bool isInput) {
3420         auto srcSinkGroups = moduleConfig->getRoutableSrcSinkGroups(isInput);
3421         if (srcSinkGroups.empty()) {
3422             GTEST_SKIP() << "No routes to any attached " << direction(isInput, false) << " devices";
3423         }
3424         auto srcSinkGroup = *srcSinkGroups.begin();
3425         auto srcSink = *srcSinkGroup.second.begin();
3426         WithAudioPatch patch(srcSink.first, srcSink.second);
3427         ASSERT_NO_FATAL_FAILURE(patch.SetUp(module.get()));
3428         std::vector<int32_t> sourceAndSinkPortConfigIds(patch.get().sourcePortConfigIds);
3429         sourceAndSinkPortConfigIds.insert(sourceAndSinkPortConfigIds.end(),
3430                                           patch.get().sinkPortConfigIds.begin(),
3431                                           patch.get().sinkPortConfigIds.end());
3432         for (const auto portConfigId : sourceAndSinkPortConfigIds) {
3433             EXPECT_STATUS(EX_ILLEGAL_STATE, module->resetAudioPortConfig(portConfigId))
3434                     << "port config ID " << portConfigId;
3435         }
3436     }
3437 
SetInvalidPatch(bool isInput)3438     void SetInvalidPatch(bool isInput) {
3439         auto srcSinkPair = moduleConfig->getRoutableSrcSinkPair(isInput);
3440         if (!srcSinkPair.has_value()) {
3441             GTEST_SKIP() << "No routes to any attached " << direction(isInput, false) << " devices";
3442         }
3443         WithAudioPortConfig srcPortConfig(srcSinkPair.value().first);
3444         ASSERT_NO_FATAL_FAILURE(srcPortConfig.SetUp(module.get()));
3445         WithAudioPortConfig sinkPortConfig(srcSinkPair.value().second);
3446         ASSERT_NO_FATAL_FAILURE(sinkPortConfig.SetUp(module.get()));
3447         {  // Check that the pair can actually be used for setting up a patch.
3448             WithAudioPatch patch(srcPortConfig.get(), sinkPortConfig.get());
3449             ASSERT_NO_FATAL_FAILURE(patch.SetUp(module.get()));
3450         }
3451         EXPECT_NO_FATAL_FAILURE(
3452                 SetInvalidPatchHelper(EX_ILLEGAL_ARGUMENT, {}, {sinkPortConfig.getId()}));
3453         EXPECT_NO_FATAL_FAILURE(SetInvalidPatchHelper(
3454                 EX_ILLEGAL_ARGUMENT, {srcPortConfig.getId(), srcPortConfig.getId()},
3455                 {sinkPortConfig.getId()}));
3456         EXPECT_NO_FATAL_FAILURE(
3457                 SetInvalidPatchHelper(EX_ILLEGAL_ARGUMENT, {srcPortConfig.getId()}, {}));
3458         EXPECT_NO_FATAL_FAILURE(
3459                 SetInvalidPatchHelper(EX_ILLEGAL_ARGUMENT, {srcPortConfig.getId()},
3460                                       {sinkPortConfig.getId(), sinkPortConfig.getId()}));
3461 
3462         std::set<int32_t> portConfigIds;
3463         ASSERT_NO_FATAL_FAILURE(GetAllPortConfigIds(&portConfigIds));
3464         for (const auto portConfigId : GetNonExistentIds(portConfigIds)) {
3465             EXPECT_NO_FATAL_FAILURE(SetInvalidPatchHelper(EX_ILLEGAL_ARGUMENT, {portConfigId},
3466                                                           {sinkPortConfig.getId()}));
3467             EXPECT_NO_FATAL_FAILURE(SetInvalidPatchHelper(EX_ILLEGAL_ARGUMENT,
3468                                                           {srcPortConfig.getId()}, {portConfigId}));
3469         }
3470     }
3471 
SetNonRoutablePatch(bool isInput)3472     void SetNonRoutablePatch(bool isInput) {
3473         auto srcSinkPair = moduleConfig->getNonRoutableSrcSinkPair(isInput);
3474         if (!srcSinkPair.has_value()) {
3475             GTEST_SKIP() << "All possible source/sink pairs are routable";
3476         }
3477         WithAudioPatch patch(srcSinkPair.value().first, srcSinkPair.value().second);
3478         ASSERT_NO_FATAL_FAILURE(patch.SetUpPortConfigs(module.get()));
3479         EXPECT_STATUS(EX_ILLEGAL_ARGUMENT, patch.SetUpNoChecks(module.get()))
3480                 << "when setting up a patch from " << srcSinkPair.value().first.toString() << " to "
3481                 << srcSinkPair.value().second.toString() << " that does not have a route";
3482     }
3483 
SetPatch(bool isInput)3484     void SetPatch(bool isInput) {
3485         auto srcSinkGroups = moduleConfig->getRoutableSrcSinkGroups(isInput);
3486         if (srcSinkGroups.empty()) {
3487             GTEST_SKIP() << "No routes to any attached " << direction(isInput, false) << " devices";
3488         }
3489         for (const auto& srcSinkGroup : srcSinkGroups) {
3490             const auto& route = srcSinkGroup.first;
3491             std::vector<std::unique_ptr<WithAudioPatch>> patches;
3492             for (const auto& srcSink : srcSinkGroup.second) {
3493                 if (!route.isExclusive) {
3494                     patches.push_back(
3495                             std::make_unique<WithAudioPatch>(srcSink.first, srcSink.second));
3496                     EXPECT_NO_FATAL_FAILURE(patches[patches.size() - 1]->SetUp(module.get()));
3497                 } else {
3498                     WithAudioPatch patch(srcSink.first, srcSink.second);
3499                     EXPECT_NO_FATAL_FAILURE(patch.SetUp(module.get()));
3500                 }
3501             }
3502         }
3503     }
3504 
UpdatePatch(bool isInput)3505     void UpdatePatch(bool isInput) {
3506         auto srcSinkGroups = moduleConfig->getRoutableSrcSinkGroups(isInput);
3507         if (srcSinkGroups.empty()) {
3508             GTEST_SKIP() << "No routes to any attached " << direction(isInput, false) << " devices";
3509         }
3510         for (const auto& srcSinkGroup : srcSinkGroups) {
3511             for (const auto& srcSink : srcSinkGroup.second) {
3512                 WithAudioPatch patch(srcSink.first, srcSink.second);
3513                 ASSERT_NO_FATAL_FAILURE(patch.SetUp(module.get()));
3514                 AudioPatch ignored;
3515                 EXPECT_NO_FATAL_FAILURE(module->setAudioPatch(patch.get(), &ignored));
3516             }
3517         }
3518     }
3519 
UpdateInvalidPatchId(bool isInput)3520     void UpdateInvalidPatchId(bool isInput) {
3521         auto srcSinkGroups = moduleConfig->getRoutableSrcSinkGroups(isInput);
3522         if (srcSinkGroups.empty()) {
3523             GTEST_SKIP() << "No routes to any attached " << direction(isInput, false) << " devices";
3524         }
3525         // First, set up a patch to ensure that its settings are accepted.
3526         auto srcSinkGroup = *srcSinkGroups.begin();
3527         auto srcSink = *srcSinkGroup.second.begin();
3528         WithAudioPatch patch(srcSink.first, srcSink.second);
3529         ASSERT_NO_FATAL_FAILURE(patch.SetUp(module.get()));
3530         // Then use the same patch setting, except for having an invalid ID.
3531         std::set<int32_t> patchIds;
3532         ASSERT_NO_FATAL_FAILURE(GetAllPatchIds(&patchIds));
3533         for (const auto patchId : GetNonExistentIds(patchIds)) {
3534             AudioPatch patchWithNonExistendId = patch.get();
3535             patchWithNonExistendId.id = patchId;
3536             EXPECT_STATUS(EX_ILLEGAL_ARGUMENT,
3537                           module->setAudioPatch(patchWithNonExistendId, &patchWithNonExistendId))
3538                     << "patch ID " << patchId;
3539         }
3540     }
3541 };
3542 
3543 // Not all tests require both directions, so parametrization would require
3544 // more abstractions.
3545 #define TEST_PATCH_BOTH_DIRECTIONS(method_name)      \
3546     TEST_P(AudioModulePatch, method_name##Input) {   \
3547         ASSERT_NO_FATAL_FAILURE(method_name(true));  \
3548     }                                                \
3549     TEST_P(AudioModulePatch, method_name##Output) {  \
3550         ASSERT_NO_FATAL_FAILURE(method_name(false)); \
3551     }
3552 
3553 TEST_PATCH_BOTH_DIRECTIONS(ResetPortConfigUsedByPatch);
3554 TEST_PATCH_BOTH_DIRECTIONS(SetInvalidPatch);
3555 TEST_PATCH_BOTH_DIRECTIONS(SetNonRoutablePatch);
3556 TEST_PATCH_BOTH_DIRECTIONS(SetPatch);
3557 TEST_PATCH_BOTH_DIRECTIONS(UpdateInvalidPatchId);
3558 TEST_PATCH_BOTH_DIRECTIONS(UpdatePatch);
3559 
TEST_P(AudioModulePatch,ResetInvalidPatchId)3560 TEST_P(AudioModulePatch, ResetInvalidPatchId) {
3561     std::set<int32_t> patchIds;
3562     ASSERT_NO_FATAL_FAILURE(GetAllPatchIds(&patchIds));
3563     for (const auto patchId : GetNonExistentIds(patchIds)) {
3564         EXPECT_STATUS(EX_ILLEGAL_ARGUMENT, module->resetAudioPatch(patchId))
3565                 << "patch ID " << patchId;
3566     }
3567 }
3568 
3569 class AudioCoreSoundDose : public AudioCoreModuleBase, public testing::TestWithParam<std::string> {
3570   public:
3571     class NoOpHalSoundDoseCallback : public ISoundDose::BnHalSoundDoseCallback {
3572       public:
3573         ndk::ScopedAStatus onMomentaryExposureWarning(float in_currentDbA,
3574                                                       const AudioDevice& in_audioDevice) override;
3575         ndk::ScopedAStatus onNewMelValues(
3576                 const ISoundDose::IHalSoundDoseCallback::MelRecord& in_melRecord,
3577                 const AudioDevice& in_audioDevice) override;
3578     };
3579 
SetUp()3580     void SetUp() override {
3581         ASSERT_NO_FATAL_FAILURE(SetUpImpl(GetParam()));
3582         ASSERT_IS_OK(module->getSoundDose(&soundDose));
3583         callback = ndk::SharedRefBase::make<NoOpHalSoundDoseCallback>();
3584     }
3585 
TearDown()3586     void TearDown() override { ASSERT_NO_FATAL_FAILURE(TearDownImpl()); }
3587 
3588     std::shared_ptr<ISoundDose> soundDose;
3589     std::shared_ptr<ISoundDose::IHalSoundDoseCallback> callback;
3590 };
3591 
onMomentaryExposureWarning(float in_currentDbA,const AudioDevice & in_audioDevice)3592 ndk::ScopedAStatus AudioCoreSoundDose::NoOpHalSoundDoseCallback::onMomentaryExposureWarning(
3593         float in_currentDbA, const AudioDevice& in_audioDevice) {
3594     // Do nothing
3595     (void)in_currentDbA;
3596     (void)in_audioDevice;
3597     LOG(INFO) << "NoOpHalSoundDoseCallback::onMomentaryExposureWarning called";
3598 
3599     return ndk::ScopedAStatus::ok();
3600 }
3601 
onNewMelValues(const ISoundDose::IHalSoundDoseCallback::MelRecord & in_melRecord,const AudioDevice & in_audioDevice)3602 ndk::ScopedAStatus AudioCoreSoundDose::NoOpHalSoundDoseCallback::onNewMelValues(
3603         const ISoundDose::IHalSoundDoseCallback::MelRecord& in_melRecord,
3604         const AudioDevice& in_audioDevice) {
3605     // Do nothing
3606     (void)in_melRecord;
3607     (void)in_audioDevice;
3608     LOG(INFO) << "NoOpHalSoundDoseCallback::onNewMelValues called";
3609 
3610     return ndk::ScopedAStatus::ok();
3611 }
3612 
3613 // @VsrTest = VSR-5.5-002.001
TEST_P(AudioCoreSoundDose,SameInstance)3614 TEST_P(AudioCoreSoundDose, SameInstance) {
3615     if (soundDose == nullptr) {
3616         GTEST_SKIP() << "SoundDose is not supported";
3617     }
3618     std::shared_ptr<ISoundDose> soundDose2;
3619     EXPECT_IS_OK(module->getSoundDose(&soundDose2));
3620     ASSERT_NE(nullptr, soundDose2.get());
3621     EXPECT_EQ(soundDose->asBinder(), soundDose2->asBinder())
3622             << "getSoundDose must return the same interface instance across invocations";
3623 }
3624 
3625 // @VsrTest = VSR-5.5-002.001
TEST_P(AudioCoreSoundDose,GetSetOutputRs2UpperBound)3626 TEST_P(AudioCoreSoundDose, GetSetOutputRs2UpperBound) {
3627     if (soundDose == nullptr) {
3628         GTEST_SKIP() << "SoundDose is not supported";
3629     }
3630 
3631     bool isSupported = false;
3632     EXPECT_NO_FATAL_FAILURE(TestAccessors<float>(soundDose.get(),
3633                                                  &ISoundDose::getOutputRs2UpperBound,
3634                                                  &ISoundDose::setOutputRs2UpperBound,
3635                                                  /*validValues=*/{80.f, 90.f, 100.f},
3636                                                  /*invalidValues=*/{79.f, 101.f}, &isSupported));
3637     EXPECT_TRUE(isSupported) << "Getting/Setting RS2 upper bound must be supported";
3638 }
3639 
3640 // @VsrTest = VSR-5.5-002.001
TEST_P(AudioCoreSoundDose,CheckDefaultRs2UpperBound)3641 TEST_P(AudioCoreSoundDose, CheckDefaultRs2UpperBound) {
3642     if (soundDose == nullptr) {
3643         GTEST_SKIP() << "SoundDose is not supported";
3644     }
3645 
3646     float rs2Value;
3647     ASSERT_IS_OK(soundDose->getOutputRs2UpperBound(&rs2Value));
3648     EXPECT_EQ(rs2Value, ISoundDose::DEFAULT_MAX_RS2);
3649 }
3650 
3651 // @VsrTest = VSR-5.5-002.001
TEST_P(AudioCoreSoundDose,RegisterSoundDoseCallbackTwiceThrowsException)3652 TEST_P(AudioCoreSoundDose, RegisterSoundDoseCallbackTwiceThrowsException) {
3653     if (soundDose == nullptr) {
3654         GTEST_SKIP() << "SoundDose is not supported";
3655     }
3656 
3657     ASSERT_IS_OK(soundDose->registerSoundDoseCallback(callback));
3658     EXPECT_STATUS(EX_ILLEGAL_STATE, soundDose->registerSoundDoseCallback(callback))
3659             << "Registering sound dose callback twice should throw EX_ILLEGAL_STATE";
3660 }
3661 
3662 // @VsrTest = VSR-5.5-002.001
TEST_P(AudioCoreSoundDose,RegisterSoundDoseNullCallbackThrowsException)3663 TEST_P(AudioCoreSoundDose, RegisterSoundDoseNullCallbackThrowsException) {
3664     if (soundDose == nullptr) {
3665         GTEST_SKIP() << "SoundDose is not supported";
3666     }
3667 
3668     EXPECT_STATUS(EX_ILLEGAL_ARGUMENT, soundDose->registerSoundDoseCallback(nullptr))
3669             << "Registering nullptr sound dose callback should throw EX_ILLEGAL_ARGUMENT";
3670 }
3671 
3672 INSTANTIATE_TEST_SUITE_P(AudioCoreModuleTest, AudioCoreModule,
3673                          testing::ValuesIn(android::getAidlHalInstanceNames(IModule::descriptor)),
3674                          android::PrintInstanceNameToString);
3675 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(AudioCoreModule);
3676 INSTANTIATE_TEST_SUITE_P(AudioCoreBluetoothTest, AudioCoreBluetooth,
3677                          testing::ValuesIn(android::getAidlHalInstanceNames(IModule::descriptor)),
3678                          android::PrintInstanceNameToString);
3679 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(AudioCoreBluetooth);
3680 INSTANTIATE_TEST_SUITE_P(AudioCoreBluetoothA2dpTest, AudioCoreBluetoothA2dp,
3681                          testing::ValuesIn(android::getAidlHalInstanceNames(IModule::descriptor)),
3682                          android::PrintInstanceNameToString);
3683 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(AudioCoreBluetoothA2dp);
3684 INSTANTIATE_TEST_SUITE_P(AudioCoreBluetoothLeTest, AudioCoreBluetoothLe,
3685                          testing::ValuesIn(android::getAidlHalInstanceNames(IModule::descriptor)),
3686                          android::PrintInstanceNameToString);
3687 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(AudioCoreBluetoothLe);
3688 INSTANTIATE_TEST_SUITE_P(AudioCoreTelephonyTest, AudioCoreTelephony,
3689                          testing::ValuesIn(android::getAidlHalInstanceNames(IModule::descriptor)),
3690                          android::PrintInstanceNameToString);
3691 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(AudioCoreTelephony);
3692 INSTANTIATE_TEST_SUITE_P(AudioStreamInTest, AudioStreamIn,
3693                          testing::ValuesIn(android::getAidlHalInstanceNames(IModule::descriptor)),
3694                          android::PrintInstanceNameToString);
3695 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(AudioStreamIn);
3696 INSTANTIATE_TEST_SUITE_P(AudioStreamOutTest, AudioStreamOut,
3697                          testing::ValuesIn(android::getAidlHalInstanceNames(IModule::descriptor)),
3698                          android::PrintInstanceNameToString);
3699 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(AudioStreamOut);
3700 INSTANTIATE_TEST_SUITE_P(AudioCoreSoundDoseTest, AudioCoreSoundDose,
3701                          testing::ValuesIn(android::getAidlHalInstanceNames(IModule::descriptor)),
3702                          android::PrintInstanceNameToString);
3703 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(AudioCoreSoundDose);
3704 
3705 // This is the value used in test sequences for which the test needs to ensure
3706 // that the HAL stays in a transient state long enough to receive the next command.
3707 static const int kStreamTransientStateTransitionDelayMs = 3000;
3708 
3709 // TODO: Add async test cases for input once it is implemented.
3710 
makeBurstCommands(bool isSync)3711 std::shared_ptr<StateSequence> makeBurstCommands(bool isSync) {
3712     using State = StreamDescriptor::State;
3713     auto d = std::make_unique<StateDag>();
3714     StateDag::Node last = d->makeFinalNode(State::ACTIVE);
3715     // Use a couple of bursts to ensure that the driver starts reporting the position.
3716     StateDag::Node active2 = d->makeNode(State::ACTIVE, kBurstCommand, last);
3717     StateDag::Node active = d->makeNode(State::ACTIVE, kBurstCommand, active2);
3718     StateDag::Node idle = d->makeNode(State::IDLE, kBurstCommand, active);
3719     if (!isSync) {
3720         // Allow optional routing via the TRANSFERRING state on bursts.
3721         active2.children().push_back(d->makeNode(State::TRANSFERRING, kTransferReadyEvent, last));
3722         active.children().push_back(d->makeNode(State::TRANSFERRING, kTransferReadyEvent, active2));
3723         idle.children().push_back(d->makeNode(State::TRANSFERRING, kTransferReadyEvent, active));
3724     }
3725     d->makeNode(State::STANDBY, kStartCommand, idle);
3726     return std::make_shared<StateSequenceFollower>(std::move(d));
3727 }
3728 static const NamedCommandSequence kReadSeq =
3729         std::make_tuple(std::string("Read"), 0, StreamTypeFilter::ANY, makeBurstCommands(true),
3730                         true /*validatePositionIncrease*/);
3731 static const NamedCommandSequence kWriteSyncSeq =
3732         std::make_tuple(std::string("Write"), 0, StreamTypeFilter::SYNC, makeBurstCommands(true),
3733                         true /*validatePositionIncrease*/);
3734 static const NamedCommandSequence kWriteAsyncSeq =
3735         std::make_tuple(std::string("Write"), 0, StreamTypeFilter::ASYNC, makeBurstCommands(false),
3736                         true /*validatePositionIncrease*/);
3737 
makeAsyncDrainCommands(bool isInput)3738 std::shared_ptr<StateSequence> makeAsyncDrainCommands(bool isInput) {
3739     using State = StreamDescriptor::State;
3740     auto d = std::make_unique<StateDag>();
3741     if (isInput) {
3742         d->makeNodes({std::make_pair(State::STANDBY, kStartCommand),
3743                       std::make_pair(State::IDLE, kBurstCommand),
3744                       std::make_pair(State::ACTIVE, kDrainInCommand),
3745                       std::make_pair(State::DRAINING, kStartCommand),
3746                       std::make_pair(State::ACTIVE, kDrainInCommand)},
3747                      State::DRAINING);
3748     } else {
3749         StateDag::Node draining =
3750                 d->makeNodes({std::make_pair(State::DRAINING, kBurstCommand),
3751                               std::make_pair(State::TRANSFERRING, kDrainOutAllCommand)},
3752                              State::DRAINING);
3753         StateDag::Node idle =
3754                 d->makeNodes({std::make_pair(State::IDLE, kBurstCommand),
3755                               std::make_pair(State::TRANSFERRING, kDrainOutAllCommand)},
3756                              draining);
3757         // If we get straight into ACTIVE on burst, no further testing is possible.
3758         draining.children().push_back(d->makeFinalNode(State::ACTIVE));
3759         idle.children().push_back(d->makeFinalNode(State::ACTIVE));
3760         d->makeNode(State::STANDBY, kStartCommand, idle);
3761     }
3762     return std::make_shared<StateSequenceFollower>(std::move(d));
3763 }
3764 static const NamedCommandSequence kWriteDrainAsyncSeq = std::make_tuple(
3765         std::string("WriteDrain"), kStreamTransientStateTransitionDelayMs, StreamTypeFilter::ASYNC,
3766         makeAsyncDrainCommands(false), false /*validatePositionIncrease*/);
3767 static const NamedCommandSequence kDrainInSeq =
3768         std::make_tuple(std::string("Drain"), 0, StreamTypeFilter::ANY,
3769                         makeAsyncDrainCommands(true), false /*validatePositionIncrease*/);
3770 
makeDrainOutCommands(bool isSync)3771 std::shared_ptr<StateSequence> makeDrainOutCommands(bool isSync) {
3772     using State = StreamDescriptor::State;
3773     auto d = std::make_unique<StateDag>();
3774     StateDag::Node last = d->makeFinalNode(State::IDLE);
3775     StateDag::Node active = d->makeNodes(
3776             {std::make_pair(State::ACTIVE, kDrainOutAllCommand),
3777              std::make_pair(State::DRAINING, isSync ? TransitionTrigger(kGetStatusCommand)
3778                                                     : TransitionTrigger(kDrainReadyEvent))},
3779             last);
3780     StateDag::Node idle = d->makeNode(State::IDLE, kBurstCommand, active);
3781     if (!isSync) {
3782         idle.children().push_back(d->makeNode(State::TRANSFERRING, kTransferReadyEvent, active));
3783     } else {
3784         active.children().push_back(last);
3785     }
3786     d->makeNode(State::STANDBY, kStartCommand, idle);
3787     return std::make_shared<StateSequenceFollower>(std::move(d));
3788 }
3789 static const NamedCommandSequence kDrainOutSyncSeq =
3790         std::make_tuple(std::string("Drain"), 0, StreamTypeFilter::SYNC, makeDrainOutCommands(true),
3791                         false /*validatePositionIncrease*/);
3792 static const NamedCommandSequence kDrainOutAsyncSeq =
3793         std::make_tuple(std::string("Drain"), 0, StreamTypeFilter::ASYNC,
3794                         makeDrainOutCommands(false), false /*validatePositionIncrease*/);
3795 
makeDrainPauseOutCommands(bool isSync)3796 std::shared_ptr<StateSequence> makeDrainPauseOutCommands(bool isSync) {
3797     using State = StreamDescriptor::State;
3798     auto d = std::make_unique<StateDag>();
3799     StateDag::Node draining = d->makeNodes({std::make_pair(State::DRAINING, kPauseCommand),
3800                                             std::make_pair(State::DRAIN_PAUSED, kStartCommand),
3801                                             std::make_pair(State::DRAINING, kPauseCommand),
3802                                             std::make_pair(State::DRAIN_PAUSED, kBurstCommand)},
3803                                            isSync ? State::PAUSED : State::TRANSFER_PAUSED);
3804     StateDag::Node active = d->makeNode(State::ACTIVE, kDrainOutAllCommand, draining);
3805     StateDag::Node idle = d->makeNode(State::IDLE, kBurstCommand, active);
3806     if (!isSync) {
3807         idle.children().push_back(d->makeNode(State::TRANSFERRING, kDrainOutAllCommand, draining));
3808     } else {
3809         // If we get straight into IDLE on drain, no further testing is possible.
3810         active.children().push_back(d->makeFinalNode(State::IDLE));
3811     }
3812     d->makeNode(State::STANDBY, kStartCommand, idle);
3813     return std::make_shared<StateSequenceFollower>(std::move(d));
3814 }
3815 static const NamedCommandSequence kDrainPauseOutSyncSeq = std::make_tuple(
3816         std::string("DrainPause"), kStreamTransientStateTransitionDelayMs, StreamTypeFilter::SYNC,
3817         makeDrainPauseOutCommands(true), false /*validatePositionIncrease*/);
3818 static const NamedCommandSequence kDrainPauseOutAsyncSeq = std::make_tuple(
3819         std::string("DrainPause"), kStreamTransientStateTransitionDelayMs, StreamTypeFilter::ASYNC,
3820         makeDrainPauseOutCommands(false), false /*validatePositionIncrease*/);
3821 
3822 // This sequence also verifies that the capture / presentation position is not reset on standby.
makeStandbyCommands(bool isInput,bool isSync)3823 std::shared_ptr<StateSequence> makeStandbyCommands(bool isInput, bool isSync) {
3824     using State = StreamDescriptor::State;
3825     auto d = std::make_unique<StateDag>();
3826     if (isInput) {
3827         d->makeNodes({std::make_pair(State::STANDBY, kStartCommand),
3828                       std::make_pair(State::IDLE, kStandbyCommand),
3829                       std::make_pair(State::STANDBY, kStartCommand),
3830                       std::make_pair(State::IDLE, kBurstCommand),
3831                       std::make_pair(State::ACTIVE, kPauseCommand),
3832                       std::make_pair(State::PAUSED, kFlushCommand),
3833                       std::make_pair(State::STANDBY, kStartCommand),
3834                       std::make_pair(State::IDLE, kBurstCommand)},
3835                      State::ACTIVE);
3836     } else {
3837         StateDag::Node idle3 =
3838                 d->makeNode(State::IDLE, kBurstCommand, d->makeFinalNode(State::ACTIVE));
3839         StateDag::Node idle2 = d->makeNodes({std::make_pair(State::IDLE, kStandbyCommand),
3840                                              std::make_pair(State::STANDBY, kStartCommand)},
3841                                             idle3);
3842         StateDag::Node active = d->makeNodes({std::make_pair(State::ACTIVE, kPauseCommand),
3843                                               std::make_pair(State::PAUSED, kFlushCommand)},
3844                                              idle2);
3845         StateDag::Node idle = d->makeNode(State::IDLE, kBurstCommand, active);
3846         if (!isSync) {
3847             idle3.children().push_back(d->makeFinalNode(State::TRANSFERRING));
3848             StateDag::Node transferring =
3849                     d->makeNodes({std::make_pair(State::TRANSFERRING, kPauseCommand),
3850                                   std::make_pair(State::TRANSFER_PAUSED, kFlushCommand)},
3851                                  idle2);
3852             idle.children().push_back(transferring);
3853         }
3854         d->makeNodes({std::make_pair(State::STANDBY, kStartCommand),
3855                       std::make_pair(State::IDLE, kStandbyCommand),
3856                       std::make_pair(State::STANDBY, kStartCommand)},
3857                      idle);
3858     }
3859     return std::make_shared<StateSequenceFollower>(std::move(d));
3860 }
3861 static const NamedCommandSequence kStandbyInSeq =
3862         std::make_tuple(std::string("Standby"), 0, StreamTypeFilter::ANY,
3863                         makeStandbyCommands(true, false), false /*validatePositionIncrease*/);
3864 static const NamedCommandSequence kStandbyOutSyncSeq =
3865         std::make_tuple(std::string("Standby"), 0, StreamTypeFilter::SYNC,
3866                         makeStandbyCommands(false, true), false /*validatePositionIncrease*/);
3867 static const NamedCommandSequence kStandbyOutAsyncSeq = std::make_tuple(
3868         std::string("Standby"), kStreamTransientStateTransitionDelayMs, StreamTypeFilter::ASYNC,
3869         makeStandbyCommands(false, false), false /*validatePositionIncrease*/);
3870 
makePauseCommands(bool isInput,bool isSync)3871 std::shared_ptr<StateSequence> makePauseCommands(bool isInput, bool isSync) {
3872     using State = StreamDescriptor::State;
3873     auto d = std::make_unique<StateDag>();
3874     if (isInput) {
3875         d->makeNodes({std::make_pair(State::STANDBY, kStartCommand),
3876                       std::make_pair(State::IDLE, kBurstCommand),
3877                       std::make_pair(State::ACTIVE, kPauseCommand),
3878                       std::make_pair(State::PAUSED, kBurstCommand),
3879                       std::make_pair(State::ACTIVE, kPauseCommand),
3880                       std::make_pair(State::PAUSED, kFlushCommand)},
3881                      State::STANDBY);
3882     } else {
3883         StateDag::Node idle = d->makeNodes({std::make_pair(State::IDLE, kBurstCommand),
3884                                             std::make_pair(State::ACTIVE, kPauseCommand),
3885                                             std::make_pair(State::PAUSED, kStartCommand),
3886                                             std::make_pair(State::ACTIVE, kPauseCommand),
3887                                             std::make_pair(State::PAUSED, kBurstCommand),
3888                                             std::make_pair(State::PAUSED, kStartCommand),
3889                                             std::make_pair(State::ACTIVE, kPauseCommand)},
3890                                            State::PAUSED);
3891         if (!isSync) {
3892             idle.children().push_back(
3893                     d->makeNodes({std::make_pair(State::TRANSFERRING, kPauseCommand),
3894                                   std::make_pair(State::TRANSFER_PAUSED, kStartCommand),
3895                                   std::make_pair(State::TRANSFERRING, kPauseCommand),
3896                                   std::make_pair(State::TRANSFER_PAUSED, kDrainOutAllCommand),
3897                                   std::make_pair(State::DRAIN_PAUSED, kBurstCommand)},
3898                                  State::TRANSFER_PAUSED));
3899         }
3900         d->makeNode(State::STANDBY, kStartCommand, idle);
3901     }
3902     return std::make_shared<StateSequenceFollower>(std::move(d));
3903 }
3904 static const NamedCommandSequence kPauseInSeq =
3905         std::make_tuple(std::string("Pause"), 0, StreamTypeFilter::ANY,
3906                         makePauseCommands(true, false), false /*validatePositionIncrease*/);
3907 static const NamedCommandSequence kPauseOutSyncSeq =
3908         std::make_tuple(std::string("Pause"), 0, StreamTypeFilter::SYNC,
3909                         makePauseCommands(false, true), false /*validatePositionIncrease*/);
3910 static const NamedCommandSequence kPauseOutAsyncSeq = std::make_tuple(
3911         std::string("Pause"), kStreamTransientStateTransitionDelayMs, StreamTypeFilter::ASYNC,
3912         makePauseCommands(false, false), false /*validatePositionIncrease*/);
3913 
makeFlushCommands(bool isInput,bool isSync)3914 std::shared_ptr<StateSequence> makeFlushCommands(bool isInput, bool isSync) {
3915     using State = StreamDescriptor::State;
3916     auto d = std::make_unique<StateDag>();
3917     if (isInput) {
3918         d->makeNodes({std::make_pair(State::STANDBY, kStartCommand),
3919                       std::make_pair(State::IDLE, kBurstCommand),
3920                       std::make_pair(State::ACTIVE, kPauseCommand),
3921                       std::make_pair(State::PAUSED, kFlushCommand)},
3922                      State::STANDBY);
3923     } else {
3924         StateDag::Node last = d->makeFinalNode(State::IDLE);
3925         StateDag::Node idle = d->makeNodes({std::make_pair(State::IDLE, kBurstCommand),
3926                                             std::make_pair(State::ACTIVE, kPauseCommand),
3927                                             std::make_pair(State::PAUSED, kFlushCommand)},
3928                                            last);
3929         if (!isSync) {
3930             idle.children().push_back(
3931                     d->makeNodes({std::make_pair(State::TRANSFERRING, kPauseCommand),
3932                                   std::make_pair(State::TRANSFER_PAUSED, kFlushCommand)},
3933                                  last));
3934         }
3935         d->makeNode(State::STANDBY, kStartCommand, idle);
3936     }
3937     return std::make_shared<StateSequenceFollower>(std::move(d));
3938 }
3939 static const NamedCommandSequence kFlushInSeq =
3940         std::make_tuple(std::string("Flush"), 0, StreamTypeFilter::ANY,
3941                         makeFlushCommands(true, false), false /*validatePositionIncrease*/);
3942 static const NamedCommandSequence kFlushOutSyncSeq =
3943         std::make_tuple(std::string("Flush"), 0, StreamTypeFilter::SYNC,
3944                         makeFlushCommands(false, true), false /*validatePositionIncrease*/);
3945 static const NamedCommandSequence kFlushOutAsyncSeq = std::make_tuple(
3946         std::string("Flush"), kStreamTransientStateTransitionDelayMs, StreamTypeFilter::ASYNC,
3947         makeFlushCommands(false, false), false /*validatePositionIncrease*/);
3948 
makeDrainPauseFlushOutCommands(bool isSync)3949 std::shared_ptr<StateSequence> makeDrainPauseFlushOutCommands(bool isSync) {
3950     using State = StreamDescriptor::State;
3951     auto d = std::make_unique<StateDag>();
3952     StateDag::Node draining = d->makeNodes({std::make_pair(State::DRAINING, kPauseCommand),
3953                                             std::make_pair(State::DRAIN_PAUSED, kFlushCommand)},
3954                                            State::IDLE);
3955     StateDag::Node active = d->makeNode(State::ACTIVE, kDrainOutAllCommand, draining);
3956     StateDag::Node idle = d->makeNode(State::IDLE, kBurstCommand, active);
3957     if (!isSync) {
3958         idle.children().push_back(d->makeNode(State::TRANSFERRING, kDrainOutAllCommand, draining));
3959     } else {
3960         // If we get straight into IDLE on drain, no further testing is possible.
3961         active.children().push_back(d->makeFinalNode(State::IDLE));
3962     }
3963     d->makeNode(State::STANDBY, kStartCommand, idle);
3964     return std::make_shared<StateSequenceFollower>(std::move(d));
3965 }
3966 static const NamedCommandSequence kDrainPauseFlushOutSyncSeq =
3967         std::make_tuple(std::string("DrainPauseFlush"), kStreamTransientStateTransitionDelayMs,
3968                         StreamTypeFilter::SYNC, makeDrainPauseFlushOutCommands(true),
3969                         false /*validatePositionIncrease*/);
3970 static const NamedCommandSequence kDrainPauseFlushOutAsyncSeq =
3971         std::make_tuple(std::string("DrainPauseFlush"), kStreamTransientStateTransitionDelayMs,
3972                         StreamTypeFilter::ASYNC, makeDrainPauseFlushOutCommands(false),
3973                         false /*validatePositionIncrease*/);
3974 
3975 // Note, this isn't the "official" enum printer, it is only used to make the test name suffix.
PrintStreamFilterToString(StreamTypeFilter filter)3976 std::string PrintStreamFilterToString(StreamTypeFilter filter) {
3977     switch (filter) {
3978         case StreamTypeFilter::ANY:
3979             return "";
3980         case StreamTypeFilter::SYNC:
3981             return "Sync";
3982         case StreamTypeFilter::ASYNC:
3983             return "Async";
3984     }
3985     return std::string("Unknown").append(std::to_string(static_cast<int32_t>(filter)));
3986 }
GetStreamIoTestName(const testing::TestParamInfo<StreamIoTestParameters> & info)3987 std::string GetStreamIoTestName(const testing::TestParamInfo<StreamIoTestParameters>& info) {
3988     return android::PrintInstanceNameToString(
3989                    testing::TestParamInfo<std::string>{std::get<PARAM_MODULE_NAME>(info.param),
3990                                                        info.index})
3991             .append("_")
3992             .append(std::get<NAMED_CMD_NAME>(std::get<PARAM_CMD_SEQ>(info.param)))
3993             .append(PrintStreamFilterToString(
3994                     std::get<NAMED_CMD_STREAM_TYPE>(std::get<PARAM_CMD_SEQ>(info.param))))
3995             .append("_SetupSeq")
3996             .append(std::get<PARAM_SETUP_SEQ>(info.param) ? "2" : "1");
3997 }
3998 
3999 INSTANTIATE_TEST_SUITE_P(
4000         AudioStreamIoInTest, AudioStreamIoIn,
4001         testing::Combine(testing::ValuesIn(android::getAidlHalInstanceNames(IModule::descriptor)),
4002                          testing::Values(kReadSeq, kDrainInSeq, kStandbyInSeq, kPauseInSeq,
4003                                          kFlushInSeq),
4004                          testing::Values(false, true)),
4005         GetStreamIoTestName);
4006 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(AudioStreamIoIn);
4007 INSTANTIATE_TEST_SUITE_P(
4008         AudioStreamIoOutTest, AudioStreamIoOut,
4009         testing::Combine(testing::ValuesIn(android::getAidlHalInstanceNames(IModule::descriptor)),
4010                          testing::Values(kWriteSyncSeq, kWriteAsyncSeq, kWriteDrainAsyncSeq,
4011                                          kDrainOutSyncSeq, kDrainPauseOutSyncSeq,
4012                                          kDrainPauseOutAsyncSeq, kStandbyOutSyncSeq,
4013                                          kStandbyOutAsyncSeq,
4014                                          kPauseOutSyncSeq,  // kPauseOutAsyncSeq,
4015                                          kFlushOutSyncSeq, kFlushOutAsyncSeq,
4016                                          kDrainPauseFlushOutSyncSeq, kDrainPauseFlushOutAsyncSeq),
4017                          testing::Values(false, true)),
4018         GetStreamIoTestName);
4019 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(AudioStreamIoOut);
4020 
4021 INSTANTIATE_TEST_SUITE_P(AudioPatchTest, AudioModulePatch,
4022                          testing::ValuesIn(android::getAidlHalInstanceNames(IModule::descriptor)),
4023                          android::PrintInstanceNameToString);
4024 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(AudioModulePatch);
4025 
getRemoteSubmixModuleInstance()4026 static std::vector<std::string> getRemoteSubmixModuleInstance() {
4027     auto instances = android::getAidlHalInstanceNames(IModule::descriptor);
4028     for (auto instance : instances) {
4029         if (instance.find("r_submix") != std::string::npos)
4030             return (std::vector<std::string>{instance});
4031     }
4032     return {};
4033 }
4034 
4035 template <typename Stream>
4036 class WithRemoteSubmix {
4037   public:
4038     WithRemoteSubmix() = default;
WithRemoteSubmix(AudioDeviceAddress address)4039     WithRemoteSubmix(AudioDeviceAddress address) : mAddress(address) {}
4040     WithRemoteSubmix(const WithRemoteSubmix&) = delete;
4041     WithRemoteSubmix& operator=(const WithRemoteSubmix&) = delete;
getAudioPort()4042     std::optional<AudioPort> getAudioPort() {
4043         AudioDeviceType deviceType = IOTraits<Stream>::is_input ? AudioDeviceType::IN_SUBMIX
4044                                                                 : AudioDeviceType::OUT_SUBMIX;
4045         auto ports = mModuleConfig->getAudioPortsForDeviceTypes(
4046                 std::vector<AudioDeviceType>{deviceType},
4047                 AudioDeviceDescription::CONNECTION_VIRTUAL);
4048         if (!ports.empty()) return ports.front();
4049         return {};
4050     }
4051     /* Connect remote submix external device */
SetUpPortConnection()4052     void SetUpPortConnection() {
4053         auto port = getAudioPort();
4054         ASSERT_TRUE(port.has_value()) << "Device AudioPort for remote submix not found";
4055         if (mAddress.has_value()) {
4056             port.value().ext.template get<AudioPortExt::Tag::device>().device.address =
4057                     mAddress.value();
4058         } else {
4059             port = GenerateUniqueDeviceAddress(port.value());
4060         }
4061         mConnectedPort = std::make_unique<WithDevicePortConnectedState>(port.value());
4062         ASSERT_NO_FATAL_FAILURE(mConnectedPort->SetUp(mModule, mModuleConfig));
4063     }
getAudioDeviceAddress()4064     AudioDeviceAddress getAudioDeviceAddress() {
4065         if (!mAddress.has_value()) {
4066             mAddress = mConnectedPort->get()
4067                                .ext.template get<AudioPortExt::Tag::device>()
4068                                .device.address;
4069         }
4070         return mAddress.value();
4071     }
4072     /* Get mix port config for stream and setup patch for it. */
SetupPatch()4073     void SetupPatch() {
4074         const auto portConfig =
4075                 mModuleConfig->getSingleConfigForMixPort(IOTraits<Stream>::is_input);
4076         if (!portConfig.has_value()) {
4077             LOG(DEBUG) << __func__ << ": portConfig not found";
4078             mSkipTest = true;
4079             return;
4080         }
4081         auto devicePortConfig = mModuleConfig->getSingleConfigForDevicePort(mConnectedPort->get());
4082         mPatch = std::make_unique<WithAudioPatch>(IOTraits<Stream>::is_input, portConfig.value(),
4083                                                   devicePortConfig);
4084         ASSERT_NO_FATAL_FAILURE(mPatch->SetUp(mModule));
4085     }
SetUp(IModule * module,ModuleConfig * moduleConfig)4086     void SetUp(IModule* module, ModuleConfig* moduleConfig) {
4087         mModule = module;
4088         mModuleConfig = moduleConfig;
4089         ASSERT_NO_FATAL_FAILURE(SetUpPortConnection());
4090         ASSERT_NO_FATAL_FAILURE(SetupPatch());
4091         if (!mSkipTest) {
4092             // open stream
4093             mStream = std::make_unique<WithStream<Stream>>(
4094                     mPatch->getPortConfig(IOTraits<Stream>::is_input));
4095             ASSERT_NO_FATAL_FAILURE(
4096                     mStream->SetUp(mModule, AudioCoreModuleBase::kDefaultBufferSizeFrames));
4097         }
4098     }
sendBurstCommands()4099     void sendBurstCommands() {
4100         const StreamContext* context = mStream->getContext();
4101         StreamLogicDefaultDriver driver(makeBurstCommands(true), context->getFrameSizeBytes());
4102         typename IOTraits<Stream>::Worker worker(*context, &driver, mStream->getEventReceiver());
4103 
4104         LOG(DEBUG) << __func__ << ": starting worker...";
4105         ASSERT_TRUE(worker.start());
4106         LOG(DEBUG) << __func__ << ": joining worker...";
4107         worker.join();
4108         EXPECT_FALSE(worker.hasError()) << worker.getError();
4109         EXPECT_EQ("", driver.getUnexpectedStateTransition());
4110         if (IOTraits<Stream>::is_input) {
4111             EXPECT_TRUE(driver.hasObservablePositionIncrease());
4112         }
4113         EXPECT_FALSE(driver.hasRetrogradeObservablePosition());
4114     }
skipTest()4115     bool skipTest() { return mSkipTest; }
4116 
4117   private:
4118     bool mSkipTest = false;
4119     IModule* mModule = nullptr;
4120     ModuleConfig* mModuleConfig = nullptr;
4121     std::optional<AudioDeviceAddress> mAddress;
4122     std::unique_ptr<WithDevicePortConnectedState> mConnectedPort;
4123     std::unique_ptr<WithAudioPatch> mPatch;
4124     std::unique_ptr<WithStream<Stream>> mStream;
4125 };
4126 
4127 class AudioModuleRemoteSubmix : public AudioCoreModule {
4128   public:
SetUp()4129     void SetUp() override {
4130         ASSERT_NO_FATAL_FAILURE(AudioCoreModule::SetUp());
4131         ASSERT_NO_FATAL_FAILURE(SetUpModuleConfig());
4132     }
4133 
TearDown()4134     void TearDown() override { ASSERT_NO_FATAL_FAILURE(TearDownImpl()); }
4135 };
4136 
TEST_P(AudioModuleRemoteSubmix,OutputDoesNotBlockWhenNoInput)4137 TEST_P(AudioModuleRemoteSubmix, OutputDoesNotBlockWhenNoInput) {
4138     // open output stream
4139     WithRemoteSubmix<IStreamOut> streamOut;
4140     ASSERT_NO_FATAL_FAILURE(streamOut.SetUp(module.get(), moduleConfig.get()));
4141     if (streamOut.skipTest()) {
4142         GTEST_SKIP() << "No mix port for attached devices";
4143     }
4144     // write something to stream
4145     ASSERT_NO_FATAL_FAILURE(streamOut.sendBurstCommands());
4146 }
4147 
TEST_P(AudioModuleRemoteSubmix,OutputDoesNotBlockWhenInputStuck)4148 TEST_P(AudioModuleRemoteSubmix, OutputDoesNotBlockWhenInputStuck) {
4149     // open output stream
4150     WithRemoteSubmix<IStreamOut> streamOut;
4151     ASSERT_NO_FATAL_FAILURE(streamOut.SetUp(module.get(), moduleConfig.get()));
4152     if (streamOut.skipTest()) {
4153         GTEST_SKIP() << "No mix port for attached devices";
4154     }
4155 
4156     // open input stream
4157     WithRemoteSubmix<IStreamIn> streamIn(streamOut.getAudioDeviceAddress());
4158     ASSERT_NO_FATAL_FAILURE(streamIn.SetUp(module.get(), moduleConfig.get()));
4159     if (streamIn.skipTest()) {
4160         GTEST_SKIP() << "No mix port for attached devices";
4161     }
4162 
4163     // write something to stream
4164     ASSERT_NO_FATAL_FAILURE(streamOut.sendBurstCommands());
4165 }
4166 
TEST_P(AudioModuleRemoteSubmix,OutputAndInput)4167 TEST_P(AudioModuleRemoteSubmix, OutputAndInput) {
4168     // open output stream
4169     WithRemoteSubmix<IStreamOut> streamOut;
4170     ASSERT_NO_FATAL_FAILURE(streamOut.SetUp(module.get(), moduleConfig.get()));
4171     if (streamOut.skipTest()) {
4172         GTEST_SKIP() << "No mix port for attached devices";
4173     }
4174 
4175     // open input stream
4176     WithRemoteSubmix<IStreamIn> streamIn(streamOut.getAudioDeviceAddress());
4177     ASSERT_NO_FATAL_FAILURE(streamIn.SetUp(module.get(), moduleConfig.get()));
4178     if (streamIn.skipTest()) {
4179         GTEST_SKIP() << "No mix port for attached devices";
4180     }
4181 
4182     // write something to stream
4183     ASSERT_NO_FATAL_FAILURE(streamOut.sendBurstCommands());
4184     // read from input stream
4185     ASSERT_NO_FATAL_FAILURE(streamIn.sendBurstCommands());
4186 }
4187 
4188 INSTANTIATE_TEST_SUITE_P(AudioModuleRemoteSubmixTest, AudioModuleRemoteSubmix,
4189                          ::testing::ValuesIn(getRemoteSubmixModuleInstance()));
4190 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(AudioModuleRemoteSubmix);
4191 
4192 class TestExecutionTracer : public ::testing::EmptyTestEventListener {
4193   public:
OnTestStart(const::testing::TestInfo & test_info)4194     void OnTestStart(const ::testing::TestInfo& test_info) override {
4195         TraceTestState("Started", test_info);
4196     }
OnTestEnd(const::testing::TestInfo & test_info)4197     void OnTestEnd(const ::testing::TestInfo& test_info) override {
4198         TraceTestState("Completed", test_info);
4199     }
4200 
4201   private:
TraceTestState(const std::string & state,const::testing::TestInfo & test_info)4202     static void TraceTestState(const std::string& state, const ::testing::TestInfo& test_info) {
4203         LOG(INFO) << state << " " << test_info.test_suite_name() << "::" << test_info.name();
4204     }
4205 };
4206 
main(int argc,char ** argv)4207 int main(int argc, char** argv) {
4208     ::testing::InitGoogleTest(&argc, argv);
4209     ::testing::UnitTest::GetInstance()->listeners().Append(new TestExecutionTracer());
4210     android::base::SetMinimumLogSeverity(::android::base::DEBUG);
4211     ABinderProcess_setThreadPoolMaxThreadCount(1);
4212     ABinderProcess_startThreadPool();
4213     return RUN_ALL_TESTS();
4214 }
4215