• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2023 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <set>
18 #include <string>
19 #include <unordered_map>
20 #include <unordered_set>
21 #include <vector>
22 
23 #define LOG_TAG "VtsHalAudioCore.Config"
24 
25 #include <Utils.h>
26 #include <aidl/Gtest.h>
27 #include <aidl/Vintf.h>
28 #include <aidl/android/hardware/audio/core/IConfig.h>
29 #include <aidl/android/media/audio/common/AudioFlag.h>
30 #include <aidl/android/media/audio/common/AudioProductStrategyType.h>
31 #include <android-base/logging.h>
32 
33 #include "AudioHalBinderServiceUtil.h"
34 #include "TestUtils.h"
35 
36 using namespace android;
37 using aidl::android::hardware::audio::common::isDefaultAudioFormat;
38 using aidl::android::hardware::audio::core::IConfig;
39 using aidl::android::hardware::audio::core::SurroundSoundConfig;
40 using aidl::android::media::audio::common::AudioAttributes;
41 using aidl::android::media::audio::common::AudioDeviceAddress;
42 using aidl::android::media::audio::common::AudioDeviceDescription;
43 using aidl::android::media::audio::common::AudioFlag;
44 using aidl::android::media::audio::common::AudioFormatDescription;
45 using aidl::android::media::audio::common::AudioFormatType;
46 using aidl::android::media::audio::common::AudioHalAttributesGroup;
47 using aidl::android::media::audio::common::AudioHalCapConfiguration;
48 using aidl::android::media::audio::common::AudioHalCapCriterionV2;
49 using aidl::android::media::audio::common::AudioHalCapDomain;
50 using aidl::android::media::audio::common::AudioHalCapParameter;
51 using aidl::android::media::audio::common::AudioHalCapRule;
52 using aidl::android::media::audio::common::AudioHalEngineConfig;
53 using aidl::android::media::audio::common::AudioHalProductStrategy;
54 using aidl::android::media::audio::common::AudioHalVolumeCurve;
55 using aidl::android::media::audio::common::AudioHalVolumeGroup;
56 using aidl::android::media::audio::common::AudioMode;
57 using aidl::android::media::audio::common::AudioPolicyForceUse;
58 using aidl::android::media::audio::common::AudioProductStrategyType;
59 using aidl::android::media::audio::common::AudioSource;
60 using aidl::android::media::audio::common::AudioStreamType;
61 using aidl::android::media::audio::common::AudioUsage;
62 using aidl::android::media::audio::common::PcmType;
63 
64 class AudioCoreConfig : public testing::TestWithParam<std::string> {
65   public:
SetUp()66     void SetUp() override { ASSERT_NO_FATAL_FAILURE(ConnectToService()); }
ConnectToService()67     void ConnectToService() {
68         mConfig = IConfig::fromBinder(mBinderUtil.connectToService(GetParam()));
69         ASSERT_NE(mConfig, nullptr);
70     }
71 
RestartService()72     void RestartService() {
73         ASSERT_NE(mConfig, nullptr);
74         mEngineConfig.reset();
75         mSurroundSoundConfig.reset();
76         mConfig = IConfig::fromBinder(mBinderUtil.restartService());
77         ASSERT_NE(mConfig, nullptr);
78     }
79 
SetUpEngineConfig()80     void SetUpEngineConfig() {
81         if (mEngineConfig == nullptr) {
82             auto tempConfig = std::make_unique<AudioHalEngineConfig>();
83             ASSERT_IS_OK(mConfig->getEngineConfig(tempConfig.get()));
84             mEngineConfig = std::move(tempConfig);
85         }
86     }
87 
SetUpSurroundSoundConfig()88     void SetUpSurroundSoundConfig() {
89         if (mSurroundSoundConfig == nullptr) {
90             auto tempConfig = std::make_unique<SurroundSoundConfig>();
91             ASSERT_IS_OK(mConfig->getSurroundSoundConfig(tempConfig.get()));
92             mSurroundSoundConfig = std::move(tempConfig);
93         }
94     }
95 
IsProductStrategyTypeReservedForSystemUse(const AudioProductStrategyType & pst)96     static bool IsProductStrategyTypeReservedForSystemUse(const AudioProductStrategyType& pst) {
97         switch (pst) {
98             case AudioProductStrategyType::SYS_RESERVED_NONE:
99             case AudioProductStrategyType::SYS_RESERVED_REROUTING:
100             case AudioProductStrategyType::SYS_RESERVED_CALL_ASSISTANT:
101                 return true;
102             default:
103                 return false;
104         }
105     }
106 
IsStreamTypeReservedForSystemUse(const AudioStreamType & streamType)107     static bool IsStreamTypeReservedForSystemUse(const AudioStreamType& streamType) {
108         switch (streamType) {
109             case AudioStreamType::SYS_RESERVED_DEFAULT:
110             case AudioStreamType::SYS_RESERVED_REROUTING:
111             case AudioStreamType::SYS_RESERVED_PATCH:
112             case AudioStreamType::CALL_ASSISTANT:
113                 return true;
114             default:
115                 return false;
116         }
117     }
118 
IsAudioUsageValid(const AudioUsage & usage)119     static bool IsAudioUsageValid(const AudioUsage& usage) {
120         switch (usage) {
121             case AudioUsage::INVALID:
122             case AudioUsage::SYS_RESERVED_NOTIFICATION_COMMUNICATION_REQUEST:
123             case AudioUsage::SYS_RESERVED_NOTIFICATION_COMMUNICATION_INSTANT:
124             case AudioUsage::SYS_RESERVED_NOTIFICATION_COMMUNICATION_DELAYED:
125                 return false;
126             default:
127                 return true;
128         }
129     }
130 
IsAudioSourceValid(const AudioSource & source)131     static bool IsAudioSourceValid(const AudioSource& source) {
132         return (source != AudioSource::SYS_RESERVED_INVALID);
133     }
134 
GetSupportedAudioProductStrategyTypes()135     static const std::unordered_set<int>& GetSupportedAudioProductStrategyTypes() {
136         static const std::unordered_set<int> supportedAudioProductStrategyTypes = []() {
137             std::unordered_set<int> supportedStrategyTypes;
138             for (const auto& audioProductStrategyType :
139                  ndk::enum_range<AudioProductStrategyType>()) {
140                 if (!IsProductStrategyTypeReservedForSystemUse(audioProductStrategyType)) {
141                     supportedStrategyTypes.insert(static_cast<int>(audioProductStrategyType));
142                 }
143             }
144             return supportedStrategyTypes;
145         }();
146         return supportedAudioProductStrategyTypes;
147     }
148 
GetSupportedAudioFlagsMask()149     static int GetSupportedAudioFlagsMask() {
150         static const int supportedAudioFlagsMask = []() {
151             int mask = 0;
152             for (const auto& audioFlag : ndk::enum_range<AudioFlag>()) {
153                 mask |= static_cast<int>(audioFlag);
154             }
155             return mask;
156         }();
157         return supportedAudioFlagsMask;
158     }
159 
160     /**
161      * Verify streamType is not INVALID if using default engine.
162      * Verify that streamType is a valid AudioStreamType if the associated
163      * volumeGroup minIndex/maxIndex is INDEX_DEFERRED_TO_AUDIO_SERVICE.
164      */
ValidateAudioStreamType(const AudioStreamType & streamType,const AudioHalVolumeGroup & associatedVolumeGroup)165     void ValidateAudioStreamType(const AudioStreamType& streamType,
166                                  const AudioHalVolumeGroup& associatedVolumeGroup) {
167         EXPECT_FALSE(IsStreamTypeReservedForSystemUse(streamType));
168         if (!mEngineConfig->capSpecificConfig ||
169             associatedVolumeGroup.minIndex ==
170                     AudioHalVolumeGroup::INDEX_DEFERRED_TO_AUDIO_SERVICE) {
171             EXPECT_NE(streamType, AudioStreamType::INVALID);
172         }
173     }
174 
175     /**
176      * Verify contained enum types are valid.
177      */
ValidateAudioAttributes(const AudioAttributes & attributes)178     void ValidateAudioAttributes(const AudioAttributes& attributes) {
179         // No need to check contentType; there are no INVALID or SYS_RESERVED values
180         EXPECT_TRUE(IsAudioUsageValid(attributes.usage));
181         EXPECT_TRUE(IsAudioSourceValid(attributes.source));
182         EXPECT_EQ(attributes.flags & ~GetSupportedAudioFlagsMask(), 0);
183     }
184 
185     /**
186      * Verify volumeGroupName corresponds to an AudioHalVolumeGroup.
187      * Validate contained types.
188      */
ValidateAudioHalAttributesGroup(const AudioHalAttributesGroup & attributesGroup,std::unordered_map<std::string,const AudioHalVolumeGroup &> & volumeGroupMap,std::unordered_set<std::string> & volumeGroupsUsedInStrategies)189     void ValidateAudioHalAttributesGroup(
190             const AudioHalAttributesGroup& attributesGroup,
191             std::unordered_map<std::string, const AudioHalVolumeGroup&>& volumeGroupMap,
192             std::unordered_set<std::string>& volumeGroupsUsedInStrategies) {
193         bool isVolumeGroupNameValid = volumeGroupMap.count(attributesGroup.volumeGroupName);
194         EXPECT_TRUE(isVolumeGroupNameValid);
195         EXPECT_NO_FATAL_FAILURE(ValidateAudioStreamType(
196                 attributesGroup.streamType, volumeGroupMap.at(attributesGroup.volumeGroupName)));
197         if (isVolumeGroupNameValid) {
198             volumeGroupsUsedInStrategies.insert(attributesGroup.volumeGroupName);
199         }
200         for (const AudioAttributes& attr : attributesGroup.attributes) {
201             EXPECT_NO_FATAL_FAILURE(ValidateAudioAttributes(attr));
202         }
203     }
204 
205     /**
206      * Default engine: verify productStrategy.id is valid AudioProductStrategyType.
207      * CAP engine: verify productStrategy.id is either valid AudioProductStrategyType
208      * or is >= VENDOR_STRATEGY_ID_START.
209      * Validate contained types.
210      */
ValidateAudioHalProductStrategy(const AudioHalProductStrategy & strategy,std::unordered_map<std::string,const AudioHalVolumeGroup &> & volumeGroupMap,std::unordered_set<std::string> & volumeGroupsUsedInStrategies)211     void ValidateAudioHalProductStrategy(
212             const AudioHalProductStrategy& strategy,
213             std::unordered_map<std::string, const AudioHalVolumeGroup&>& volumeGroupMap,
214             std::unordered_set<std::string>& volumeGroupsUsedInStrategies) {
215         if (!mEngineConfig->capSpecificConfig ||
216             (strategy.id < AudioHalProductStrategy::VENDOR_STRATEGY_ID_START)) {
217             EXPECT_NE(GetSupportedAudioProductStrategyTypes().find(strategy.id),
218                       GetSupportedAudioProductStrategyTypes().end());
219         }
220         for (const AudioHalAttributesGroup& attributesGroup : strategy.attributesGroups) {
221             EXPECT_NO_FATAL_FAILURE(ValidateAudioHalAttributesGroup(attributesGroup, volumeGroupMap,
222                                                                     volumeGroupsUsedInStrategies));
223         }
224     }
225 
226     /**
227      * Verify curve point index is in [CurvePoint::MIN_INDEX, CurvePoint::MAX_INDEX].
228      */
ValidateAudioHalVolumeCurve(const AudioHalVolumeCurve & volumeCurve)229     void ValidateAudioHalVolumeCurve(const AudioHalVolumeCurve& volumeCurve) {
230         for (const AudioHalVolumeCurve::CurvePoint& curvePoint : volumeCurve.curvePoints) {
231             EXPECT_TRUE(curvePoint.index >= AudioHalVolumeCurve::CurvePoint::MIN_INDEX);
232             EXPECT_TRUE(curvePoint.index <= AudioHalVolumeCurve::CurvePoint::MAX_INDEX);
233         }
234     }
235 
236     /**
237      * Verify minIndex, maxIndex are non-negative.
238      * Verify minIndex <= maxIndex.
239      * Verify no two volume curves use the same device category.
240      * Validate contained types.
241      */
ValidateAudioHalVolumeGroup(const AudioHalVolumeGroup & volumeGroup)242     void ValidateAudioHalVolumeGroup(const AudioHalVolumeGroup& volumeGroup) {
243         /**
244          * Legacy volume curves in audio_policy_configuration.xsd don't use
245          * minIndex or maxIndex. Use of audio_policy_configuration.xml still
246          * allows, and in some cases, relies on, AudioService to provide the min
247          * and max indices for a volumeGroup. From the VTS perspective, there is
248          * no way to differentiate between use of audio_policy_configuration.xml
249          * or audio_policy_engine_configuration.xml, as either one can be used
250          * for the default audio policy engine.
251          */
252         if (volumeGroup.minIndex != AudioHalVolumeGroup::INDEX_DEFERRED_TO_AUDIO_SERVICE ||
253             volumeGroup.maxIndex != AudioHalVolumeGroup::INDEX_DEFERRED_TO_AUDIO_SERVICE) {
254             EXPECT_TRUE(volumeGroup.minIndex >= 0);
255             EXPECT_TRUE(volumeGroup.maxIndex >= 0);
256         }
257         EXPECT_TRUE(volumeGroup.minIndex <= volumeGroup.maxIndex);
258         std::unordered_set<AudioHalVolumeCurve::DeviceCategory> deviceCategorySet;
259         for (const AudioHalVolumeCurve& volumeCurve : volumeGroup.volumeCurves) {
260             EXPECT_TRUE(deviceCategorySet.insert(volumeCurve.deviceCategory).second);
261             EXPECT_NO_FATAL_FAILURE(ValidateAudioHalVolumeCurve(volumeCurve));
262         }
263     }
264 
265     /**
266      * Verify criterion provides a non empty value list.
267      * Verify logic rule provided is the expected one.
268      */
ValidateAudioHalCapCriterion(const AudioHalCapCriterionV2 & criterionV2)269     void ValidateAudioHalCapCriterion(const AudioHalCapCriterionV2& criterionV2) {
270         switch (criterionV2.getTag()) {
271             case AudioHalCapCriterionV2::availableInputDevices: {
272                 auto criterion = criterionV2.get<AudioHalCapCriterionV2::availableInputDevices>();
273                 EXPECT_FALSE(criterion.values.empty());
274                 EXPECT_EQ(criterion.logic, AudioHalCapCriterionV2::LogicalDisjunction::INCLUSIVE);
275                 break;
276             }
277             case AudioHalCapCriterionV2::availableOutputDevices: {
278                 auto criterion = criterionV2.get<AudioHalCapCriterionV2::availableOutputDevices>();
279                 EXPECT_FALSE(criterion.values.empty());
280                 EXPECT_EQ(criterion.logic, AudioHalCapCriterionV2::LogicalDisjunction::INCLUSIVE);
281                 break;
282             }
283             case AudioHalCapCriterionV2::availableInputDevicesAddresses: {
284                 auto criterion =
285                         criterionV2.get<AudioHalCapCriterionV2::availableInputDevicesAddresses>();
286                 EXPECT_FALSE(criterion.values.empty());
287                 EXPECT_EQ(criterion.logic, AudioHalCapCriterionV2::LogicalDisjunction::INCLUSIVE);
288                 break;
289             }
290             case AudioHalCapCriterionV2::availableOutputDevicesAddresses: {
291                 auto criterion =
292                         criterionV2.get<AudioHalCapCriterionV2::availableOutputDevicesAddresses>();
293                 EXPECT_FALSE(criterion.values.empty());
294                 EXPECT_EQ(criterion.logic, AudioHalCapCriterionV2::LogicalDisjunction::INCLUSIVE);
295                 break;
296             }
297             case AudioHalCapCriterionV2::telephonyMode: {
298                 auto criterion = criterionV2.get<AudioHalCapCriterionV2::telephonyMode>();
299                 EXPECT_FALSE(criterion.values.empty());
300                 EXPECT_EQ(criterion.logic, AudioHalCapCriterionV2::LogicalDisjunction::EXCLUSIVE);
301                 break;
302             }
303             case AudioHalCapCriterionV2::forceConfigForUse: {
304                 auto criterion = criterionV2.get<AudioHalCapCriterionV2::forceConfigForUse>();
305                 EXPECT_FALSE(criterion.values.empty());
306                 EXPECT_EQ(criterion.logic, AudioHalCapCriterionV2::LogicalDisjunction::EXCLUSIVE);
307                 break;
308             }
309             default:
310                 ADD_FAILURE() << "Invalid criterion tag " << toString(criterionV2.getTag());
311         }
312     }
313 
314     /**
315      * Verify the rule involve the right matching logic according to the criterion logic.
316      * @param matchingRule logic followed by the rule
317      * @param logicalDisjunction logic exposed by the criterion
318      */
ValidateAudioHalCapRuleMatchingRule(const AudioHalCapRule::MatchingRule matchingRule,const AudioHalCapCriterionV2::LogicalDisjunction logicalDisjunction)319     void ValidateAudioHalCapRuleMatchingRule(
320             const AudioHalCapRule::MatchingRule matchingRule,
321             const AudioHalCapCriterionV2::LogicalDisjunction logicalDisjunction) {
322         if (logicalDisjunction == AudioHalCapCriterionV2::LogicalDisjunction::INCLUSIVE) {
323             EXPECT_TRUE(matchingRule == AudioHalCapRule::MatchingRule::EXCLUDES ||
324                         matchingRule == AudioHalCapRule::MatchingRule::INCLUDES);
325         } else if (logicalDisjunction == AudioHalCapCriterionV2::LogicalDisjunction::EXCLUSIVE) {
326             EXPECT_TRUE(matchingRule == AudioHalCapRule::MatchingRule::IS ||
327                         matchingRule == AudioHalCapRule::MatchingRule::IS_NOT);
328         } else {
329             ADD_FAILURE() << "Invalid criterion Logical rule";
330         }
331     }
332 
333     /**
334      * Verify that the value and the matching rule are supported by the given criterion
335      */
336     template <typename CriterionV2, typename Value>
validateAudioHalCapRule(CriterionV2 criterionV2,Value value,const AudioHalCapRule::MatchingRule matchingRule)337     void validateAudioHalCapRule(CriterionV2 criterionV2, Value value,
338                                  const AudioHalCapRule::MatchingRule matchingRule) {
339         ValidateAudioHalCapRuleMatchingRule(matchingRule, criterionV2.logic);
340         EXPECT_FALSE(criterionV2.values.empty());
341         auto values = criterionV2.values;
342         auto valueIt = find_if(values.begin(), values.end(),
343                                [&](const auto& typedValue) { return typedValue == value; });
344         EXPECT_NE(valueIt, values.end()) << "Not found: \"" << value << "\"";
345     }
346 
347     /**
348      * Verify rule involves a supported criterion.
349      * Verify rule involves supported logic keyword according to logic rule exposed by the
350      * criterion.
351      * Verify rule involves a value supported by the associated criterion.
352      */
ValidateAudioHalConfigurationRule(const AudioHalCapRule & rule,const std::vector<std::optional<AudioHalCapCriterionV2>> & criteria)353     void ValidateAudioHalConfigurationRule(
354             const AudioHalCapRule& rule,
355             const std::vector<std::optional<AudioHalCapCriterionV2>>& criteria) {
356         const auto& compoundRule = rule.compoundRule;
357         if (rule.nestedRules.empty() && rule.criterionRules.empty()) {
358             EXPECT_EQ(compoundRule, AudioHalCapRule::CompoundRule::ALL);
359         }
360         EXPECT_TRUE(compoundRule == AudioHalCapRule::CompoundRule::ANY ||
361                     compoundRule == AudioHalCapRule::CompoundRule::ALL);
362         for (const auto& nestedRule : rule.nestedRules) {
363             ValidateAudioHalConfigurationRule(nestedRule, criteria);
364         }
365         for (const auto& criterionRule : rule.criterionRules) {
366             auto selectionCriterion = criterionRule.criterionAndValue;
367             auto criterionValue = criterionRule.criterionAndValue;
368             auto matchesWhen = criterionRule.matchingRule;
369             auto criteriaIt = find_if(criteria.begin(), criteria.end(), [&](const auto& criterion) {
370                 auto getForceConfigTag = [](const AudioHalCapCriterionV2& forceConfig) {
371                     return forceConfig.get<AudioHalCapCriterionV2::forceConfigForUse>()
372                             .values[0].getTag();
373                 };
374                 return criterion.has_value() &&
375                        criterion.value().getTag() == selectionCriterion.getTag() &&
376                        (criterion.value().getTag() != AudioHalCapCriterionV2::forceConfigForUse ||
377                         getForceConfigTag(criterion.value()) ==
378                                 getForceConfigTag(selectionCriterion));
379             });
380             EXPECT_NE(criteriaIt, criteria.end())
381                     << " Invalid rule criterion " << toString(selectionCriterion.getTag());
382             AudioHalCapCriterionV2 matchingCriterion = (*criteriaIt).value();
383             switch (selectionCriterion.getTag()) {
384                 case AudioHalCapCriterionV2::availableInputDevices: {
385                     const auto& values =
386                             criterionValue.get<AudioHalCapCriterionV2::availableInputDevices>()
387                                     .values;
388                     ASSERT_FALSE(values.empty());
389                     validateAudioHalCapRule(
390                             matchingCriterion.get<AudioHalCapCriterionV2::availableInputDevices>(),
391                             values[0], matchesWhen);
392                     break;
393                 }
394                 case AudioHalCapCriterionV2::availableOutputDevices: {
395                     const auto& values =
396                             criterionValue.get<AudioHalCapCriterionV2::availableOutputDevices>()
397                                     .values;
398                     ASSERT_FALSE(values.empty());
399                     validateAudioHalCapRule(
400                             matchingCriterion.get<AudioHalCapCriterionV2::availableOutputDevices>(),
401                             values[0], matchesWhen);
402                     break;
403                 }
404                 case AudioHalCapCriterionV2::availableInputDevicesAddresses: {
405                     const auto& values =
406                             criterionValue
407                                     .get<AudioHalCapCriterionV2::availableInputDevicesAddresses>()
408                                     .values;
409                     ASSERT_FALSE(values.empty());
410                     validateAudioHalCapRule(
411                             matchingCriterion
412                                     .get<AudioHalCapCriterionV2::availableInputDevicesAddresses>(),
413                             values[0], matchesWhen);
414                     break;
415                 }
416                 case AudioHalCapCriterionV2::availableOutputDevicesAddresses: {
417                     const auto& values =
418                             criterionValue
419                                     .get<AudioHalCapCriterionV2::availableOutputDevicesAddresses>()
420                                     .values;
421                     ASSERT_FALSE(values.empty());
422                     validateAudioHalCapRule(
423                             matchingCriterion
424                                     .get<AudioHalCapCriterionV2::availableOutputDevicesAddresses>(),
425                             values[0], matchesWhen);
426                     break;
427                 }
428                 case AudioHalCapCriterionV2::telephonyMode: {
429                     const auto& values =
430                             criterionValue.get<AudioHalCapCriterionV2::telephonyMode>().values;
431                     ASSERT_FALSE(values.empty());
432                     validateAudioHalCapRule(
433                             matchingCriterion.get<AudioHalCapCriterionV2::telephonyMode>(),
434                             values[0], matchesWhen);
435                     break;
436                 }
437                 case AudioHalCapCriterionV2::forceConfigForUse: {
438                     const auto& values =
439                             criterionValue.get<AudioHalCapCriterionV2::forceConfigForUse>().values;
440                     ASSERT_FALSE(values.empty());
441                     validateAudioHalCapRule(
442                             matchingCriterion.get<AudioHalCapCriterionV2::forceConfigForUse>(),
443                             values[0], matchesWhen);
444                     break;
445                 }
446                 default:
447                     break;
448             }
449         }
450     }
451 
452     /**
453      * Get the number of occurrence of a given parameter within a given vector of parameter.
454      * It just take into account the parameter, not its associated value.
455      * @param parameter to consider
456      * @param domainParameters to check against
457      * @return matching occurrence of the parameter within the provided vector.
458      */
countsParameter(const AudioHalCapParameter & parameter,const std::vector<AudioHalCapParameter> & domainParameters)459     size_t countsParameter(const AudioHalCapParameter& parameter,
460                            const std::vector<AudioHalCapParameter>& domainParameters) {
461         size_t count = 0;
462         for (const auto& domainParameter : domainParameters) {
463             if (domainParameter.getTag() != parameter.getTag()) {
464                 continue;
465             }
466             switch (domainParameter.getTag()) {
467                 case AudioHalCapParameter::selectedStrategyDevice: {
468                     auto typedDomainParam =
469                             domainParameter.get<AudioHalCapParameter::selectedStrategyDevice>();
470                     auto typedParam = parameter.get<AudioHalCapParameter::selectedStrategyDevice>();
471                     if (typedDomainParam.id == typedParam.id &&
472                         typedDomainParam.device == typedParam.device) {
473                         count += 1;
474                     }
475                     break;
476                 }
477                 case AudioHalCapParameter::strategyDeviceAddress: {
478                     auto typedDomainParam =
479                             domainParameter.get<AudioHalCapParameter::strategyDeviceAddress>();
480                     auto typedParam = parameter.get<AudioHalCapParameter::strategyDeviceAddress>();
481                     if (typedDomainParam.id == typedParam.id) {
482                         count += 1;
483                     }
484                     break;
485                 }
486                 case AudioHalCapParameter::selectedInputSourceDevice: {
487                     auto typedDomainParam =
488                             domainParameter.get<AudioHalCapParameter::selectedInputSourceDevice>();
489                     auto typedParam =
490                             parameter.get<AudioHalCapParameter::selectedInputSourceDevice>();
491                     if (typedDomainParam.inputSource == typedParam.inputSource &&
492                         typedDomainParam.device == typedParam.device) {
493                         count += 1;
494                     }
495                     break;
496                 }
497                 case AudioHalCapParameter::streamVolumeProfile: {
498                     auto typedDomainParam =
499                             domainParameter.get<AudioHalCapParameter::streamVolumeProfile>();
500                     auto typedParam = parameter.get<AudioHalCapParameter::streamVolumeProfile>();
501                     if (typedDomainParam.stream == typedParam.stream) {
502                         count += 1;
503                     }
504                     break;
505                 }
506                 default:
507                     break;
508             }
509         }
510         return count;
511     }
512 
513     /**
514      * Verify each configuration has unique name within a domain
515      * Verify no duplicate parameter within a domain.
516      * Verify that each configuration has no duplicated parameter.
517      * Verify that each configuration has an associated value for all parameter within a domain.
518      */
ValidateAudioHalCapDomain(const AudioHalCapDomain & domain,const std::vector<std::optional<AudioHalCapCriterionV2>> & criteria)519     void ValidateAudioHalCapDomain(
520             const AudioHalCapDomain& domain,
521             const std::vector<std::optional<AudioHalCapCriterionV2>>& criteria) {
522         std::unordered_set<std::string> configurationNames;
523         for (const AudioHalCapConfiguration& configuration : domain.configurations) {
524             EXPECT_TRUE(configurationNames.insert(configuration.name).second);
525             ASSERT_NO_FATAL_FAILURE(
526                     ValidateAudioHalConfigurationRule(configuration.rule, criteria));
527         }
528         auto domainParameters = domain.configurations[0].parameterSettings;
529         for (const auto& settingParameter : domainParameters) {
530             EXPECT_EQ(1ul, countsParameter(settingParameter, domainParameters))
531                     << "Duplicated parameter within domain " << domain.name << " configuration "
532                     << domain.configurations[0].name << " for parameter "
533                     << settingParameter.toString();
534         }
535         for (const auto& configuration : domain.configurations) {
536             auto configurationParameters = configuration.parameterSettings;
537             for (const auto& configurationParameter : configurationParameters) {
538                 EXPECT_EQ(1ul, countsParameter(configurationParameter, configurationParameters))
539                         << "Duplicated parameter within domain " << domain.name << " configuration "
540                         << configuration.name << " for parameter "
541                         << configurationParameter.toString();
542             }
543             EXPECT_EQ(domainParameters.size(), configurationParameters.size());
544             for (const auto& settingParameter : configuration.parameterSettings) {
545                 EXPECT_EQ(1ul, countsParameter(settingParameter, domainParameters))
546                         << "Confiugration " << configuration.name << " within domain "
547                         << domain.name << " exposes invalid parameter "
548                         << settingParameter.toString();
549                 ;
550             }
551         }
552     }
553 
554     /**
555      * Verify each domain has a unique name.
556      * Verify that a given parameter does not appear in more than one domain.
557      */
ValidateAudioHalCapDomains(const std::vector<std::optional<AudioHalCapDomain>> & domains,const std::vector<std::optional<AudioHalCapCriterionV2>> & criteria)558     void ValidateAudioHalCapDomains(
559             const std::vector<std::optional<AudioHalCapDomain>>& domains,
560             const std::vector<std::optional<AudioHalCapCriterionV2>>& criteria) {
561         std::unordered_map<std::string, AudioHalCapDomain> domainMap;
562         std::vector<AudioHalCapParameter> allDomainParameters;
563         for (const auto& domain : domains) {
564             EXPECT_TRUE(domain.has_value());
565             EXPECT_FALSE(domain.value().configurations.empty());
566             auto domainParameters = domain.value().configurations[0].parameterSettings;
567             for (const auto& domainParameter : domainParameters) {
568                 EXPECT_EQ(0ul, countsParameter(domainParameter, allDomainParameters))
569                         << "Duplicated parameter in domain " << domain.value().name
570                         << " for parameter " << domainParameter.toString();
571                 allDomainParameters.push_back(domainParameter);
572             }
573             EXPECT_NO_FATAL_FAILURE(ValidateAudioHalCapDomain(domain.value(), criteria));
574             EXPECT_TRUE(domainMap.insert({domain.value().name, domain.value()}).second);
575         }
576     }
577 
578     /**
579      * Verify unique criterion is provided for a given Tag, except for ForceUse
580      * Verify unique forceUse criterion are provided for usage
581      * Verify each criterion is validating.
582      * Verify domains.
583      */
ValidateCapSpecificConfig(const AudioHalEngineConfig::CapSpecificConfig & capCfg)584     void ValidateCapSpecificConfig(const AudioHalEngineConfig::CapSpecificConfig& capCfg) {
585         EXPECT_TRUE(capCfg.criteriaV2.has_value());
586         std::unordered_set<AudioHalCapCriterionV2::Tag> criterionTagSet;
587         std::unordered_set<AudioPolicyForceUse::Tag> forceUseCriterionUseSet;
588         for (const auto& criterion : capCfg.criteriaV2.value()) {
589             EXPECT_TRUE(criterion.has_value());
590             if (criterion.value().getTag() != AudioHalCapCriterionV2::forceConfigForUse) {
591                 EXPECT_TRUE(criterionTagSet.insert(criterion.value().getTag()).second);
592             } else {
593                 auto forceUseCriterion =
594                         criterion.value().get<AudioHalCapCriterionV2::forceConfigForUse>();
595                 ASSERT_FALSE(forceUseCriterion.values.empty());
596                 EXPECT_TRUE(forceUseCriterionUseSet.insert(forceUseCriterion.values[0].getTag())
597                                     .second);
598             }
599             EXPECT_NO_FATAL_FAILURE(ValidateAudioHalCapCriterion(criterion.value()));
600         }
601         ASSERT_NO_FATAL_FAILURE(
602                 ValidateAudioHalCapDomains(capCfg.domains.value(), capCfg.criteriaV2.value()));
603     }
604 
605     /**
606      * Verify VolumeGroups are non-empty.
607      * Verify defaultProductStrategyId matches one of the provided productStrategies.
608      * Otherwise, must be left uninitialized.
609      * Verify each volumeGroup has a unique name.
610      * Verify each productStrategy has a unique id.
611      * Verify each volumeGroup is used in a product strategy.
612      * CAP engine: verify productStrategies are non-empty.
613      * Validate contained types.
614      */
ValidateAudioHalEngineConfig()615     void ValidateAudioHalEngineConfig() {
616         EXPECT_NE(mEngineConfig->volumeGroups.size(), 0UL);
617         std::unordered_map<std::string, const AudioHalVolumeGroup&> volumeGroupMap;
618         for (const AudioHalVolumeGroup& volumeGroup : mEngineConfig->volumeGroups) {
619             EXPECT_TRUE(volumeGroupMap.insert({volumeGroup.name, volumeGroup}).second);
620             EXPECT_NO_FATAL_FAILURE(ValidateAudioHalVolumeGroup(volumeGroup));
621         }
622         if (!mEngineConfig->productStrategies.empty()) {
623             std::unordered_set<int> productStrategyIdSet;
624             std::unordered_set<std::string> volumeGroupsUsedInStrategies;
625             for (const AudioHalProductStrategy& strategy : mEngineConfig->productStrategies) {
626                 EXPECT_TRUE(productStrategyIdSet.insert(strategy.id).second);
627                 EXPECT_NO_FATAL_FAILURE(ValidateAudioHalProductStrategy(
628                         strategy, volumeGroupMap, volumeGroupsUsedInStrategies));
629             }
630             EXPECT_TRUE(productStrategyIdSet.count(mEngineConfig->defaultProductStrategyId))
631                     << "defaultProductStrategyId doesn't match any of the provided "
632                        "productStrategies";
633             EXPECT_EQ(volumeGroupMap.size(), volumeGroupsUsedInStrategies.size());
634         } else {
635             EXPECT_EQ(mEngineConfig->defaultProductStrategyId,
636                       static_cast<int>(AudioProductStrategyType::SYS_RESERVED_NONE))
637                     << "defaultProductStrategyId defined, but no productStrategies were provided";
638         }
639         if (mEngineConfig->capSpecificConfig) {
640             EXPECT_NO_FATAL_FAILURE(
641                     ValidateCapSpecificConfig(mEngineConfig->capSpecificConfig.value()));
642             EXPECT_FALSE(mEngineConfig->productStrategies.empty());
643         }
644     }
645 
ValidateAudioFormatDescription(const AudioFormatDescription & format)646     void ValidateAudioFormatDescription(const AudioFormatDescription& format) {
647         EXPECT_NE(AudioFormatType::SYS_RESERVED_INVALID, format.type);
648         if (format.type == AudioFormatType::PCM) {
649             EXPECT_NE(PcmType::DEFAULT, format.pcm);
650             EXPECT_TRUE(format.encoding.empty()) << format.encoding;
651         } else {
652             EXPECT_FALSE(format.encoding.empty());
653         }
654     }
655 
656     /**
657      * Verify that the surround sound configuration is not empty.
658      * Verify each of the formatFamilies has a non-empty primaryFormat.
659      * Verify that each format only appears once.
660      */
ValidateSurroundSoundConfig()661     void ValidateSurroundSoundConfig() {
662         EXPECT_FALSE(mSurroundSoundConfig->formatFamilies.empty());
663         std::set<AudioFormatDescription> formatSet;
664         for (const SurroundSoundConfig::SurroundFormatFamily& family :
665              mSurroundSoundConfig->formatFamilies) {
666             EXPECT_NO_FATAL_FAILURE(ValidateAudioFormatDescription(family.primaryFormat));
667             EXPECT_FALSE(isDefaultAudioFormat(family.primaryFormat));
668             EXPECT_TRUE(formatSet.insert(family.primaryFormat).second);
669             for (const AudioFormatDescription& subformat : family.subFormats) {
670                 EXPECT_NO_FATAL_FAILURE(ValidateAudioFormatDescription(subformat));
671                 EXPECT_FALSE(isDefaultAudioFormat(subformat));
672                 EXPECT_TRUE(formatSet.insert(subformat).second);
673             }
674         }
675     }
676 
677   private:
678     std::shared_ptr<IConfig> mConfig;
679     std::unique_ptr<AudioHalEngineConfig> mEngineConfig;
680     std::unique_ptr<SurroundSoundConfig> mSurroundSoundConfig;
681     AudioHalBinderServiceUtil mBinderUtil;
682 };
683 
TEST_P(AudioCoreConfig,Published)684 TEST_P(AudioCoreConfig, Published) {
685     // SetUp must complete with no failures.
686 }
687 
TEST_P(AudioCoreConfig,CanBeRestarted)688 TEST_P(AudioCoreConfig, CanBeRestarted) {
689     ASSERT_NO_FATAL_FAILURE(RestartService());
690 }
691 
TEST_P(AudioCoreConfig,GetEngineConfigIsValid)692 TEST_P(AudioCoreConfig, GetEngineConfigIsValid) {
693     ASSERT_NO_FATAL_FAILURE(SetUpEngineConfig());
694     EXPECT_NO_FATAL_FAILURE(ValidateAudioHalEngineConfig());
695 }
696 
TEST_P(AudioCoreConfig,GetSurroundSoundConfigIsValid)697 TEST_P(AudioCoreConfig, GetSurroundSoundConfigIsValid) {
698     ASSERT_NO_FATAL_FAILURE(SetUpSurroundSoundConfig());
699     EXPECT_NO_FATAL_FAILURE(ValidateSurroundSoundConfig());
700 }
701 
702 INSTANTIATE_TEST_SUITE_P(AudioCoreConfigTest, AudioCoreConfig,
703                          testing::ValuesIn(android::getAidlHalInstanceNames(IConfig::descriptor)),
704                          android::PrintInstanceNameToString);
705 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(AudioCoreConfig);
706