MediaMetrics: Update Item serialization code

Add for bounds checking errors
Update key checks to omit length, use C primitive types

Test: atest mediametrics_tests, adb shell dumpsys media.metrics
Change-Id: I1e6d5bd7a9611f6d59e15a1dbebc646405e5a018
diff --git a/services/mediaanalytics/tests/mediametrics_tests.cpp b/services/mediaanalytics/tests/mediametrics_tests.cpp
index 7a6f5a4..09ca114 100644
--- a/services/mediaanalytics/tests/mediametrics_tests.cpp
+++ b/services/mediaanalytics/tests/mediametrics_tests.cpp
@@ -160,6 +160,27 @@
   }
 }
 
+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");
 
@@ -175,3 +196,88 @@
   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);
+}