blob: 7da6306ad483cfc64952ada70044534de6d2600c [file] [log] [blame]
Andy Hungc89c8dc2019-10-16 17:48:21 -07001/*
2 * Copyright (C) 2019 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_TAG "mediametrics_tests"
18#include <utils/Log.h>
19
Ray Essick40e8e5e2019-12-05 20:19:40 -080020#include "MediaMetricsService.h"
Andy Hung1ea842e2020-05-18 10:47:31 -070021#include "StringUtils.h"
Andy Hungc89c8dc2019-10-16 17:48:21 -070022
23#include <stdio.h>
24
25#include <gtest/gtest.h>
Ray Essickf27e9872019-12-07 06:28:46 -080026#include <media/MediaMetricsItem.h>
Andy Hungc89c8dc2019-10-16 17:48:21 -070027
28using namespace android;
29
Andy Hung06f3aba2019-12-03 16:36:42 -080030static size_t countNewlines(const char *s) {
31 size_t count = 0;
32 while ((s = strchr(s, '\n')) != nullptr) {
33 ++s;
34 ++count;
35 }
36 return count;
37}
38
Andy Hung37de9b72020-01-02 13:54:05 -080039TEST(mediametrics_tests, startsWith) {
40 std::string s("test");
41 ASSERT_EQ(true, android::mediametrics::startsWith(s, "te"));
42 ASSERT_EQ(true, android::mediametrics::startsWith(s, std::string("tes")));
43 ASSERT_EQ(false, android::mediametrics::startsWith(s, "ts"));
44 ASSERT_EQ(false, android::mediametrics::startsWith(s, std::string("est")));
45}
46
47TEST(mediametrics_tests, defer) {
48 bool check = false;
49 {
50 android::mediametrics::Defer defer([&] { check = true; });
51 ASSERT_EQ(false, check);
52 }
53 ASSERT_EQ(true, check);
54}
55
Andy Hung0f7ad8c2020-01-03 13:24:34 -080056TEST(mediametrics_tests, shared_ptr_wrap) {
57 // Test shared pointer wrap with simple access
58 android::mediametrics::SharedPtrWrap<std::string> s("123");
59 ASSERT_EQ('1', s->at(0));
60 ASSERT_EQ('2', s->at(1));
61 s->push_back('4');
62 ASSERT_EQ('4', s->at(3));
63
64 const android::mediametrics::SharedPtrWrap<std::string> s2("345");
65 ASSERT_EQ('3', s2->operator[](0)); // s2[0] == '3'
66 // we allow modification through a const shared pointer wrap
67 // for compatibility with shared_ptr.
68 s2->push_back('6');
69 ASSERT_EQ('6', s2->operator[](3)); // s2[3] == '6'
70
71 android::mediametrics::SharedPtrWrap<std::string> s3("");
72 s3.set(std::make_shared<std::string>("abc"));
73 ASSERT_EQ('b', s3->operator[](1)); // s2[1] = 'b';
74
75 // Use Thunk to check whether the destructor was called prematurely
76 // when setting the shared ptr wrap in the middle of a method.
77
78 class Thunk {
79 std::function<void(int)> mF;
80 const int mFinal;
81
82 public:
Andy Hungb744faf2020-04-09 13:09:26 -070083 explicit Thunk(decltype(mF) f, int final) : mF(std::move(f)), mFinal(final) {}
Andy Hung0f7ad8c2020-01-03 13:24:34 -080084 ~Thunk() { mF(mFinal); }
85 void thunk(int value) { mF(value); }
86 };
87
88 int counter = 0;
89 android::mediametrics::SharedPtrWrap<Thunk> s4(
90 [&](int value) {
91 s4.set(std::make_shared<Thunk>([](int){}, 0)); // recursively set s4 while in s4.
92 ++counter;
93 ASSERT_EQ(value, counter); // on thunk() value is 1, on destructor this is 2.
94 }, 2);
95
96 // This will fail if the shared ptr wrap doesn't hold a ref count during method access.
97 s4->thunk(1);
98}
99
100TEST(mediametrics_tests, lock_wrap) {
101 // Test lock wrap with simple access
102 android::mediametrics::LockWrap<std::string> s("123");
103 ASSERT_EQ('1', s->at(0));
104 ASSERT_EQ('2', s->at(1));
105 s->push_back('4');
106 ASSERT_EQ('4', s->at(3));
107
108 const android::mediametrics::LockWrap<std::string> s2("345");
109 ASSERT_EQ('3', s2->operator[](0)); // s2[0] == '3'
110 // note: we can't modify s2 due to const, s2->push_back('6');
111
112 android::mediametrics::LockWrap<std::string> s3("");
113 s3->operator=("abc");
114 ASSERT_EQ('b', s3->operator[](1)); // s2[1] = 'b';
115
Andy Hung42b99302020-01-10 12:01:18 -0800116 // Check that we can recursively hold lock.
117 android::mediametrics::LockWrap<std::vector<int>> v{std::initializer_list<int>{1, 2}};
118 v->push_back(3);
119 v->push_back(4);
120 ASSERT_EQ(1, v->operator[](0));
121 ASSERT_EQ(2, v->operator[](1));
122 ASSERT_EQ(3, v->operator[](2));
123 ASSERT_EQ(4, v->operator[](3));
124 // The end of the full expression here requires recursive depth of 4.
125 ASSERT_EQ(10, v->operator[](0) + v->operator[](1) + v->operator[](2) + v->operator[](3));
126
127 // Mikhail's note: a non-recursive lock implementation could be used if one obtains
128 // the LockedPointer helper object like this and directly hold the lock through RAII,
129 // though it is trickier in use.
130 //
131 // We include an example here for completeness.
132 {
133 auto l = v.operator->();
134 ASSERT_EQ(10, l->operator[](0) + l->operator[](1) + l->operator[](2) + l->operator[](3));
135 }
136
Andy Hung0f7ad8c2020-01-03 13:24:34 -0800137 // Use Thunk to check whether we have the lock when calling a method through LockWrap.
138
139 class Thunk {
140 std::function<void()> mF;
141
142 public:
Andy Hungb744faf2020-04-09 13:09:26 -0700143 explicit Thunk(decltype(mF) f) : mF(std::move(f)) {}
Andy Hung0f7ad8c2020-01-03 13:24:34 -0800144 void thunk() { mF(); }
145 };
146
147 android::mediametrics::LockWrap<Thunk> s4([&]{
Andy Hung42b99302020-01-10 12:01:18 -0800148 ASSERT_EQ((size_t)1, s4.getRecursionDepth()); // we must be locked when thunk() is called.
Andy Hung0f7ad8c2020-01-03 13:24:34 -0800149 });
150
Andy Hung42b99302020-01-10 12:01:18 -0800151 ASSERT_EQ((size_t)0, s4.getRecursionDepth());
Andy Hung0f7ad8c2020-01-03 13:24:34 -0800152 // This will fail if we are not locked during method access.
153 s4->thunk();
Andy Hung42b99302020-01-10 12:01:18 -0800154 ASSERT_EQ((size_t)0, s4.getRecursionDepth());
Andy Hung0f7ad8c2020-01-03 13:24:34 -0800155}
156
157TEST(mediametrics_tests, lock_wrap_multithread) {
158 class Accumulator {
159 int32_t value_ = 0;
160 public:
161 void add(int32_t incr) {
162 const int32_t temp = value_;
163 sleep(0); // yield
164 value_ = temp + incr;
165 }
166 int32_t get() { return value_; }
167 };
168
169 android::mediametrics::LockWrap<Accumulator> a{}; // locked accumulator succeeds
170 // auto a = std::make_shared<Accumulator>(); // this fails, only 50% adds atomic.
171
172 constexpr size_t THREADS = 100;
173 constexpr size_t ITERATIONS = 10;
174 constexpr int32_t INCREMENT = 1;
175
176 std::vector<std::future<void>> threads(THREADS);
177 for (size_t i = 0; i < THREADS; ++i) {
178 threads.push_back(std::async(std::launch::async, [&] {
179 for (size_t j = 0; j < ITERATIONS; ++j) {
180 a->add(INCREMENT);
181 }
182 }));
183 }
184 threads.clear();
185
186 // If the add operations are not atomic, value will be smaller than expected.
187 ASSERT_EQ(INCREMENT * THREADS * ITERATIONS, (size_t)a->get());
188}
189
Andy Hungc89c8dc2019-10-16 17:48:21 -0700190TEST(mediametrics_tests, instantiate) {
Ray Essickf27e9872019-12-07 06:28:46 -0800191 sp mediaMetrics = new MediaMetricsService();
Andy Hungc89c8dc2019-10-16 17:48:21 -0700192 status_t status;
193
Andy Hungc89c8dc2019-10-16 17:48:21 -0700194 // random keys ignored when empty
Ray Essickf27e9872019-12-07 06:28:46 -0800195 std::unique_ptr<mediametrics::Item> random_key(mediametrics::Item::create("random_key"));
Andy Hunga87e69c2019-10-18 10:07:40 -0700196 status = mediaMetrics->submit(random_key.get());
197 ASSERT_EQ(PERMISSION_DENIED, status);
Andy Hungc89c8dc2019-10-16 17:48:21 -0700198
199 // random keys ignored with data
Andy Hungc89c8dc2019-10-16 17:48:21 -0700200 random_key->setInt32("foo", 10);
Andy Hunga87e69c2019-10-18 10:07:40 -0700201 status = mediaMetrics->submit(random_key.get());
202 ASSERT_EQ(PERMISSION_DENIED, status);
Andy Hungc89c8dc2019-10-16 17:48:21 -0700203
204 // known keys ignored if empty
Ray Essickf27e9872019-12-07 06:28:46 -0800205 std::unique_ptr<mediametrics::Item> audiotrack_key(mediametrics::Item::create("audiotrack"));
Andy Hunga87e69c2019-10-18 10:07:40 -0700206 status = mediaMetrics->submit(audiotrack_key.get());
207 ASSERT_EQ(BAD_VALUE, status);
Andy Hungc89c8dc2019-10-16 17:48:21 -0700208
Andy Hunga87e69c2019-10-18 10:07:40 -0700209 // known keys not ignored if not empty
210 audiotrack_key->addInt32("foo", 10);
211 status = mediaMetrics->submit(audiotrack_key.get());
212 ASSERT_EQ(NO_ERROR, status);
Andy Hungc89c8dc2019-10-16 17:48:21 -0700213
Andy Hungaeef7882019-10-18 15:18:14 -0700214
215 /*
216 // fluent style that goes directly to mediametrics
Ray Essickf27e9872019-12-07 06:28:46 -0800217 ASSERT_EQ(true, mediametrics::Item("audiorecord")
Andy Hungaeef7882019-10-18 15:18:14 -0700218 .setInt32("value", 2)
219 .addInt32("bar", 1)
220 .addInt32("value", 3)
221 .selfrecord());
222 */
223
Andy Hungc89c8dc2019-10-16 17:48:21 -0700224 mediaMetrics->dump(fileno(stdout), {} /* args */);
225}
Andy Hungaeef7882019-10-18 15:18:14 -0700226
Andy Hunga85efab2019-12-23 11:41:29 -0800227TEST(mediametrics_tests, package_installer_check) {
228 ASSERT_EQ(false, MediaMetricsService::useUidForPackage(
229 "abcd", "installer")); // ok, package name has no dot.
230 ASSERT_EQ(false, MediaMetricsService::useUidForPackage(
231 "android.com", "installer")); // ok, package name starts with android
232
233 ASSERT_EQ(false, MediaMetricsService::useUidForPackage(
234 "abc.def", "com.android.foo")); // ok, installer name starts with com.android
235 ASSERT_EQ(false, MediaMetricsService::useUidForPackage(
236 "123.456", "com.google.bar")); // ok, installer name starts with com.google
237 ASSERT_EQ(false, MediaMetricsService::useUidForPackage(
238 "r2.d2", "preload")); // ok, installer name is preload
239
240 ASSERT_EQ(true, MediaMetricsService::useUidForPackage(
241 "abc.def", "installer")); // unknown installer
242 ASSERT_EQ(true, MediaMetricsService::useUidForPackage(
243 "123.456", "installer")); // unknown installer
244 ASSERT_EQ(true, MediaMetricsService::useUidForPackage(
245 "r2.d2", "preload23")); // unknown installer
246
247 ASSERT_EQ(true, MediaMetricsService::useUidForPackage(
248 "com.android.foo", "abc.def")); // unknown installer
249 ASSERT_EQ(true, MediaMetricsService::useUidForPackage(
250 "com.google.bar", "123.456")); // unknown installer
251}
252
Andy Hungaeef7882019-10-18 15:18:14 -0700253TEST(mediametrics_tests, item_manipulation) {
Ray Essickf27e9872019-12-07 06:28:46 -0800254 mediametrics::Item item("audiorecord");
Andy Hungaeef7882019-10-18 15:18:14 -0700255
256 item.setInt32("value", 2).addInt32("bar", 3).addInt32("value", 4);
257
258 int32_t i32;
259 ASSERT_TRUE(item.getInt32("value", &i32));
260 ASSERT_EQ(6, i32);
261
262 ASSERT_TRUE(item.getInt32("bar", &i32));
263 ASSERT_EQ(3, i32);
264
265 item.setInt64("big", INT64_MAX).setInt64("smaller", INT64_MAX - 1).addInt64("smaller", -2);
266
267 int64_t i64;
268 ASSERT_TRUE(item.getInt64("big", &i64));
269 ASSERT_EQ(INT64_MAX, i64);
270
271 ASSERT_TRUE(item.getInt64("smaller", &i64));
272 ASSERT_EQ(INT64_MAX - 3, i64);
273
274 item.setDouble("precise", 10.5).setDouble("small", 0.125).addDouble("precise", 0.25);
275
276 double d;
277 ASSERT_TRUE(item.getDouble("precise", &d));
278 ASSERT_EQ(10.75, d);
279
280 ASSERT_TRUE(item.getDouble("small", &d));
281 ASSERT_EQ(0.125, d);
282
283 char *s;
284 item.setCString("name", "Frank").setCString("mother", "June").setCString("mother", "July");
285 ASSERT_TRUE(item.getCString("name", &s));
286 ASSERT_EQ(0, strcmp(s, "Frank"));
287 free(s);
288
289 ASSERT_TRUE(item.getCString("mother", &s));
290 ASSERT_EQ(0, strcmp(s, "July")); // "July" overwrites "June"
291 free(s);
292
293 item.setRate("burgersPerHour", 5, 2);
294 int64_t b, h;
295 ASSERT_TRUE(item.getRate("burgersPerHour", &b, &h, &d));
296 ASSERT_EQ(5, b);
297 ASSERT_EQ(2, h);
298 ASSERT_EQ(2.5, d);
299
300 item.addRate("burgersPerHour", 4, 2);
301 ASSERT_TRUE(item.getRate("burgersPerHour", &b, &h, &d));
302 ASSERT_EQ(9, b);
303 ASSERT_EQ(4, h);
304 ASSERT_EQ(2.25, d);
305
306 printf("item: %s\n", item.toString().c_str());
307 fflush(stdout);
308
Ray Essickf27e9872019-12-07 06:28:46 -0800309 sp mediaMetrics = new MediaMetricsService();
Andy Hungaeef7882019-10-18 15:18:14 -0700310 status_t status = mediaMetrics->submit(&item);
311 ASSERT_EQ(NO_ERROR, status);
312 mediaMetrics->dump(fileno(stdout), {} /* args */);
313}
314
315TEST(mediametrics_tests, superbig_item) {
Ray Essickf27e9872019-12-07 06:28:46 -0800316 mediametrics::Item item("TheBigOne");
Andy Hungaeef7882019-10-18 15:18:14 -0700317 constexpr size_t count = 10000;
318
319 for (size_t i = 0; i < count; ++i) {
320 item.setInt32(std::to_string(i).c_str(), i);
321 }
322 for (size_t i = 0; i < count; ++i) {
323 int32_t i32;
324 ASSERT_TRUE(item.getInt32(std::to_string(i).c_str(), &i32));
325 ASSERT_EQ((int32_t)i, i32);
326 }
327}
328
329TEST(mediametrics_tests, superbig_item_removal) {
Ray Essickf27e9872019-12-07 06:28:46 -0800330 mediametrics::Item item("TheOddBigOne");
Andy Hungaeef7882019-10-18 15:18:14 -0700331 constexpr size_t count = 10000;
332
333 for (size_t i = 0; i < count; ++i) {
334 item.setInt32(std::to_string(i).c_str(), i);
335 }
336 for (size_t i = 0; i < count; i += 2) {
337 item.filter(std::to_string(i).c_str()); // filter out all the evens.
338 }
339 for (size_t i = 0; i < count; ++i) {
340 int32_t i32;
341 if (i & 1) { // check to see that only the odds are left.
342 ASSERT_TRUE(item.getInt32(std::to_string(i).c_str(), &i32));
343 ASSERT_EQ((int32_t)i, i32);
344 } else {
345 ASSERT_FALSE(item.getInt32(std::to_string(i).c_str(), &i32));
346 }
347 }
348}
349
Andy Hung3253f2d2019-10-21 14:50:07 -0700350TEST(mediametrics_tests, superbig_item_removal2) {
Ray Essickf27e9872019-12-07 06:28:46 -0800351 mediametrics::Item item("TheOne");
Andy Hung3253f2d2019-10-21 14:50:07 -0700352 constexpr size_t count = 10000;
353
354 for (size_t i = 0; i < count; ++i) {
355 item.setInt32(std::to_string(i).c_str(), i);
356 }
357 static const char *attrs[] = { "1", };
358 item.filterNot(1, attrs);
359
360 for (size_t i = 0; i < count; ++i) {
361 int32_t i32;
362 if (i == 1) { // check to see that there is only one
363 ASSERT_TRUE(item.getInt32(std::to_string(i).c_str(), &i32));
364 ASSERT_EQ((int32_t)i, i32);
365 } else {
366 ASSERT_FALSE(item.getInt32(std::to_string(i).c_str(), &i32));
367 }
368 }
369}
370
Andy Hungaeef7882019-10-18 15:18:14 -0700371TEST(mediametrics_tests, item_transmutation) {
Ray Essickf27e9872019-12-07 06:28:46 -0800372 mediametrics::Item item("Alchemist's Stone");
Andy Hungaeef7882019-10-18 15:18:14 -0700373
374 item.setInt64("convert", 123);
375 int64_t i64;
376 ASSERT_TRUE(item.getInt64("convert", &i64));
377 ASSERT_EQ(123, i64);
378
379 item.addInt32("convert", 2); // changes type of 'convert' from i64 to i32 (and re-init).
380 ASSERT_FALSE(item.getInt64("convert", &i64)); // should be false, no value in i64.
381
382 int32_t i32;
383 ASSERT_TRUE(item.getInt32("convert", &i32)); // check it is i32 and 2 (123 is discarded).
384 ASSERT_EQ(2, i32);
385}
Andy Hung3253f2d2019-10-21 14:50:07 -0700386
387TEST(mediametrics_tests, item_binderization) {
Ray Essickf27e9872019-12-07 06:28:46 -0800388 mediametrics::Item item;
Andy Hung3253f2d2019-10-21 14:50:07 -0700389 item.setInt32("i32", 1)
390 .setInt64("i64", 2)
391 .setDouble("double", 3.1)
392 .setCString("string", "abc")
393 .setRate("rate", 11, 12);
394
395 Parcel p;
396 item.writeToParcel(&p);
397
398 p.setDataPosition(0); // rewind for reading
Ray Essickf27e9872019-12-07 06:28:46 -0800399 mediametrics::Item item2;
Andy Hung3253f2d2019-10-21 14:50:07 -0700400 item2.readFromParcel(p);
401
402 ASSERT_EQ(item, item2);
403}
404
405TEST(mediametrics_tests, item_byteserialization) {
Ray Essickf27e9872019-12-07 06:28:46 -0800406 mediametrics::Item item;
Andy Hung3253f2d2019-10-21 14:50:07 -0700407 item.setInt32("i32", 1)
408 .setInt64("i64", 2)
409 .setDouble("double", 3.1)
410 .setCString("string", "abc")
411 .setRate("rate", 11, 12);
412
413 char *data;
414 size_t length;
415 ASSERT_EQ(0, item.writeToByteString(&data, &length));
416 ASSERT_GT(length, (size_t)0);
417
Ray Essickf27e9872019-12-07 06:28:46 -0800418 mediametrics::Item item2;
Andy Hung3253f2d2019-10-21 14:50:07 -0700419 item2.readFromByteString(data, length);
420
421 printf("item: %s\n", item.toString().c_str());
422 printf("item2: %s\n", item2.toString().c_str());
423 ASSERT_EQ(item, item2);
424
425 free(data);
426}
427
428TEST(mediametrics_tests, item_iteration) {
Ray Essickf27e9872019-12-07 06:28:46 -0800429 mediametrics::Item item;
Andy Hung3253f2d2019-10-21 14:50:07 -0700430 item.setInt32("i32", 1)
431 .setInt64("i64", 2)
432 .setDouble("double", 3.125)
433 .setCString("string", "abc")
434 .setRate("rate", 11, 12);
435
436 int mask = 0;
437 for (auto &prop : item) {
438 const char *name = prop.getName();
439 if (!strcmp(name, "i32")) {
440 int32_t i32;
441 ASSERT_TRUE(prop.get(&i32));
442 ASSERT_EQ(1, i32);
Andy Hung692870b2020-01-02 13:46:06 -0800443 ASSERT_EQ(1, std::get<int32_t>(prop.get()));
Andy Hung3253f2d2019-10-21 14:50:07 -0700444 mask |= 1;
445 } else if (!strcmp(name, "i64")) {
446 int64_t i64;
447 ASSERT_TRUE(prop.get(&i64));
448 ASSERT_EQ(2, i64);
Andy Hung692870b2020-01-02 13:46:06 -0800449 ASSERT_EQ(2, std::get<int64_t>(prop.get()));
Andy Hung3253f2d2019-10-21 14:50:07 -0700450 mask |= 2;
451 } else if (!strcmp(name, "double")) {
452 double d;
453 ASSERT_TRUE(prop.get(&d));
454 ASSERT_EQ(3.125, d);
Andy Hung692870b2020-01-02 13:46:06 -0800455 ASSERT_EQ(3.125, std::get<double>(prop.get()));
Andy Hung3253f2d2019-10-21 14:50:07 -0700456 mask |= 4;
457 } else if (!strcmp(name, "string")) {
Andy Hungb7aadb32019-12-09 19:40:42 -0800458 std::string s;
Andy Hung3253f2d2019-10-21 14:50:07 -0700459 ASSERT_TRUE(prop.get(&s));
Andy Hungb7aadb32019-12-09 19:40:42 -0800460 ASSERT_EQ("abc", s);
Andy Hung692870b2020-01-02 13:46:06 -0800461 ASSERT_EQ(s, std::get<std::string>(prop.get()));
Andy Hung3253f2d2019-10-21 14:50:07 -0700462 mask |= 8;
463 } else if (!strcmp(name, "rate")) {
464 std::pair<int64_t, int64_t> r;
465 ASSERT_TRUE(prop.get(&r));
466 ASSERT_EQ(11, r.first);
467 ASSERT_EQ(12, r.second);
Andy Hung692870b2020-01-02 13:46:06 -0800468 ASSERT_EQ(r, std::get<decltype(r)>(prop.get()));
Andy Hung3253f2d2019-10-21 14:50:07 -0700469 mask |= 16;
470 } else {
471 FAIL();
472 }
473 }
474 ASSERT_EQ(31, mask);
475}
Andy Hung1efc9c62019-12-03 13:43:33 -0800476
477TEST(mediametrics_tests, item_expansion) {
Ray Essickf27e9872019-12-07 06:28:46 -0800478 mediametrics::LogItem<1> item("I");
Andy Hung1efc9c62019-12-03 13:43:33 -0800479 item.set("i32", (int32_t)1)
480 .set("i64", (int64_t)2)
481 .set("double", (double)3.125)
482 .set("string", "abcdefghijklmnopqrstuvwxyz")
483 .set("rate", std::pair<int64_t, int64_t>(11, 12));
484 ASSERT_TRUE(item.updateHeader());
485
Ray Essickf27e9872019-12-07 06:28:46 -0800486 mediametrics::Item item2;
Andy Hung1efc9c62019-12-03 13:43:33 -0800487 item2.readFromByteString(item.getBuffer(), item.getLength());
488 ASSERT_EQ((pid_t)-1, item2.getPid());
489 ASSERT_EQ((uid_t)-1, item2.getUid());
490 int mask = 0;
491 for (auto &prop : item2) {
492 const char *name = prop.getName();
493 if (!strcmp(name, "i32")) {
494 int32_t i32;
495 ASSERT_TRUE(prop.get(&i32));
496 ASSERT_EQ(1, i32);
497 mask |= 1;
498 } else if (!strcmp(name, "i64")) {
499 int64_t i64;
500 ASSERT_TRUE(prop.get(&i64));
501 ASSERT_EQ(2, i64);
502 mask |= 2;
503 } else if (!strcmp(name, "double")) {
504 double d;
505 ASSERT_TRUE(prop.get(&d));
506 ASSERT_EQ(3.125, d);
507 mask |= 4;
508 } else if (!strcmp(name, "string")) {
Andy Hungb7aadb32019-12-09 19:40:42 -0800509 std::string s;
Andy Hung1efc9c62019-12-03 13:43:33 -0800510 ASSERT_TRUE(prop.get(&s));
Andy Hungb7aadb32019-12-09 19:40:42 -0800511 ASSERT_EQ("abcdefghijklmnopqrstuvwxyz", s);
Andy Hung1efc9c62019-12-03 13:43:33 -0800512 mask |= 8;
513 } else if (!strcmp(name, "rate")) {
514 std::pair<int64_t, int64_t> r;
515 ASSERT_TRUE(prop.get(&r));
516 ASSERT_EQ(11, r.first);
517 ASSERT_EQ(12, r.second);
518 mask |= 16;
519 } else {
520 FAIL();
521 }
522 }
523 ASSERT_EQ(31, mask);
524}
525
526TEST(mediametrics_tests, item_expansion2) {
Ray Essickf27e9872019-12-07 06:28:46 -0800527 mediametrics::LogItem<1> item("Bigly");
Andy Hung1efc9c62019-12-03 13:43:33 -0800528 item.setPid(123)
529 .setUid(456);
530 constexpr size_t count = 10000;
531
532 for (size_t i = 0; i < count; ++i) {
533 // printf("recording %zu, %p, len:%zu of %zu remaining:%zu \n", i, item.getBuffer(), item.getLength(), item.getCapacity(), item.getRemaining());
534 item.set(std::to_string(i).c_str(), (int32_t)i);
535 }
536 ASSERT_TRUE(item.updateHeader());
537
Ray Essickf27e9872019-12-07 06:28:46 -0800538 mediametrics::Item item2;
Andy Hung1efc9c62019-12-03 13:43:33 -0800539 printf("begin buffer:%p length:%zu\n", item.getBuffer(), item.getLength());
540 fflush(stdout);
541 item2.readFromByteString(item.getBuffer(), item.getLength());
542
543 ASSERT_EQ((pid_t)123, item2.getPid());
544 ASSERT_EQ((uid_t)456, item2.getUid());
545 for (size_t i = 0; i < count; ++i) {
546 int32_t i32;
547 ASSERT_TRUE(item2.getInt32(std::to_string(i).c_str(), &i32));
548 ASSERT_EQ((int32_t)i, i32);
549 }
550}
Andy Hung06f3aba2019-12-03 16:36:42 -0800551
552TEST(mediametrics_tests, time_machine_storage) {
Ray Essickf27e9872019-12-07 06:28:46 -0800553 auto item = std::make_shared<mediametrics::Item>("Key");
Andy Hung06f3aba2019-12-03 16:36:42 -0800554 (*item).set("i32", (int32_t)1)
555 .set("i64", (int64_t)2)
556 .set("double", (double)3.125)
557 .set("string", "abcdefghijklmnopqrstuvwxyz")
558 .set("rate", std::pair<int64_t, int64_t>(11, 12));
559
560 // Let's put the item in
561 android::mediametrics::TimeMachine timeMachine;
562 ASSERT_EQ(NO_ERROR, timeMachine.put(item, true));
563
564 // Can we read the values?
565 int32_t i32;
566 ASSERT_EQ(NO_ERROR, timeMachine.get("Key", "i32", &i32, -1));
567 ASSERT_EQ(1, i32);
568
569 int64_t i64;
570 ASSERT_EQ(NO_ERROR, timeMachine.get("Key", "i64", &i64, -1));
571 ASSERT_EQ(2, i64);
572
573 double d;
574 ASSERT_EQ(NO_ERROR, timeMachine.get("Key", "double", &d, -1));
575 ASSERT_EQ(3.125, d);
576
577 std::string s;
578 ASSERT_EQ(NO_ERROR, timeMachine.get("Key", "string", &s, -1));
579 ASSERT_EQ("abcdefghijklmnopqrstuvwxyz", s);
580
581 // Using fully qualified name?
582 i32 = 0;
583 ASSERT_EQ(NO_ERROR, timeMachine.get("Key.i32", &i32, -1));
584 ASSERT_EQ(1, i32);
585
586 i64 = 0;
587 ASSERT_EQ(NO_ERROR, timeMachine.get("Key.i64", &i64, -1));
588 ASSERT_EQ(2, i64);
589
590 d = 0.;
591 ASSERT_EQ(NO_ERROR, timeMachine.get("Key.double", &d, -1));
592 ASSERT_EQ(3.125, d);
593
594 s.clear();
595 ASSERT_EQ(NO_ERROR, timeMachine.get("Key.string", &s, -1));
596 ASSERT_EQ("abcdefghijklmnopqrstuvwxyz", s);
597}
598
599TEST(mediametrics_tests, time_machine_remote_key) {
Ray Essickf27e9872019-12-07 06:28:46 -0800600 auto item = std::make_shared<mediametrics::Item>("Key1");
Andy Hung06f3aba2019-12-03 16:36:42 -0800601 (*item).set("one", (int32_t)1)
602 .set("two", (int32_t)2);
603
604 android::mediametrics::TimeMachine timeMachine;
605 ASSERT_EQ(NO_ERROR, timeMachine.put(item, true));
606
Ray Essickf27e9872019-12-07 06:28:46 -0800607 auto item2 = std::make_shared<mediametrics::Item>("Key2");
Andy Hung06f3aba2019-12-03 16:36:42 -0800608 (*item2).set("three", (int32_t)3)
609 .set("[Key1]four", (int32_t)4) // affects Key1
610 .set("[Key1]five", (int32_t)5); // affects key1
611
612 ASSERT_EQ(NO_ERROR, timeMachine.put(item2, true));
613
Ray Essickf27e9872019-12-07 06:28:46 -0800614 auto item3 = std::make_shared<mediametrics::Item>("Key2");
Andy Hung06f3aba2019-12-03 16:36:42 -0800615 (*item3).set("six", (int32_t)6)
616 .set("[Key1]seven", (int32_t)7); // affects Key1
617
618 ASSERT_EQ(NO_ERROR, timeMachine.put(item3, false)); // remote keys not allowed.
619
620 // Can we read the values?
621 int32_t i32;
622 ASSERT_EQ(NO_ERROR, timeMachine.get("Key1.one", &i32, -1));
623 ASSERT_EQ(1, i32);
624
625 ASSERT_EQ(NO_ERROR, timeMachine.get("Key1.two", &i32, -1));
626 ASSERT_EQ(2, i32);
627
628 ASSERT_EQ(BAD_VALUE, timeMachine.get("Key1.three", &i32, -1));
629
630 ASSERT_EQ(NO_ERROR, timeMachine.get("Key2.three", &i32, -1));
631 ASSERT_EQ(3, i32);
632
633 ASSERT_EQ(NO_ERROR, timeMachine.get("Key1.four", &i32, -1));
634 ASSERT_EQ(4, i32);
635
636 ASSERT_EQ(BAD_VALUE, timeMachine.get("Key2.four", &i32, -1));
637
638 ASSERT_EQ(NO_ERROR, timeMachine.get("Key1.five", &i32, -1));
639 ASSERT_EQ(5, i32);
640
641 ASSERT_EQ(BAD_VALUE, timeMachine.get("Key2.five", &i32, -1));
642
643 ASSERT_EQ(NO_ERROR, timeMachine.get("Key2.six", &i32, -1));
644 ASSERT_EQ(6, i32);
645
646 ASSERT_EQ(BAD_VALUE, timeMachine.get("Key2.seven", &i32, -1));
647}
648
649TEST(mediametrics_tests, time_machine_gc) {
Ray Essickf27e9872019-12-07 06:28:46 -0800650 auto item = std::make_shared<mediametrics::Item>("Key1");
Andy Hung06f3aba2019-12-03 16:36:42 -0800651 (*item).set("one", (int32_t)1)
652 .set("two", (int32_t)2)
653 .setTimestamp(10);
654
655 android::mediametrics::TimeMachine timeMachine(1, 2); // keep at most 2 keys.
656
657 ASSERT_EQ((size_t)0, timeMachine.size());
658
659 ASSERT_EQ(NO_ERROR, timeMachine.put(item, true));
660
661 ASSERT_EQ((size_t)1, timeMachine.size());
662
Ray Essickf27e9872019-12-07 06:28:46 -0800663 auto item2 = std::make_shared<mediametrics::Item>("Key2");
Andy Hung06f3aba2019-12-03 16:36:42 -0800664 (*item2).set("three", (int32_t)3)
665 .set("[Key1]three", (int32_t)3)
666 .setTimestamp(11);
667
668 ASSERT_EQ(NO_ERROR, timeMachine.put(item2, true));
669 ASSERT_EQ((size_t)2, timeMachine.size());
670
671 //printf("Before\n%s\n\n", timeMachine.dump().c_str());
672
Ray Essickf27e9872019-12-07 06:28:46 -0800673 auto item3 = std::make_shared<mediametrics::Item>("Key3");
Andy Hung06f3aba2019-12-03 16:36:42 -0800674 (*item3).set("six", (int32_t)6)
675 .set("[Key1]four", (int32_t)4) // affects Key1
676 .set("[Key1]five", (int32_t)5) // affects key1
677 .setTimestamp(12);
678
679 ASSERT_EQ(NO_ERROR, timeMachine.put(item3, true));
680
681 ASSERT_EQ((size_t)2, timeMachine.size());
682
683 // Can we read the values?
684 int32_t i32;
685 ASSERT_EQ(BAD_VALUE, timeMachine.get("Key1.one", &i32, -1));
686 ASSERT_EQ(BAD_VALUE, timeMachine.get("Key1.two", &i32, -1));
687 ASSERT_EQ(BAD_VALUE, timeMachine.get("Key1.three", &i32, -1));
688 ASSERT_EQ(BAD_VALUE, timeMachine.get("Key1.four", &i32, -1));
689 ASSERT_EQ(BAD_VALUE, timeMachine.get("Key1.five", &i32, -1));
690
691 ASSERT_EQ(NO_ERROR, timeMachine.get("Key2.three", &i32, -1));
692 ASSERT_EQ(3, i32);
693
694 ASSERT_EQ(NO_ERROR, timeMachine.get("Key3.six", &i32, -1));
695 ASSERT_EQ(6, i32);
696
697 printf("After\n%s\n", timeMachine.dump().first.c_str());
698}
699
700TEST(mediametrics_tests, transaction_log_gc) {
Ray Essickf27e9872019-12-07 06:28:46 -0800701 auto item = std::make_shared<mediametrics::Item>("Key1");
Andy Hung06f3aba2019-12-03 16:36:42 -0800702 (*item).set("one", (int32_t)1)
703 .set("two", (int32_t)2)
704 .setTimestamp(10);
705
706 android::mediametrics::TransactionLog transactionLog(1, 2); // keep at most 2 items
707 ASSERT_EQ((size_t)0, transactionLog.size());
708
709 ASSERT_EQ(NO_ERROR, transactionLog.put(item));
710 ASSERT_EQ((size_t)1, transactionLog.size());
711
Ray Essickf27e9872019-12-07 06:28:46 -0800712 auto item2 = std::make_shared<mediametrics::Item>("Key2");
Andy Hung06f3aba2019-12-03 16:36:42 -0800713 (*item2).set("three", (int32_t)3)
714 .set("[Key1]three", (int32_t)3)
715 .setTimestamp(11);
716
717 ASSERT_EQ(NO_ERROR, transactionLog.put(item2));
718 ASSERT_EQ((size_t)2, transactionLog.size());
719
Ray Essickf27e9872019-12-07 06:28:46 -0800720 auto item3 = std::make_shared<mediametrics::Item>("Key3");
Andy Hung06f3aba2019-12-03 16:36:42 -0800721 (*item3).set("six", (int32_t)6)
722 .set("[Key1]four", (int32_t)4) // affects Key1
723 .set("[Key1]five", (int32_t)5) // affects key1
724 .setTimestamp(12);
725
726 ASSERT_EQ(NO_ERROR, transactionLog.put(item3));
727 ASSERT_EQ((size_t)2, transactionLog.size());
728}
729
Andy Hung0f7ad8c2020-01-03 13:24:34 -0800730TEST(mediametrics_tests, analytics_actions) {
731 mediametrics::AnalyticsActions analyticsActions;
732 bool action1 = false;
733 bool action2 = false;
734 bool action3 = false;
735 bool action4 = false;
736
737 // check to see whether various actions have been matched.
738 analyticsActions.addAction(
739 "audio.flinger.event",
740 std::string("AudioFlinger"),
741 std::make_shared<mediametrics::AnalyticsActions::Function>(
742 [&](const std::shared_ptr<const android::mediametrics::Item> &) {
743 action1 = true;
744 }));
745
746 analyticsActions.addAction(
747 "audio.*.event",
748 std::string("AudioFlinger"),
749 std::make_shared<mediametrics::AnalyticsActions::Function>(
750 [&](const std::shared_ptr<const android::mediametrics::Item> &) {
751 action2 = true;
752 }));
753
754 analyticsActions.addAction("audio.fl*n*g*r.event",
755 std::string("AudioFlinger"),
756 std::make_shared<mediametrics::AnalyticsActions::Function>(
757 [&](const std::shared_ptr<const android::mediametrics::Item> &) {
758 action3 = true;
759 }));
760
761 analyticsActions.addAction("audio.fl*gn*r.event",
762 std::string("AudioFlinger"),
763 std::make_shared<mediametrics::AnalyticsActions::Function>(
764 [&](const std::shared_ptr<const android::mediametrics::Item> &) {
765 action4 = true;
766 }));
767
768 // make a test item
769 auto item = std::make_shared<mediametrics::Item>("audio.flinger");
770 (*item).set("event", "AudioFlinger");
771
772 // get the actions and execute them
773 auto actions = analyticsActions.getActionsForItem(item);
774 for (const auto& action : actions) {
775 action->operator()(item);
776 }
777
778 // The following should match.
779 ASSERT_EQ(true, action1);
780 ASSERT_EQ(true, action2);
781 ASSERT_EQ(true, action3);
782 ASSERT_EQ(false, action4); // audio.fl*gn*r != audio.flinger
783}
784
Andy Hung06f3aba2019-12-03 16:36:42 -0800785TEST(mediametrics_tests, audio_analytics_permission) {
Ray Essickf27e9872019-12-07 06:28:46 -0800786 auto item = std::make_shared<mediametrics::Item>("audio.1");
Andy Hung06f3aba2019-12-03 16:36:42 -0800787 (*item).set("one", (int32_t)1)
788 .set("two", (int32_t)2)
789 .setTimestamp(10);
790
Ray Essickf27e9872019-12-07 06:28:46 -0800791 auto item2 = std::make_shared<mediametrics::Item>("audio.1");
Andy Hung06f3aba2019-12-03 16:36:42 -0800792 (*item2).set("three", (int32_t)3)
793 .setTimestamp(11);
794
Ray Essickf27e9872019-12-07 06:28:46 -0800795 auto item3 = std::make_shared<mediametrics::Item>("audio.2");
Andy Hung06f3aba2019-12-03 16:36:42 -0800796 (*item3).set("four", (int32_t)4)
797 .setTimestamp(12);
798
799 android::mediametrics::AudioAnalytics audioAnalytics;
800
801 // untrusted entities cannot create a new key.
802 ASSERT_EQ(PERMISSION_DENIED, audioAnalytics.submit(item, false /* isTrusted */));
803 ASSERT_EQ(PERMISSION_DENIED, audioAnalytics.submit(item2, false /* isTrusted */));
804
805 // TODO: Verify contents of AudioAnalytics.
806 // Currently there is no getter API in AudioAnalytics besides dump.
Joey Poomarin52989982020-03-05 17:40:49 +0800807 ASSERT_EQ(10, audioAnalytics.dump(1000).second /* lines */);
Andy Hung06f3aba2019-12-03 16:36:42 -0800808
809 ASSERT_EQ(NO_ERROR, audioAnalytics.submit(item, true /* isTrusted */));
810 // untrusted entities can add to an existing key
811 ASSERT_EQ(NO_ERROR, audioAnalytics.submit(item2, false /* isTrusted */));
812
813 // Check that we have some info in the dump.
Andy Hung0f7ad8c2020-01-03 13:24:34 -0800814 ASSERT_LT(9, audioAnalytics.dump(1000).second /* lines */);
Andy Hung06f3aba2019-12-03 16:36:42 -0800815}
816
Andy Hungd203eb62020-04-27 09:12:46 -0700817TEST(mediametrics_tests, audio_analytics_permission2) {
818 constexpr int32_t transactionUid = 1010; // arbitrary
819 auto item = std::make_shared<mediametrics::Item>("audio.1");
820 (*item).set("one", (int32_t)1)
821 .set("two", (int32_t)2)
822 .set(AMEDIAMETRICS_PROP_ALLOWUID, transactionUid)
823 .setTimestamp(10);
824
825 // item2 submitted untrusted
826 auto item2 = std::make_shared<mediametrics::Item>("audio.1");
827 (*item2).set("three", (int32_t)3)
828 .setUid(transactionUid)
829 .setTimestamp(11);
830
831 auto item3 = std::make_shared<mediametrics::Item>("audio.2");
832 (*item3).set("four", (int32_t)4)
833 .setTimestamp(12);
834
835 android::mediametrics::AudioAnalytics audioAnalytics;
836
837 // untrusted entities cannot create a new key.
838 ASSERT_EQ(PERMISSION_DENIED, audioAnalytics.submit(item, false /* isTrusted */));
839 ASSERT_EQ(PERMISSION_DENIED, audioAnalytics.submit(item2, false /* isTrusted */));
840
841 // TODO: Verify contents of AudioAnalytics.
842 // Currently there is no getter API in AudioAnalytics besides dump.
Joey Poomarin52989982020-03-05 17:40:49 +0800843 ASSERT_EQ(10, audioAnalytics.dump(1000).second /* lines */);
Andy Hungd203eb62020-04-27 09:12:46 -0700844
845 ASSERT_EQ(NO_ERROR, audioAnalytics.submit(item, true /* isTrusted */));
846 // untrusted entities can add to an existing key
847 ASSERT_EQ(NO_ERROR, audioAnalytics.submit(item2, false /* isTrusted */));
848
849 // Check that we have some info in the dump.
850 ASSERT_LT(9, audioAnalytics.dump(1000).second /* lines */);
851}
852
Andy Hung06f3aba2019-12-03 16:36:42 -0800853TEST(mediametrics_tests, audio_analytics_dump) {
Ray Essickf27e9872019-12-07 06:28:46 -0800854 auto item = std::make_shared<mediametrics::Item>("audio.1");
Andy Hung06f3aba2019-12-03 16:36:42 -0800855 (*item).set("one", (int32_t)1)
856 .set("two", (int32_t)2)
857 .setTimestamp(10);
858
Ray Essickf27e9872019-12-07 06:28:46 -0800859 auto item2 = std::make_shared<mediametrics::Item>("audio.1");
Andy Hung06f3aba2019-12-03 16:36:42 -0800860 (*item2).set("three", (int32_t)3)
861 .setTimestamp(11);
862
Ray Essickf27e9872019-12-07 06:28:46 -0800863 auto item3 = std::make_shared<mediametrics::Item>("audio.2");
Andy Hung06f3aba2019-12-03 16:36:42 -0800864 (*item3).set("four", (int32_t)4)
865 .setTimestamp(12);
866
867 android::mediametrics::AudioAnalytics audioAnalytics;
868
869 ASSERT_EQ(NO_ERROR, audioAnalytics.submit(item, true /* isTrusted */));
870 // untrusted entities can add to an existing key
871 ASSERT_EQ(NO_ERROR, audioAnalytics.submit(item2, false /* isTrusted */));
872 ASSERT_EQ(NO_ERROR, audioAnalytics.submit(item3, true /* isTrusted */));
873
874 // find out how many lines we have.
875 auto [string, lines] = audioAnalytics.dump(1000);
876 ASSERT_EQ(lines, (int32_t) countNewlines(string.c_str()));
877
878 printf("AudioAnalytics: %s", string.c_str());
879 // ensure that dump operates over those lines.
880 for (int32_t ll = 0; ll < lines; ++ll) {
881 auto [s, l] = audioAnalytics.dump(ll);
882 ASSERT_EQ(ll, l);
883 ASSERT_EQ(ll, (int32_t) countNewlines(s.c_str()));
884 }
885}
Andy Hung5d3f2d12020-03-04 19:55:03 -0800886
Andy Hungce9b6632020-04-28 20:15:17 -0700887TEST(mediametrics_tests, device_parsing) {
Andy Hung1ea842e2020-05-18 10:47:31 -0700888 auto devaddr = android::mediametrics::stringutils::getDeviceAddressPairs("(DEVICE, )");
Andy Hungce9b6632020-04-28 20:15:17 -0700889 ASSERT_EQ((size_t)1, devaddr.size());
890 ASSERT_EQ("DEVICE", devaddr[0].first);
891 ASSERT_EQ("", devaddr[0].second);
892
Andy Hung1ea842e2020-05-18 10:47:31 -0700893 devaddr = android::mediametrics::stringutils::getDeviceAddressPairs(
Andy Hungce9b6632020-04-28 20:15:17 -0700894 "(DEVICE1, A)|(D, ADDRB)");
895 ASSERT_EQ((size_t)2, devaddr.size());
896 ASSERT_EQ("DEVICE1", devaddr[0].first);
897 ASSERT_EQ("A", devaddr[0].second);
898 ASSERT_EQ("D", devaddr[1].first);
899 ASSERT_EQ("ADDRB", devaddr[1].second);
900
Andy Hung1ea842e2020-05-18 10:47:31 -0700901 devaddr = android::mediametrics::stringutils::getDeviceAddressPairs(
Andy Hungce9b6632020-04-28 20:15:17 -0700902 "(A,B)|(C,D)");
903 ASSERT_EQ((size_t)2, devaddr.size());
904 ASSERT_EQ("A", devaddr[0].first);
905 ASSERT_EQ("B", devaddr[0].second);
906 ASSERT_EQ("C", devaddr[1].first);
907 ASSERT_EQ("D", devaddr[1].second);
908
Andy Hung1ea842e2020-05-18 10:47:31 -0700909 devaddr = android::mediametrics::stringutils::getDeviceAddressPairs(
Andy Hungce9b6632020-04-28 20:15:17 -0700910 " ( A1 , B ) | ( C , D2 ) ");
911 ASSERT_EQ((size_t)2, devaddr.size());
912 ASSERT_EQ("A1", devaddr[0].first);
913 ASSERT_EQ("B", devaddr[0].second);
914 ASSERT_EQ("C", devaddr[1].first);
915 ASSERT_EQ("D2", devaddr[1].second);
916}
917
918TEST(mediametrics_tests, timed_action) {
919 android::mediametrics::TimedAction timedAction;
920 std::atomic_int value1 = 0;
921
922 timedAction.postIn(std::chrono::seconds(0), [&value1] { ++value1; });
923 timedAction.postIn(std::chrono::seconds(1000), [&value1] { ++value1; });
924 usleep(100000);
925 ASSERT_EQ(1, value1);
926 ASSERT_EQ((size_t)1, timedAction.size());
927}
928
Andy Hung5d3f2d12020-03-04 19:55:03 -0800929#if 0
930// Stress test code for garbage collection, you need to enable AID_SHELL as trusted to run
931// in MediaMetricsService.cpp.
932//
933// TODO: Make a dedicated stress test.
934//
935TEST(mediametrics_tests, gc_same_key) {
936 // random keys ignored when empty
937 for (int i = 0; i < 10000000; ++i) {
938 std::unique_ptr<mediametrics::Item> test_key(mediametrics::Item::create("audio.zzz.123"));
939 test_key->set("event#", "hello");
940 test_key->set("value", (int)10);
941 test_key->selfrecord();
942 }
943 //mediaMetrics->dump(fileno(stdout), {} /* args */);
944}
945#endif