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