Snap for 7336869 from 0311d9c497b1ae80b1343ce804de62331630ee5d to sc-v2-release

Change-Id: I4e78fc70d453530b0d189845161ed2dfcf9cd389
diff --git a/audio_utils/Metadata.cpp b/audio_utils/Metadata.cpp
index f38c8bf..d580f4c 100644
--- a/audio_utils/Metadata.cpp
+++ b/audio_utils/Metadata.cpp
@@ -185,3 +185,7 @@
     memcpy(*byteString, bs.c_str(), bs.size());
     return bs.size();
 }
+
+size_t audio_metadata_byte_string_len(const uint8_t *byteString) {
+    return dataByteStringLen(byteString);
+}
diff --git a/audio_utils/include/audio_utils/Metadata.h b/audio_utils/include/audio_utils/Metadata.h
index f1990b2..2f1edb3 100644
--- a/audio_utils/include/audio_utils/Metadata.h
+++ b/audio_utils/include/audio_utils/Metadata.h
@@ -905,6 +905,43 @@
     return bs; // copy elision
 }
 
+/**
+ * \brief Returns the length of the byte string buffer from the raw pointer.
+ *
+ * The raw pointer comes from the Data object's ByteString.data()
+ * or from the C API byte_string_from_audio_metadata().
+ * This is a helper method for C implementations which may pass the raw
+ * byte string buffer pointer (which does not directly contain the length).
+ * C++ methods should always use the ByteString object.
+ *
+ * \param byteString       byte string buffer raw pointer.
+ * \return size in bytes of metadata in the buffer or 0 if something went wrong.
+ */
+
+inline size_t dataByteStringLen(const uint8_t *ptr) {
+    index_size_t elements;
+    const uint8_t * const origPtr = ptr;
+    memcpy(&elements, ptr, sizeof(elements));
+    ptr += sizeof(elements);
+    for (index_size_t i = 0; i < elements; ++i) {
+        // get key (string)
+        index_size_t keyLen;
+        memcpy(&keyLen, ptr, sizeof(keyLen));
+        ptr += keyLen + sizeof(keyLen);
+        // get type
+        type_size_t type;
+        memcpy(&type, ptr, sizeof(type));
+        ptr += sizeof(type_size_t);
+        // Note: could check type validity.
+        // payload size
+        datum_size_t datumSize;
+        memcpy(&datumSize, ptr, sizeof(datumSize));
+        ptr += datumSize + sizeof(datumSize);
+    }
+    const ptrdiff_t size = ptr - origPtr;
+    return size < 0 ? 0 : size;
+}
+
 } // namespace android::audio_utils::metadata
 
 #endif // __cplusplus
@@ -1169,6 +1206,16 @@
  */
 ssize_t byte_string_from_audio_metadata(audio_metadata_t *metadata, uint8_t **byteString);
 
+/**
+ * \brief Return the size in bytes of the metadata byte string
+ *
+ * Note: strlen() cannot be used as there are embedded 0's in the byte string.
+ *
+ * \param byteString       a valid byte string buffer from byte_string_from_audio_metadata().
+ * \return size in bytes of metadata in the buffer or 0 if something went wrong.
+ */
+size_t audio_metadata_byte_string_len(const uint8_t *byteString);
+
 /** \cond */
 __END_DECLS
 /** \endcond */
diff --git a/audio_utils/tests/metadata_tests.cpp b/audio_utils/tests/metadata_tests.cpp
index 6ac6726..3856dc0 100644
--- a/audio_utils/tests/metadata_tests.cpp
+++ b/audio_utils/tests/metadata_tests.cpp
@@ -454,13 +454,19 @@
     ASSERT_EQ(-EINVAL, audio_metadata_get(metadata, "i32", nullI32Val));
 
     uint8_t *bs = nullptr;
-    size_t length = byte_string_from_audio_metadata(metadata, &bs);
+    ssize_t length = byte_string_from_audio_metadata(metadata, &bs);
+    ASSERT_GT(length, 0); // if gt 0, the bs has been updated to a new value.
+    ASSERT_EQ((size_t)length, audio_metadata_byte_string_len(bs));
+    ASSERT_EQ((size_t)length, dataByteStringLen(bs));
     ASSERT_EQ(byteStringFromData(d).size(), ByteString(bs, length).size());
     audio_metadata_t *metadataFromBs = audio_metadata_from_byte_string(bs, length);
     free(bs);
     bs = nullptr;
     length = byte_string_from_audio_metadata(metadataFromBs, &bs);
+    ASSERT_GT(length, 0); // if gt 0, the bs has been updated to a new value.
     ASSERT_EQ(byteStringFromData(d), ByteString(bs, length));
+    ASSERT_EQ((size_t)length, audio_metadata_byte_string_len(bs));
+    ASSERT_EQ((size_t)length, dataByteStringLen(bs));
     free(bs);
     bs = nullptr;
     audio_metadata_destroy(metadataFromBs);
@@ -481,3 +487,25 @@
 
     audio_metadata_destroy(metadata);
 };
+
+TEST(metadata_tests, empty_data_c) {
+    std::unique_ptr<audio_metadata_t, decltype(&audio_metadata_destroy)>
+        metadata{audio_metadata_create(), audio_metadata_destroy};  // empty metadata container.
+    uint8_t *bs = nullptr;
+    ssize_t length = byte_string_from_audio_metadata(metadata.get(), &bs);
+    ASSERT_GT(length, 0); // if gt 0, the bs has been updated to a new value.
+    std::unique_ptr<uint8_t, decltype(&free)> bs_scoped_deleter{bs, free};
+    ASSERT_EQ((size_t)length, audio_metadata_byte_string_len(bs));
+    ASSERT_EQ((size_t)length, dataByteStringLen(bs));
+
+    Data d;  // empty metadata container.
+    ASSERT_EQ(byteStringFromData(d).size(), ByteString(bs, length).size());
+    std::unique_ptr<audio_metadata_t, decltype(&audio_metadata_destroy)>
+            metadataFromBs{audio_metadata_from_byte_string(bs, length), audio_metadata_destroy};
+    length = byte_string_from_audio_metadata(metadataFromBs.get(), &bs);
+    ASSERT_GT(length, 0); // if gt 0, the bs has been updated to a new value.
+    bs_scoped_deleter.reset(bs);
+    ASSERT_EQ(byteStringFromData(d), ByteString(bs, length));
+    ASSERT_EQ((size_t)length, audio_metadata_byte_string_len(bs));
+    ASSERT_EQ((size_t)length, dataByteStringLen(bs));
+};