• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 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 //#define LOG_NDEBUG 0
18 #define LOG_TAG "AudioClientSerializationUnitTests"
19 
20 #include <cstdint>
21 #include <cstdlib>
22 #include <ctime>
23 
24 #include <gtest/gtest.h>
25 
26 #include <android_audio_policy_configuration_V7_0-enums.h>
27 #include <xsdc/XsdcSupport.h>
28 
29 #include "audio_test_utils.h"
30 
31 using namespace android;
32 namespace xsd {
33 using namespace ::android::audio::policy::configuration::V7_0;
34 }
35 
36 template <typename T, typename X, typename FUNC>
getFlags(const xsdc_enum_range<X> & range,const FUNC & func,const std::string & findString={})37 std::vector<T> getFlags(const xsdc_enum_range<X>& range, const FUNC& func,
38                         const std::string& findString = {}) {
39     std::vector<T> vec;
40     for (const auto& xsdEnumVal : range) {
41         T enumVal;
42         std::string enumString = toString(xsdEnumVal);
43         if (enumString.find(findString) != std::string::npos &&
44             func(enumString.c_str(), &enumVal)) {
45             vec.push_back(enumVal);
46         }
47     }
48     return vec;
49 }
50 
51 static const std::vector<audio_usage_t> kUsages =
52         getFlags<audio_usage_t, xsd::AudioUsage, decltype(audio_usage_from_string)>(
53                 xsdc_enum_range<xsd::AudioUsage>{}, audio_usage_from_string);
54 
55 static const std::vector<audio_content_type_t> kContentType =
56         getFlags<audio_content_type_t, xsd::AudioContentType,
57                  decltype(audio_content_type_from_string)>(xsdc_enum_range<xsd::AudioContentType>{},
58                                                            audio_content_type_from_string);
59 
60 static const std::vector<audio_source_t> kInputSources =
61         getFlags<audio_source_t, xsd::AudioSource, decltype(audio_source_from_string)>(
62                 xsdc_enum_range<xsd::AudioSource>{}, audio_source_from_string);
63 
64 static const std::vector<audio_stream_type_t> kStreamtypes =
65         getFlags<audio_stream_type_t, xsd::AudioStreamType,
66                  decltype(audio_stream_type_from_string)>(xsdc_enum_range<xsd::AudioStreamType>{},
67                                                           audio_stream_type_from_string);
68 
69 static const std::vector<uint32_t> kMixMatchRules = {RULE_MATCH_ATTRIBUTE_USAGE,
70                                                      RULE_EXCLUDE_ATTRIBUTE_USAGE,
71                                                      RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET,
72                                                      RULE_EXCLUDE_ATTRIBUTE_CAPTURE_PRESET,
73                                                      RULE_MATCH_UID,
74                                                      RULE_EXCLUDE_UID,
75                                                      RULE_MATCH_USERID,
76                                                      RULE_EXCLUDE_USERID,
77                                                      RULE_MATCH_AUDIO_SESSION_ID,
78                                                      RULE_EXCLUDE_AUDIO_SESSION_ID};
79 
80 // Generates a random string.
CreateRandomString(size_t n)81 std::string CreateRandomString(size_t n) {
82     std::string data =
83             "abcdefghijklmnopqrstuvwxyz"
84             "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
85             "0123456789";
86     srand(static_cast<unsigned int>(time(0)));
87     std::string s(n, ' ');
88     for (size_t i = 0; i < n; ++i) {
89         s[i] = data[rand() % data.size()];
90     }
91     return s;
92 }
93 
94 class FillAudioAttributes {
95   public:
96     void fillAudioAttributes(audio_attributes_t& attr);
97 
98     unsigned int mSeed;
99 };
100 
fillAudioAttributes(audio_attributes_t & attr)101 void FillAudioAttributes::fillAudioAttributes(audio_attributes_t& attr) {
102     attr.content_type = kContentType[rand() % kContentType.size()];
103     attr.usage = kUsages[rand() % kUsages.size()];
104     attr.source = kInputSources[rand() % kInputSources.size()];
105     // attr.flags -> [0, (1 << (CAPTURE_PRIVATE + 1) - 1)]
106     attr.flags = static_cast<audio_flags_mask_t>(rand() & 0x3ffd);  // exclude AUDIO_FLAG_SECURE
107     sprintf(attr.tags, "%s",
108             CreateRandomString((int)rand() % (AUDIO_ATTRIBUTES_TAGS_MAX_SIZE - 1)).c_str());
109 }
110 
111 class SerializationTest : public FillAudioAttributes, public ::testing::Test {
SetUp()112     void SetUp() override {
113         mSeed = static_cast<unsigned int>(time(0));
114         srand(mSeed);
115     }
116 };
117 
118 // UNIT TESTS
TEST_F(SerializationTest,AudioProductStrategyBinderization)119 TEST_F(SerializationTest, AudioProductStrategyBinderization) {
120     for (int j = 0; j < 512; j++) {
121         const std::string name{"Test APSBinderization for seed::" + std::to_string(mSeed)};
122         SCOPED_TRACE(name);
123         std::vector<VolumeGroupAttributes> volumeGroupAttrVector;
124         for (auto i = 0; i < 16; i++) {
125             audio_attributes_t attributes;
126             fillAudioAttributes(attributes);
127             VolumeGroupAttributes volumeGroupAttr{static_cast<volume_group_t>(rand()),
128                                                   kStreamtypes[rand() % kStreamtypes.size()],
129                                                   attributes};
130             volumeGroupAttrVector.push_back(volumeGroupAttr);
131         }
132         product_strategy_t psId = static_cast<product_strategy_t>(rand());
133         AudioProductStrategy aps{name, volumeGroupAttrVector, psId};
134 
135         Parcel p;
136         EXPECT_EQ(NO_ERROR, aps.writeToParcel(&p));
137 
138         AudioProductStrategy apsCopy;
139         p.setDataPosition(0);
140         EXPECT_EQ(NO_ERROR, apsCopy.readFromParcel(&p));
141         EXPECT_EQ(apsCopy.getName(), name);
142         EXPECT_EQ(apsCopy.getId(), psId);
143         auto avec = apsCopy.getVolumeGroupAttributes();
144         EXPECT_EQ(avec.size(), volumeGroupAttrVector.size());
145         for (int i = 0; i < std::min(avec.size(), volumeGroupAttrVector.size()); i++) {
146             EXPECT_EQ(avec[i].getGroupId(), volumeGroupAttrVector[i].getGroupId());
147             EXPECT_EQ(avec[i].getStreamType(), volumeGroupAttrVector[i].getStreamType());
148             EXPECT_TRUE(avec[i].getAttributes() == volumeGroupAttrVector[i].getAttributes());
149         }
150     }
151 }
152 
TEST_F(SerializationTest,AudioVolumeGroupBinderization)153 TEST_F(SerializationTest, AudioVolumeGroupBinderization) {
154     for (int j = 0; j < 512; j++) {
155         const std::string name{"Test AVGBinderization for seed::" + std::to_string(mSeed)};
156         volume_group_t groupId = static_cast<volume_group_t>(rand());
157         std::vector<audio_attributes_t> attributesvector;
158         for (auto i = 0; i < 16; i++) {
159             audio_attributes_t attributes;
160             fillAudioAttributes(attributes);
161             attributesvector.push_back(attributes);
162         }
163         std::vector<audio_stream_type_t> streamsvector;
164         for (auto i = 0; i < 8; i++) {
165             streamsvector.push_back(kStreamtypes[rand() % kStreamtypes.size()]);
166         }
167         AudioVolumeGroup avg{name, groupId, attributesvector, streamsvector};
168 
169         Parcel p;
170         EXPECT_EQ(NO_ERROR, avg.writeToParcel(&p));
171 
172         AudioVolumeGroup avgCopy;
173         p.setDataPosition(0);
174         EXPECT_EQ(NO_ERROR, avgCopy.readFromParcel(&p)) << name;
175         EXPECT_EQ(avgCopy.getName(), name) << name;
176         EXPECT_EQ(avgCopy.getId(), groupId) << name;
177         auto avec = avgCopy.getAudioAttributes();
178         EXPECT_EQ(avec.size(), attributesvector.size()) << name;
179         for (int i = 0; i < avec.size(); i++) {
180             EXPECT_TRUE(avec[i] == attributesvector[i]) << name;
181         }
182         StreamTypeVector svec = avgCopy.getStreamTypes();
183         EXPECT_EQ(svec.size(), streamsvector.size()) << name;
184         for (int i = 0; i < svec.size(); i++) {
185             EXPECT_EQ(svec[i], streamsvector[i]) << name;
186         }
187     }
188 }
189 
TEST_F(SerializationTest,AudioMixBinderization)190 TEST_F(SerializationTest, AudioMixBinderization) {
191     for (int j = 0; j < 512; j++) {
192         const std::string msg{"Test AMBinderization for seed::" + std::to_string(mSeed)};
193         std::vector<AudioMixMatchCriterion> criteria;
194         criteria.reserve(16);
195         for (int i = 0; i < 16; i++) {
196             AudioMixMatchCriterion ammc{kUsages[rand() % kUsages.size()],
197                                         kInputSources[rand() % kInputSources.size()],
198                                         kMixMatchRules[rand() % kMixMatchRules.size()]};
199             criteria.push_back(ammc);
200         }
201         audio_config_t config{};
202         config.sample_rate = 48000;
203         config.channel_mask = AUDIO_CHANNEL_IN_MONO;
204         config.format = AUDIO_FORMAT_PCM_16_BIT;
205         config.offload_info = AUDIO_INFO_INITIALIZER;
206         config.frame_count = 4800;
207         AudioMix am{criteria,
208                     static_cast<uint32_t>(rand()),
209                     config,
210                     static_cast<uint32_t>(rand()),
211                     String8(msg.c_str()),
212                     static_cast<uint32_t>(rand())};
213 
214         Parcel p;
215         EXPECT_EQ(NO_ERROR, am.writeToParcel(&p)) << msg;
216 
217         AudioMix amCopy;
218         p.setDataPosition(0);
219         EXPECT_EQ(NO_ERROR, amCopy.readFromParcel(&p)) << msg;
220         EXPECT_EQ(amCopy.mMixType, am.mMixType) << msg;
221         EXPECT_EQ(amCopy.mFormat.sample_rate, am.mFormat.sample_rate) << msg;
222         EXPECT_EQ(amCopy.mFormat.channel_mask, am.mFormat.channel_mask) << msg;
223         EXPECT_EQ(amCopy.mFormat.format, am.mFormat.format) << msg;
224         EXPECT_EQ(amCopy.mRouteFlags, am.mRouteFlags) << msg;
225         EXPECT_EQ(amCopy.mDeviceAddress, am.mDeviceAddress) << msg;
226         EXPECT_EQ(amCopy.mCbFlags, am.mCbFlags) << msg;
227         EXPECT_EQ(amCopy.mCriteria.size(), am.mCriteria.size()) << msg;
228         for (auto i = 0; i < amCopy.mCriteria.size(); i++) {
229             EXPECT_EQ(amCopy.mCriteria[i].mRule, am.mCriteria[i].mRule) << msg;
230             EXPECT_EQ(amCopy.mCriteria[i].mValue.mUserId, am.mCriteria[i].mValue.mUserId) << msg;
231         }
232     }
233 }
234 
235 using MMCTestParams = std::tuple<audio_usage_t, audio_source_t, uint32_t>;
236 
237 class MMCParameterizedTest : public FillAudioAttributes,
238                              public ::testing::TestWithParam<MMCTestParams> {
239   public:
MMCParameterizedTest()240     MMCParameterizedTest()
241         : mAudioUsage(std::get<0>(GetParam())),
242           mAudioSource(std::get<1>(GetParam())),
243           mAudioMixMatchRules(std::get<2>(GetParam())){};
244 
245     const audio_usage_t mAudioUsage;
246     const audio_source_t mAudioSource;
247     const uint32_t mAudioMixMatchRules;
248 
SetUp()249     void SetUp() override {
250         mSeed = static_cast<unsigned int>(time(0));
251         srand(mSeed);
252     }
253 };
254 
TEST_P(MMCParameterizedTest,AudioMixMatchCriterionBinderization)255 TEST_P(MMCParameterizedTest, AudioMixMatchCriterionBinderization) {
256     const std::string msg{"Test AMMCBinderization for seed::" + std::to_string(mSeed)};
257     AudioMixMatchCriterion ammc{mAudioUsage, mAudioSource, mAudioMixMatchRules};
258 
259     Parcel p;
260     EXPECT_EQ(NO_ERROR, ammc.writeToParcel(&p)) << msg;
261 
262     AudioMixMatchCriterion ammcCopy;
263     p.setDataPosition(0);
264     EXPECT_EQ(NO_ERROR, ammcCopy.readFromParcel(&p)) << msg;
265     EXPECT_EQ(ammcCopy.mRule, ammc.mRule) << msg;
266     EXPECT_EQ(ammcCopy.mValue.mUserId, ammc.mValue.mUserId) << msg;
267 }
268 
269 // audioUsage, audioSource, audioMixMatchRules
270 INSTANTIATE_TEST_SUITE_P(SerializationParameterizedTests, MMCParameterizedTest,
271                          ::testing::Combine(testing::ValuesIn(kUsages),
272                                             testing::ValuesIn(kInputSources),
273                                             testing::ValuesIn(kMixMatchRules)));
274 
275 using AudioAttributesTestParams = std::tuple<audio_stream_type_t>;
276 
277 class AudioAttributesParameterizedTest
278     : public FillAudioAttributes,
279       public ::testing::TestWithParam<AudioAttributesTestParams> {
280   public:
AudioAttributesParameterizedTest()281     AudioAttributesParameterizedTest() : mAudioStream(std::get<0>(GetParam())){};
282 
283     const audio_stream_type_t mAudioStream;
284 
SetUp()285     void SetUp() override {
286         mSeed = static_cast<unsigned int>(time(0));
287         srand(mSeed);
288     }
289 };
290 
TEST_P(AudioAttributesParameterizedTest,AudioAttributesBinderization)291 TEST_P(AudioAttributesParameterizedTest, AudioAttributesBinderization) {
292     const std::string msg{"Test AABinderization for seed::" + std::to_string(mSeed)};
293     volume_group_t groupId = static_cast<volume_group_t>(rand());
294     audio_stream_type_t stream = mAudioStream;
295     audio_attributes_t attributes;
296     fillAudioAttributes(attributes);
297     VolumeGroupAttributes volumeGroupAttr{groupId, stream, attributes};
298 
299     Parcel p;
300     EXPECT_EQ(NO_ERROR, volumeGroupAttr.writeToParcel(&p)) << msg;
301 
302     VolumeGroupAttributes volumeGroupAttrCopy;
303     p.setDataPosition(0);
304     EXPECT_EQ(NO_ERROR, volumeGroupAttrCopy.readFromParcel(&p)) << msg;
305     EXPECT_EQ(volumeGroupAttrCopy.getGroupId(), volumeGroupAttr.getGroupId()) << msg;
306     EXPECT_EQ(volumeGroupAttrCopy.getStreamType(), volumeGroupAttr.getStreamType()) << msg;
307     EXPECT_TRUE(volumeGroupAttrCopy.getAttributes() == attributes) << msg;
308 }
309 
310 // audioStream
311 INSTANTIATE_TEST_SUITE_P(SerializationParameterizedTests, AudioAttributesParameterizedTest,
312                          ::testing::Combine(testing::ValuesIn(kStreamtypes)));
313