Merge changes from topic "AMsgItem" into pi-dev am: ec2c0359ec
am: aa53a3e07b

Change-Id: I143b151134ffa4870090f0060e596adf07902e96
diff --git a/media/libstagefright/foundation/AMessage.cpp b/media/libstagefright/foundation/AMessage.cpp
index 3b84018..738f066 100644
--- a/media/libstagefright/foundation/AMessage.cpp
+++ b/media/libstagefright/foundation/AMessage.cpp
@@ -944,6 +944,40 @@
     return mItems[index].mName;
 }
 
+AMessage::ItemData AMessage::getEntryAt(size_t index) const {
+    ItemData it;
+    if (index < mNumItems) {
+        switch (mItems[index].mType) {
+            case kTypeInt32:    it.set(mItems[index].u.int32Value); break;
+            case kTypeInt64:    it.set(mItems[index].u.int64Value); break;
+            case kTypeSize:     it.set(mItems[index].u.sizeValue); break;
+            case kTypeFloat:    it.set(mItems[index].u.floatValue); break;
+            case kTypeDouble:   it.set(mItems[index].u.doubleValue); break;
+            case kTypePointer:  it.set(mItems[index].u.ptrValue); break;
+            case kTypeRect:     it.set(mItems[index].u.rectValue); break;
+            case kTypeString:   it.set(*mItems[index].u.stringValue); break;
+            case kTypeObject: {
+                sp<RefBase> obj = mItems[index].u.refValue;
+                it.set(obj);
+                break;
+            }
+            case kTypeMessage: {
+                sp<AMessage> msg = static_cast<AMessage *>(mItems[index].u.refValue);
+                it.set(msg);
+                break;
+            }
+            case kTypeBuffer: {
+                sp<ABuffer> buf = static_cast<ABuffer *>(mItems[index].u.refValue);
+                it.set(buf);
+                break;
+            }
+            default:
+                break;
+        }
+    }
+    return it;
+}
+
 status_t AMessage::setEntryNameAt(size_t index, const char *name) {
     if (index >= mNumItems) {
         return BAD_INDEX;
@@ -964,6 +998,60 @@
     return OK;
 }
 
+status_t AMessage::setEntryAt(size_t index, const ItemData &item) {
+    AString stringValue;
+    sp<RefBase> refValue;
+    sp<AMessage> msgValue;
+    sp<ABuffer> bufValue;
+
+    if (index >= mNumItems) {
+        return BAD_INDEX;
+    }
+    if (!item.used()) {
+        return BAD_VALUE;
+    }
+    Item *dst = &mItems[index];
+    freeItemValue(dst);
+
+    // some values can be directly set with the getter. others need items to be allocated
+    if (item.find(&dst->u.int32Value)) {
+        dst->mType = kTypeInt32;
+    } else if (item.find(&dst->u.int64Value)) {
+        dst->mType = kTypeInt64;
+    } else if (item.find(&dst->u.sizeValue)) {
+        dst->mType = kTypeSize;
+    } else if (item.find(&dst->u.floatValue)) {
+        dst->mType = kTypeFloat;
+    } else if (item.find(&dst->u.doubleValue)) {
+        dst->mType = kTypeDouble;
+    } else if (item.find(&dst->u.ptrValue)) {
+        dst->mType = kTypePointer;
+    } else if (item.find(&dst->u.rectValue)) {
+        dst->mType = kTypeRect;
+    } else if (item.find(&stringValue)) {
+        dst->u.stringValue = new AString(stringValue);
+        dst->mType = kTypeString;
+    } else if (item.find(&refValue)) {
+        if (refValue != NULL) { refValue->incStrong(this); }
+        dst->u.refValue = refValue.get();
+        dst->mType = kTypeObject;
+    } else if (item.find(&msgValue)) {
+        if (msgValue != NULL) { msgValue->incStrong(this); }
+        dst->u.refValue = msgValue.get();
+        dst->mType = kTypeMessage;
+    } else if (item.find(&bufValue)) {
+        if (bufValue != NULL) { bufValue->incStrong(this); }
+        dst->u.refValue = bufValue.get();
+        dst->mType = kTypeBuffer;
+    } else {
+        // unsupported item - we should not be here.
+        dst->mType = kTypeInt32;
+        dst->u.int32Value = 0xDEADDEAD;
+        return BAD_TYPE;
+    }
+    return OK;
+}
+
 status_t AMessage::removeEntryAt(size_t index) {
     if (index >= mNumItems) {
         return BAD_INDEX;
@@ -983,6 +1071,34 @@
     return OK;
 }
 
+void AMessage::setItem(const char *name, const ItemData &item) {
+    if (item.used()) {
+        Item *it = allocateItem(name);
+        if (it != nullptr) {
+            setEntryAt(it - mItems, item);
+        }
+    }
+}
+
+AMessage::ItemData AMessage::findItem(const char *name) const {
+    return getEntryAt(findEntryByName(name));
+}
+
+void AMessage::extend(const sp<AMessage> &other) {
+    // ignore null messages
+    if (other == nullptr) {
+        return;
+    }
+
+    for (size_t ix = 0; ix < other->mNumItems; ++ix) {
+        Item *it = allocateItem(other->mItems[ix].mName);
+        if (it != nullptr) {
+            ItemData data = other->getEntryAt(ix);
+            setEntryAt(it - mItems, data);
+        }
+    }
+}
+
 size_t AMessage::findEntryByName(const char *name) const {
     return name == nullptr ? countEntries() : findItemIndex(name, strlen(name));
 }
diff --git a/media/libstagefright/foundation/include/media/stagefright/foundation/AData.h b/media/libstagefright/foundation/include/media/stagefright/foundation/AData.h
index 49aa0dc..5acc6d6 100644
--- a/media/libstagefright/foundation/include/media/stagefright/foundation/AData.h
+++ b/media/libstagefright/foundation/include/media/stagefright/foundation/AData.h
@@ -25,6 +25,9 @@
 #include <media/stagefright/foundation/TypeTraits.h>
 #include <media/stagefright/foundation/Flagged.h>
 
+#undef HIDE
+#define HIDE __attribute__((visibility("hidden")))
+
 namespace android {
 
 /**
@@ -78,7 +81,7 @@
  * This class is needed as member function specialization is not allowed for a
  * templated class.
  */
-struct _AUnion_impl {
+struct HIDE _AUnion_impl {
     /**
      * Calls placement constuctor for type T with arbitrary arguments for a storage at an address.
      * Storage MUST be large enough to contain T.
@@ -113,13 +116,13 @@
 
 /** Constructor specialization for void type */
 template<>
-inline void _AUnion_impl::emplace<void>(size_t totalSize, void *addr) {
+HIDE inline void _AUnion_impl::emplace<void>(size_t totalSize, void *addr) {
     memset(addr, 0, totalSize);
 }
 
 /** Destructor specialization for void type */
 template<>
-inline void _AUnion_impl::del<void>(void *) {
+HIDE inline void _AUnion_impl::del<void>(void *) {
 }
 
 /// \endcond
@@ -221,7 +224,7 @@
 template<
         typename T,
         bool=std::is_copy_assignable<T>::value>
-struct _AData_copier {
+struct HIDE _AData_copier {
     static_assert(std::is_copy_assignable<T>::value, "T must be copy assignable here");
 
     /**
@@ -294,7 +297,7 @@
  *
  */
 template<typename T>
-struct _AData_copier<T, false> {
+struct HIDE _AData_copier<T, false> {
     static_assert(!std::is_copy_assignable<T>::value, "T must not be copy assignable here");
     static_assert(std::is_copy_constructible<T>::value, "T must be copy constructible here");
 
@@ -318,7 +321,7 @@
 template<
         typename T,
         bool=std::is_move_assignable<T>::value>
-struct _AData_mover {
+struct HIDE _AData_mover {
     static_assert(std::is_move_assignable<T>::value, "T must be move assignable here");
 
     /**
@@ -389,7 +392,7 @@
  *
  */
 template<typename T>
-struct _AData_mover<T, false> {
+struct HIDE _AData_mover<T, false> {
     static_assert(!std::is_move_assignable<T>::value, "T must not be move assignable here");
     static_assert(std::is_move_constructible<T>::value, "T must be move constructible here");
 
@@ -407,13 +410,13 @@
  * \param Ts types to consider for the member
  */
 template<typename Flagger, typename U, typename ...Ts>
-struct _AData_deleter;
+struct HIDE _AData_deleter;
 
 /**
  * Template specialization when there are still types to consider (T and rest)
  */
 template<typename Flagger, typename U, typename T, typename ...Ts>
-struct _AData_deleter<Flagger, U, T, Ts...> {
+struct HIDE _AData_deleter<Flagger, U, T, Ts...> {
     static bool del(typename Flagger::type flags, U &data) {
         if (Flagger::canDeleteAs(flags, Flagger::flagFor((T*)0))) {
             data.template del<T>();
@@ -427,7 +430,7 @@
  * Template specialization when there are no more types to consider.
  */
 template<typename Flagger, typename U>
-struct _AData_deleter<Flagger, U> {
+struct HIDE _AData_deleter<Flagger, U> {
     inline static bool del(typename Flagger::type, U &) {
         return false;
     }
diff --git a/media/libstagefright/foundation/include/media/stagefright/foundation/AMessage.h b/media/libstagefright/foundation/include/media/stagefright/foundation/AMessage.h
index d90a0de..742651e 100644
--- a/media/libstagefright/foundation/include/media/stagefright/foundation/AMessage.h
+++ b/media/libstagefright/foundation/include/media/stagefright/foundation/AMessage.h
@@ -19,6 +19,7 @@
 #define A_MESSAGE_H_
 
 #include <media/stagefright/foundation/ABase.h>
+#include <media/stagefright/foundation/AData.h>
 #include <media/stagefright/foundation/ALooper.h>
 #include <utils/KeyedVector.h>
 #include <utils/RefBase.h>
@@ -155,6 +156,9 @@
     // their refcount incremented.
     sp<AMessage> dup() const;
 
+    // Adds all items from other into this.
+    void extend(const sp<AMessage> &other);
+
     // Performs a shallow or deep comparison of |this| and |other| and returns
     // an AMessage with the differences.
     // Warning: RefBase items, i.e. "objects" are _not_ copied but only have
@@ -180,10 +184,39 @@
         kTypeBuffer,
     };
 
+    struct Rect {
+        int32_t mLeft, mTop, mRight, mBottom;
+    };
+
     size_t countEntries() const;
     const char *getEntryNameAt(size_t index, Type *type) const;
 
     /**
+     * Retrieves the item at a specific index.
+     */
+    typedef AData<
+        int32_t, int64_t, size_t, float, double, Rect, AString,
+        void *, sp<AMessage>, sp<ABuffer>, sp<RefBase>>::Basic ItemData;
+
+    /**
+     * Finds an item by name. This can be used if the type is unknown.
+     *
+     * \param name name of the item
+     * Returns an empty item if no item is present with that name.
+     */
+    ItemData findItem(const char *name) const;
+
+    /**
+     * Sets an item of arbitrary type. Does nothing if the item value is empty.
+     *
+     * \param name name of the item
+     * \param item value of the item
+     */
+    void setItem(const char *name, const ItemData &item);
+
+    ItemData getEntryAt(size_t index) const;
+
+    /**
      * Finds an entry by name and returns its index.
      *
      * \retval countEntries() if the entry is not found.
@@ -204,6 +237,19 @@
     status_t setEntryNameAt(size_t index, const char *name);
 
     /**
+     * Sets the item of an entry based on index.
+     *
+     * \param index index of the entry
+     * \param item new item of the entry
+     *
+     * \retval OK the item was set successfully
+     * \retval BAD_INDEX invalid index
+     * \retval BAD_VALUE item is invalid (null)
+     * \retval BAD_TYPE type is unsupported (should not happen)
+     */
+    status_t setEntryAt(size_t index, const ItemData &item);
+
+    /**
      * Removes an entry based on index.
      *
      * \param index index of the entry
@@ -227,10 +273,6 @@
     wp<AHandler> mHandler;
     wp<ALooper> mLooper;
 
-    struct Rect {
-        int32_t mLeft, mTop, mRight, mBottom;
-    };
-
     struct Item {
         union {
             int32_t int32Value;
diff --git a/media/libstagefright/foundation/include/media/stagefright/foundation/TypeTraits.h b/media/libstagefright/foundation/include/media/stagefright/foundation/TypeTraits.h
index 1250e9b..2041b22 100644
--- a/media/libstagefright/foundation/include/media/stagefright/foundation/TypeTraits.h
+++ b/media/libstagefright/foundation/include/media/stagefright/foundation/TypeTraits.h
@@ -19,6 +19,9 @@
 
 #include <type_traits>
 
+#undef HIDE
+#define HIDE __attribute__((visibility("hidden")))
+
 namespace android {
 
 /**
@@ -31,7 +34,7 @@
  * Type support utility class to check if a type is an integral type or an enum.
  */
 template<typename T>
-struct is_integral_or_enum
+struct HIDE is_integral_or_enum
     : std::integral_constant<bool, std::is_integral<T>::value || std::is_enum<T>::value> { };
 
 /**
@@ -46,7 +49,7 @@
         typename U=typename std::enable_if<is_integral_or_enum<T>::value>::type,
         bool=std::is_enum<T>::value,
         bool=std::is_integral<T>::value>
-struct underlying_integral_type {
+struct HIDE underlying_integral_type {
     static_assert(!std::is_enum<T>::value, "T should not be enum here");
     static_assert(!std::is_integral<T>::value, "T should not be integral here");
     typedef U type;
@@ -54,7 +57,7 @@
 
 /** Specialization for enums. */
 template<typename T, typename U>
-struct underlying_integral_type<T, U, true, false> {
+struct HIDE underlying_integral_type<T, U, true, false> {
     static_assert(std::is_enum<T>::value, "T should be enum here");
     static_assert(!std::is_integral<T>::value, "T should not be integral here");
     typedef typename std::underlying_type<T>::type type;
@@ -62,7 +65,7 @@
 
 /** Specialization for non-enum std-integral types. */
 template<typename T, typename U>
-struct underlying_integral_type<T, U, false, true> {
+struct HIDE underlying_integral_type<T, U, false, true> {
     static_assert(!std::is_enum<T>::value, "T should not be enum here");
     static_assert(std::is_integral<T>::value, "T should be integral here");
     typedef T type;
@@ -72,7 +75,7 @@
  * Type support utility class to check if the underlying integral type is signed.
  */
 template<typename T>
-struct is_signed_integral
+struct HIDE is_signed_integral
     : std::integral_constant<bool, std::is_signed<
             typename underlying_integral_type<T, unsigned>::type>::value> { };
 
@@ -80,7 +83,7 @@
  * Type support utility class to check if the underlying integral type is unsigned.
  */
 template<typename T>
-struct is_unsigned_integral
+struct HIDE is_unsigned_integral
     : std::integral_constant<bool, std::is_unsigned<
             typename underlying_integral_type<T, signed>::type>::value> {
 };
@@ -92,26 +95,26 @@
  * member constant |value| equal to true. Otherwise value is false.
  */
 template<typename T, typename ...Us>
-struct is_one_of;
+struct HIDE is_one_of;
 
 /// \if 0
 /**
  * Template specialization when first type matches the searched type.
  */
 template<typename T, typename ...Us>
-struct is_one_of<T, T, Us...> : std::true_type {};
+struct HIDE is_one_of<T, T, Us...> : std::true_type {};
 
 /**
  * Template specialization when first type does not match the searched type.
  */
 template<typename T, typename U, typename ...Us>
-struct is_one_of<T, U, Us...> : is_one_of<T, Us...> {};
+struct HIDE is_one_of<T, U, Us...> : is_one_of<T, Us...> {};
 
 /**
  * Template specialization when there are no types to search.
  */
 template<typename T>
-struct is_one_of<T> : std::false_type {};
+struct HIDE is_one_of<T> : std::false_type {};
 /// \endif
 
 /**
@@ -121,44 +124,44 @@
  * Otherwise value is false.
  */
 template<typename ...Us>
-struct are_unique;
+struct HIDE are_unique;
 
 /// \if 0
 /**
  * Template specialization when there are no types.
  */
 template<>
-struct are_unique<> : std::true_type {};
+struct HIDE are_unique<> : std::true_type {};
 
 /**
  * Template specialization when there is at least one type to check.
  */
 template<typename T, typename ...Us>
-struct are_unique<T, Us...>
+struct HIDE are_unique<T, Us...>
     : std::integral_constant<bool, are_unique<Us...>::value && !is_one_of<T, Us...>::value> {};
 /// \endif
 
 /// \if 0
 template<size_t Base, typename T, typename ...Us>
-struct _find_first_impl;
+struct HIDE _find_first_impl;
 
 /**
  * Template specialization when there are no types to search.
  */
 template<size_t Base, typename T>
-struct _find_first_impl<Base, T> : std::integral_constant<size_t, 0> {};
+struct HIDE _find_first_impl<Base, T> : std::integral_constant<size_t, 0> {};
 
 /**
  * Template specialization when T is the first type in Us.
  */
 template<size_t Base, typename T, typename ...Us>
-struct _find_first_impl<Base, T, T, Us...> : std::integral_constant<size_t, Base> {};
+struct HIDE _find_first_impl<Base, T, T, Us...> : std::integral_constant<size_t, Base> {};
 
 /**
  * Template specialization when T is not the first type in Us.
  */
 template<size_t Base, typename T, typename U, typename ...Us>
-struct _find_first_impl<Base, T, U, Us...>
+struct HIDE _find_first_impl<Base, T, U, Us...>
     : std::integral_constant<size_t, _find_first_impl<Base + 1, T, Us...>::value> {};
 
 /// \endif
@@ -169,7 +172,7 @@
  * If T occurs in Us, index is the 1-based left-most index of T in Us. Otherwise, index is 0.
  */
 template<typename T, typename ...Us>
-struct find_first {
+struct HIDE find_first {
     static constexpr size_t index = _find_first_impl<1, T, Us...>::value;
 };
 
@@ -180,13 +183,13 @@
  * Adds a base index.
  */
 template<size_t Base, typename T, typename ...Us>
-struct _find_first_convertible_to_helper;
+struct HIDE _find_first_convertible_to_helper;
 
 /**
  * Template specialization for when there are more types to consider
  */
 template<size_t Base, typename T, typename U, typename ...Us>
-struct _find_first_convertible_to_helper<Base, T, U, Us...> {
+struct HIDE _find_first_convertible_to_helper<Base, T, U, Us...> {
     static constexpr size_t index =
         std::is_convertible<T, U>::value ? Base :
                 _find_first_convertible_to_helper<Base + 1, T, Us...>::index;
@@ -199,7 +202,7 @@
  * Template specialization for when there are no more types to consider
  */
 template<size_t Base, typename T>
-struct _find_first_convertible_to_helper<Base, T> {
+struct HIDE _find_first_convertible_to_helper<Base, T> {
     static constexpr size_t index = 0;
     typedef void type;
 };
@@ -216,7 +219,7 @@
  * \param Us types into which the conversion is considered
  */
 template<typename T, typename ...Us>
-struct find_first_convertible_to : public _find_first_convertible_to_helper<1, T, Us...> { };
+struct HIDE find_first_convertible_to : public _find_first_convertible_to_helper<1, T, Us...> { };
 
 }  // namespace android