change media analytics references to media metrics
part 1: make directory names coherent.
Bug: 145780674
Test: build
Test: atest mediametrics_test
Test: atest CtsNativeMediaMetricsTestCases
Change-Id: If552a742df02206f703801a6530b66fe5addac53
diff --git a/services/mediametrics/tests/mediametrics_tests.cpp b/services/mediametrics/tests/mediametrics_tests.cpp
new file mode 100644
index 0000000..808da7b
--- /dev/null
+++ b/services/mediametrics/tests/mediametrics_tests.cpp
@@ -0,0 +1,611 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "mediametrics_tests"
+#include <utils/Log.h>
+
+#include "MediaMetricsService.h"
+
+#include <stdio.h>
+
+#include <gtest/gtest.h>
+#include <media/MediaAnalyticsItem.h>
+
+using namespace android;
+
+static size_t countNewlines(const char *s) {
+ size_t count = 0;
+ while ((s = strchr(s, '\n')) != nullptr) {
+ ++s;
+ ++count;
+ }
+ return count;
+}
+
+TEST(mediametrics_tests, instantiate) {
+ sp mediaMetrics = new MediaAnalyticsService();
+ status_t status;
+
+ // random keys ignored when empty
+ std::unique_ptr<MediaAnalyticsItem> random_key(MediaAnalyticsItem::create("random_key"));
+ status = mediaMetrics->submit(random_key.get());
+ ASSERT_EQ(PERMISSION_DENIED, status);
+
+ // random keys ignored with data
+ random_key->setInt32("foo", 10);
+ status = mediaMetrics->submit(random_key.get());
+ ASSERT_EQ(PERMISSION_DENIED, status);
+
+ // known keys ignored if empty
+ std::unique_ptr<MediaAnalyticsItem> audiotrack_key(MediaAnalyticsItem::create("audiotrack"));
+ status = mediaMetrics->submit(audiotrack_key.get());
+ ASSERT_EQ(BAD_VALUE, status);
+
+ // known keys not ignored if not empty
+ audiotrack_key->addInt32("foo", 10);
+ status = mediaMetrics->submit(audiotrack_key.get());
+ ASSERT_EQ(NO_ERROR, status);
+
+
+ /*
+ // fluent style that goes directly to mediametrics
+ ASSERT_EQ(true, MediaAnalyticsItem("audiorecord")
+ .setInt32("value", 2)
+ .addInt32("bar", 1)
+ .addInt32("value", 3)
+ .selfrecord());
+ */
+
+ mediaMetrics->dump(fileno(stdout), {} /* args */);
+}
+
+TEST(mediametrics_tests, item_manipulation) {
+ MediaAnalyticsItem item("audiorecord");
+
+ item.setInt32("value", 2).addInt32("bar", 3).addInt32("value", 4);
+
+ int32_t i32;
+ ASSERT_TRUE(item.getInt32("value", &i32));
+ ASSERT_EQ(6, i32);
+
+ ASSERT_TRUE(item.getInt32("bar", &i32));
+ ASSERT_EQ(3, i32);
+
+ item.setInt64("big", INT64_MAX).setInt64("smaller", INT64_MAX - 1).addInt64("smaller", -2);
+
+ int64_t i64;
+ ASSERT_TRUE(item.getInt64("big", &i64));
+ ASSERT_EQ(INT64_MAX, i64);
+
+ ASSERT_TRUE(item.getInt64("smaller", &i64));
+ ASSERT_EQ(INT64_MAX - 3, i64);
+
+ item.setDouble("precise", 10.5).setDouble("small", 0.125).addDouble("precise", 0.25);
+
+ double d;
+ ASSERT_TRUE(item.getDouble("precise", &d));
+ ASSERT_EQ(10.75, d);
+
+ ASSERT_TRUE(item.getDouble("small", &d));
+ ASSERT_EQ(0.125, d);
+
+ char *s;
+ item.setCString("name", "Frank").setCString("mother", "June").setCString("mother", "July");
+ ASSERT_TRUE(item.getCString("name", &s));
+ ASSERT_EQ(0, strcmp(s, "Frank"));
+ free(s);
+
+ ASSERT_TRUE(item.getCString("mother", &s));
+ ASSERT_EQ(0, strcmp(s, "July")); // "July" overwrites "June"
+ free(s);
+
+ item.setRate("burgersPerHour", 5, 2);
+ int64_t b, h;
+ ASSERT_TRUE(item.getRate("burgersPerHour", &b, &h, &d));
+ ASSERT_EQ(5, b);
+ ASSERT_EQ(2, h);
+ ASSERT_EQ(2.5, d);
+
+ item.addRate("burgersPerHour", 4, 2);
+ ASSERT_TRUE(item.getRate("burgersPerHour", &b, &h, &d));
+ ASSERT_EQ(9, b);
+ ASSERT_EQ(4, h);
+ ASSERT_EQ(2.25, d);
+
+ printf("item: %s\n", item.toString().c_str());
+ fflush(stdout);
+
+ sp mediaMetrics = new MediaAnalyticsService();
+ status_t status = mediaMetrics->submit(&item);
+ ASSERT_EQ(NO_ERROR, status);
+ mediaMetrics->dump(fileno(stdout), {} /* args */);
+}
+
+TEST(mediametrics_tests, superbig_item) {
+ MediaAnalyticsItem item("TheBigOne");
+ constexpr size_t count = 10000;
+
+ for (size_t i = 0; i < count; ++i) {
+ item.setInt32(std::to_string(i).c_str(), i);
+ }
+ for (size_t i = 0; i < count; ++i) {
+ int32_t i32;
+ ASSERT_TRUE(item.getInt32(std::to_string(i).c_str(), &i32));
+ ASSERT_EQ((int32_t)i, i32);
+ }
+}
+
+TEST(mediametrics_tests, superbig_item_removal) {
+ MediaAnalyticsItem item("TheOddBigOne");
+ constexpr size_t count = 10000;
+
+ for (size_t i = 0; i < count; ++i) {
+ item.setInt32(std::to_string(i).c_str(), i);
+ }
+ for (size_t i = 0; i < count; i += 2) {
+ item.filter(std::to_string(i).c_str()); // filter out all the evens.
+ }
+ for (size_t i = 0; i < count; ++i) {
+ int32_t i32;
+ if (i & 1) { // check to see that only the odds are left.
+ ASSERT_TRUE(item.getInt32(std::to_string(i).c_str(), &i32));
+ ASSERT_EQ((int32_t)i, i32);
+ } else {
+ ASSERT_FALSE(item.getInt32(std::to_string(i).c_str(), &i32));
+ }
+ }
+}
+
+TEST(mediametrics_tests, superbig_item_removal2) {
+ MediaAnalyticsItem item("TheOne");
+ constexpr size_t count = 10000;
+
+ for (size_t i = 0; i < count; ++i) {
+ item.setInt32(std::to_string(i).c_str(), i);
+ }
+ static const char *attrs[] = { "1", };
+ item.filterNot(1, attrs);
+
+ for (size_t i = 0; i < count; ++i) {
+ int32_t i32;
+ if (i == 1) { // check to see that there is only one
+ ASSERT_TRUE(item.getInt32(std::to_string(i).c_str(), &i32));
+ ASSERT_EQ((int32_t)i, i32);
+ } else {
+ ASSERT_FALSE(item.getInt32(std::to_string(i).c_str(), &i32));
+ }
+ }
+}
+
+TEST(mediametrics_tests, item_transmutation) {
+ MediaAnalyticsItem item("Alchemist's Stone");
+
+ item.setInt64("convert", 123);
+ int64_t i64;
+ ASSERT_TRUE(item.getInt64("convert", &i64));
+ ASSERT_EQ(123, i64);
+
+ item.addInt32("convert", 2); // changes type of 'convert' from i64 to i32 (and re-init).
+ ASSERT_FALSE(item.getInt64("convert", &i64)); // should be false, no value in i64.
+
+ int32_t i32;
+ ASSERT_TRUE(item.getInt32("convert", &i32)); // check it is i32 and 2 (123 is discarded).
+ ASSERT_EQ(2, i32);
+}
+
+TEST(mediametrics_tests, item_binderization) {
+ MediaAnalyticsItem item;
+ item.setInt32("i32", 1)
+ .setInt64("i64", 2)
+ .setDouble("double", 3.1)
+ .setCString("string", "abc")
+ .setRate("rate", 11, 12);
+
+ Parcel p;
+ item.writeToParcel(&p);
+
+ p.setDataPosition(0); // rewind for reading
+ MediaAnalyticsItem item2;
+ item2.readFromParcel(p);
+
+ ASSERT_EQ(item, item2);
+}
+
+TEST(mediametrics_tests, item_byteserialization) {
+ MediaAnalyticsItem item;
+ item.setInt32("i32", 1)
+ .setInt64("i64", 2)
+ .setDouble("double", 3.1)
+ .setCString("string", "abc")
+ .setRate("rate", 11, 12);
+
+ char *data;
+ size_t length;
+ ASSERT_EQ(0, item.writeToByteString(&data, &length));
+ ASSERT_GT(length, (size_t)0);
+
+ MediaAnalyticsItem item2;
+ item2.readFromByteString(data, length);
+
+ printf("item: %s\n", item.toString().c_str());
+ printf("item2: %s\n", item2.toString().c_str());
+ ASSERT_EQ(item, item2);
+
+ free(data);
+}
+
+TEST(mediametrics_tests, item_iteration) {
+ MediaAnalyticsItem item;
+ item.setInt32("i32", 1)
+ .setInt64("i64", 2)
+ .setDouble("double", 3.125)
+ .setCString("string", "abc")
+ .setRate("rate", 11, 12);
+
+ int mask = 0;
+ for (auto &prop : item) {
+ const char *name = prop.getName();
+ if (!strcmp(name, "i32")) {
+ int32_t i32;
+ ASSERT_TRUE(prop.get(&i32));
+ ASSERT_EQ(1, i32);
+ mask |= 1;
+ } else if (!strcmp(name, "i64")) {
+ int64_t i64;
+ ASSERT_TRUE(prop.get(&i64));
+ ASSERT_EQ(2, i64);
+ mask |= 2;
+ } else if (!strcmp(name, "double")) {
+ double d;
+ ASSERT_TRUE(prop.get(&d));
+ ASSERT_EQ(3.125, d);
+ mask |= 4;
+ } else if (!strcmp(name, "string")) {
+ const char *s;
+ ASSERT_TRUE(prop.get(&s));
+ ASSERT_EQ(0, strcmp(s, "abc"));
+ mask |= 8;
+ } else if (!strcmp(name, "rate")) {
+ std::pair<int64_t, int64_t> r;
+ ASSERT_TRUE(prop.get(&r));
+ ASSERT_EQ(11, r.first);
+ ASSERT_EQ(12, r.second);
+ mask |= 16;
+ } else {
+ FAIL();
+ }
+ }
+ ASSERT_EQ(31, mask);
+}
+
+TEST(mediametrics_tests, item_expansion) {
+ mediametrics::Item<1> item("I");
+ item.set("i32", (int32_t)1)
+ .set("i64", (int64_t)2)
+ .set("double", (double)3.125)
+ .set("string", "abcdefghijklmnopqrstuvwxyz")
+ .set("rate", std::pair<int64_t, int64_t>(11, 12));
+ ASSERT_TRUE(item.updateHeader());
+
+ MediaAnalyticsItem item2;
+ item2.readFromByteString(item.getBuffer(), item.getLength());
+ ASSERT_EQ((pid_t)-1, item2.getPid());
+ ASSERT_EQ((uid_t)-1, item2.getUid());
+ int mask = 0;
+ for (auto &prop : item2) {
+ const char *name = prop.getName();
+ if (!strcmp(name, "i32")) {
+ int32_t i32;
+ ASSERT_TRUE(prop.get(&i32));
+ ASSERT_EQ(1, i32);
+ mask |= 1;
+ } else if (!strcmp(name, "i64")) {
+ int64_t i64;
+ ASSERT_TRUE(prop.get(&i64));
+ ASSERT_EQ(2, i64);
+ mask |= 2;
+ } else if (!strcmp(name, "double")) {
+ double d;
+ ASSERT_TRUE(prop.get(&d));
+ ASSERT_EQ(3.125, d);
+ mask |= 4;
+ } else if (!strcmp(name, "string")) {
+ const char *s;
+ ASSERT_TRUE(prop.get(&s));
+ ASSERT_EQ(0, strcmp(s, "abcdefghijklmnopqrstuvwxyz"));
+ mask |= 8;
+ } else if (!strcmp(name, "rate")) {
+ std::pair<int64_t, int64_t> r;
+ ASSERT_TRUE(prop.get(&r));
+ ASSERT_EQ(11, r.first);
+ ASSERT_EQ(12, r.second);
+ mask |= 16;
+ } else {
+ FAIL();
+ }
+ }
+ ASSERT_EQ(31, mask);
+}
+
+TEST(mediametrics_tests, item_expansion2) {
+ mediametrics::Item<1> item("Bigly");
+ item.setPid(123)
+ .setUid(456);
+ constexpr size_t count = 10000;
+
+ for (size_t i = 0; i < count; ++i) {
+ // printf("recording %zu, %p, len:%zu of %zu remaining:%zu \n", i, item.getBuffer(), item.getLength(), item.getCapacity(), item.getRemaining());
+ item.set(std::to_string(i).c_str(), (int32_t)i);
+ }
+ ASSERT_TRUE(item.updateHeader());
+
+ MediaAnalyticsItem item2;
+ printf("begin buffer:%p length:%zu\n", item.getBuffer(), item.getLength());
+ fflush(stdout);
+ item2.readFromByteString(item.getBuffer(), item.getLength());
+
+ ASSERT_EQ((pid_t)123, item2.getPid());
+ ASSERT_EQ((uid_t)456, item2.getUid());
+ for (size_t i = 0; i < count; ++i) {
+ int32_t i32;
+ ASSERT_TRUE(item2.getInt32(std::to_string(i).c_str(), &i32));
+ ASSERT_EQ((int32_t)i, i32);
+ }
+}
+
+TEST(mediametrics_tests, time_machine_storage) {
+ auto item = std::make_shared<MediaAnalyticsItem>("Key");
+ (*item).set("i32", (int32_t)1)
+ .set("i64", (int64_t)2)
+ .set("double", (double)3.125)
+ .set("string", "abcdefghijklmnopqrstuvwxyz")
+ .set("rate", std::pair<int64_t, int64_t>(11, 12));
+
+ // Let's put the item in
+ android::mediametrics::TimeMachine timeMachine;
+ ASSERT_EQ(NO_ERROR, timeMachine.put(item, true));
+
+ // Can we read the values?
+ int32_t i32;
+ ASSERT_EQ(NO_ERROR, timeMachine.get("Key", "i32", &i32, -1));
+ ASSERT_EQ(1, i32);
+
+ int64_t i64;
+ ASSERT_EQ(NO_ERROR, timeMachine.get("Key", "i64", &i64, -1));
+ ASSERT_EQ(2, i64);
+
+ double d;
+ ASSERT_EQ(NO_ERROR, timeMachine.get("Key", "double", &d, -1));
+ ASSERT_EQ(3.125, d);
+
+ std::string s;
+ ASSERT_EQ(NO_ERROR, timeMachine.get("Key", "string", &s, -1));
+ ASSERT_EQ("abcdefghijklmnopqrstuvwxyz", s);
+
+ // Using fully qualified name?
+ i32 = 0;
+ ASSERT_EQ(NO_ERROR, timeMachine.get("Key.i32", &i32, -1));
+ ASSERT_EQ(1, i32);
+
+ i64 = 0;
+ ASSERT_EQ(NO_ERROR, timeMachine.get("Key.i64", &i64, -1));
+ ASSERT_EQ(2, i64);
+
+ d = 0.;
+ ASSERT_EQ(NO_ERROR, timeMachine.get("Key.double", &d, -1));
+ ASSERT_EQ(3.125, d);
+
+ s.clear();
+ ASSERT_EQ(NO_ERROR, timeMachine.get("Key.string", &s, -1));
+ ASSERT_EQ("abcdefghijklmnopqrstuvwxyz", s);
+}
+
+TEST(mediametrics_tests, time_machine_remote_key) {
+ auto item = std::make_shared<MediaAnalyticsItem>("Key1");
+ (*item).set("one", (int32_t)1)
+ .set("two", (int32_t)2);
+
+ android::mediametrics::TimeMachine timeMachine;
+ ASSERT_EQ(NO_ERROR, timeMachine.put(item, true));
+
+ auto item2 = std::make_shared<MediaAnalyticsItem>("Key2");
+ (*item2).set("three", (int32_t)3)
+ .set("[Key1]four", (int32_t)4) // affects Key1
+ .set("[Key1]five", (int32_t)5); // affects key1
+
+ ASSERT_EQ(NO_ERROR, timeMachine.put(item2, true));
+
+ auto item3 = std::make_shared<MediaAnalyticsItem>("Key2");
+ (*item3).set("six", (int32_t)6)
+ .set("[Key1]seven", (int32_t)7); // affects Key1
+
+ ASSERT_EQ(NO_ERROR, timeMachine.put(item3, false)); // remote keys not allowed.
+
+ // Can we read the values?
+ int32_t i32;
+ ASSERT_EQ(NO_ERROR, timeMachine.get("Key1.one", &i32, -1));
+ ASSERT_EQ(1, i32);
+
+ ASSERT_EQ(NO_ERROR, timeMachine.get("Key1.two", &i32, -1));
+ ASSERT_EQ(2, i32);
+
+ ASSERT_EQ(BAD_VALUE, timeMachine.get("Key1.three", &i32, -1));
+
+ ASSERT_EQ(NO_ERROR, timeMachine.get("Key2.three", &i32, -1));
+ ASSERT_EQ(3, i32);
+
+ ASSERT_EQ(NO_ERROR, timeMachine.get("Key1.four", &i32, -1));
+ ASSERT_EQ(4, i32);
+
+ ASSERT_EQ(BAD_VALUE, timeMachine.get("Key2.four", &i32, -1));
+
+ ASSERT_EQ(NO_ERROR, timeMachine.get("Key1.five", &i32, -1));
+ ASSERT_EQ(5, i32);
+
+ ASSERT_EQ(BAD_VALUE, timeMachine.get("Key2.five", &i32, -1));
+
+ ASSERT_EQ(NO_ERROR, timeMachine.get("Key2.six", &i32, -1));
+ ASSERT_EQ(6, i32);
+
+ ASSERT_EQ(BAD_VALUE, timeMachine.get("Key2.seven", &i32, -1));
+}
+
+TEST(mediametrics_tests, time_machine_gc) {
+ auto item = std::make_shared<MediaAnalyticsItem>("Key1");
+ (*item).set("one", (int32_t)1)
+ .set("two", (int32_t)2)
+ .setTimestamp(10);
+
+ android::mediametrics::TimeMachine timeMachine(1, 2); // keep at most 2 keys.
+
+ ASSERT_EQ((size_t)0, timeMachine.size());
+
+ ASSERT_EQ(NO_ERROR, timeMachine.put(item, true));
+
+ ASSERT_EQ((size_t)1, timeMachine.size());
+
+ auto item2 = std::make_shared<MediaAnalyticsItem>("Key2");
+ (*item2).set("three", (int32_t)3)
+ .set("[Key1]three", (int32_t)3)
+ .setTimestamp(11);
+
+ ASSERT_EQ(NO_ERROR, timeMachine.put(item2, true));
+ ASSERT_EQ((size_t)2, timeMachine.size());
+
+ //printf("Before\n%s\n\n", timeMachine.dump().c_str());
+
+ auto item3 = std::make_shared<MediaAnalyticsItem>("Key3");
+ (*item3).set("six", (int32_t)6)
+ .set("[Key1]four", (int32_t)4) // affects Key1
+ .set("[Key1]five", (int32_t)5) // affects key1
+ .setTimestamp(12);
+
+ ASSERT_EQ(NO_ERROR, timeMachine.put(item3, true));
+
+ ASSERT_EQ((size_t)2, timeMachine.size());
+
+ // Can we read the values?
+ int32_t i32;
+ ASSERT_EQ(BAD_VALUE, timeMachine.get("Key1.one", &i32, -1));
+ ASSERT_EQ(BAD_VALUE, timeMachine.get("Key1.two", &i32, -1));
+ ASSERT_EQ(BAD_VALUE, timeMachine.get("Key1.three", &i32, -1));
+ ASSERT_EQ(BAD_VALUE, timeMachine.get("Key1.four", &i32, -1));
+ ASSERT_EQ(BAD_VALUE, timeMachine.get("Key1.five", &i32, -1));
+
+ ASSERT_EQ(NO_ERROR, timeMachine.get("Key2.three", &i32, -1));
+ ASSERT_EQ(3, i32);
+
+ ASSERT_EQ(NO_ERROR, timeMachine.get("Key3.six", &i32, -1));
+ ASSERT_EQ(6, i32);
+
+ printf("After\n%s\n", timeMachine.dump().first.c_str());
+}
+
+TEST(mediametrics_tests, transaction_log_gc) {
+ auto item = std::make_shared<MediaAnalyticsItem>("Key1");
+ (*item).set("one", (int32_t)1)
+ .set("two", (int32_t)2)
+ .setTimestamp(10);
+
+ android::mediametrics::TransactionLog transactionLog(1, 2); // keep at most 2 items
+ ASSERT_EQ((size_t)0, transactionLog.size());
+
+ ASSERT_EQ(NO_ERROR, transactionLog.put(item));
+ ASSERT_EQ((size_t)1, transactionLog.size());
+
+ auto item2 = std::make_shared<MediaAnalyticsItem>("Key2");
+ (*item2).set("three", (int32_t)3)
+ .set("[Key1]three", (int32_t)3)
+ .setTimestamp(11);
+
+ ASSERT_EQ(NO_ERROR, transactionLog.put(item2));
+ ASSERT_EQ((size_t)2, transactionLog.size());
+
+ auto item3 = std::make_shared<MediaAnalyticsItem>("Key3");
+ (*item3).set("six", (int32_t)6)
+ .set("[Key1]four", (int32_t)4) // affects Key1
+ .set("[Key1]five", (int32_t)5) // affects key1
+ .setTimestamp(12);
+
+ ASSERT_EQ(NO_ERROR, transactionLog.put(item3));
+ ASSERT_EQ((size_t)2, transactionLog.size());
+}
+
+TEST(mediametrics_tests, audio_analytics_permission) {
+ auto item = std::make_shared<MediaAnalyticsItem>("audio.1");
+ (*item).set("one", (int32_t)1)
+ .set("two", (int32_t)2)
+ .setTimestamp(10);
+
+ auto item2 = std::make_shared<MediaAnalyticsItem>("audio.1");
+ (*item2).set("three", (int32_t)3)
+ .setTimestamp(11);
+
+ auto item3 = std::make_shared<MediaAnalyticsItem>("audio.2");
+ (*item3).set("four", (int32_t)4)
+ .setTimestamp(12);
+
+ android::mediametrics::AudioAnalytics audioAnalytics;
+
+ // untrusted entities cannot create a new key.
+ ASSERT_EQ(PERMISSION_DENIED, audioAnalytics.submit(item, false /* isTrusted */));
+ ASSERT_EQ(PERMISSION_DENIED, audioAnalytics.submit(item2, false /* isTrusted */));
+
+ // TODO: Verify contents of AudioAnalytics.
+ // Currently there is no getter API in AudioAnalytics besides dump.
+ ASSERT_EQ(4, audioAnalytics.dump(1000).second /* lines */);
+
+ ASSERT_EQ(NO_ERROR, audioAnalytics.submit(item, true /* isTrusted */));
+ // untrusted entities can add to an existing key
+ ASSERT_EQ(NO_ERROR, audioAnalytics.submit(item2, false /* isTrusted */));
+
+ // Check that we have some info in the dump.
+ ASSERT_LT(4, audioAnalytics.dump(1000).second /* lines */);
+}
+
+TEST(mediametrics_tests, audio_analytics_dump) {
+ auto item = std::make_shared<MediaAnalyticsItem>("audio.1");
+ (*item).set("one", (int32_t)1)
+ .set("two", (int32_t)2)
+ .setTimestamp(10);
+
+ auto item2 = std::make_shared<MediaAnalyticsItem>("audio.1");
+ (*item2).set("three", (int32_t)3)
+ .setTimestamp(11);
+
+ auto item3 = std::make_shared<MediaAnalyticsItem>("audio.2");
+ (*item3).set("four", (int32_t)4)
+ .setTimestamp(12);
+
+ android::mediametrics::AudioAnalytics audioAnalytics;
+
+ ASSERT_EQ(NO_ERROR, audioAnalytics.submit(item, true /* isTrusted */));
+ // untrusted entities can add to an existing key
+ ASSERT_EQ(NO_ERROR, audioAnalytics.submit(item2, false /* isTrusted */));
+ ASSERT_EQ(NO_ERROR, audioAnalytics.submit(item3, true /* isTrusted */));
+
+ // find out how many lines we have.
+ auto [string, lines] = audioAnalytics.dump(1000);
+ ASSERT_EQ(lines, (int32_t) countNewlines(string.c_str()));
+
+ printf("AudioAnalytics: %s", string.c_str());
+ // ensure that dump operates over those lines.
+ for (int32_t ll = 0; ll < lines; ++ll) {
+ auto [s, l] = audioAnalytics.dump(ll);
+ ASSERT_EQ(ll, l);
+ ASSERT_EQ(ll, (int32_t) countNewlines(s.c_str()));
+ }
+}