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