Codec2: fix up C2Param

Add an internal _C2ParamInspector to be able to inspect fields of
C2ParamField and C2FieldId, and to parse C2Param out of blob.

Fix C2Param::updateFrom to allow copying a param that is smaller
than the current param (e.g. for flex params) as that is always
safe.

Allow enum helper macros to be 'preinited' by C2Config.h to allow
any include order.

Bug: 64121714
Change-Id: I8be8fa974194bfe397f90a334e786f94fe20862c
diff --git a/media/libstagefright/codec2/include/C2Param.h b/media/libstagefright/codec2/include/C2Param.h
index 2a8c1b2..9785c87 100644
--- a/media/libstagefright/codec2/include/C2Param.h
+++ b/media/libstagefright/codec2/include/C2Param.h
@@ -397,8 +397,8 @@
 
     /// safe(r) type cast from pointer and size
     inline static C2Param* From(void *addr, size_t len) {
-        // _mSize must fit into size
-        if (len < sizeof(_mSize) + offsetof(C2Param, _mSize)) {
+        // _mSize must fit into size, but really C2Param must also to be a valid param
+        if (len < sizeof(C2Param)) {
             return nullptr;
         }
         // _mSize must match length
@@ -446,7 +446,7 @@
     // if other is the same kind of (valid) param as this, copy it into this and return true.
     // otherwise, do not copy anything, and return false.
     inline bool updateFrom(const C2Param &other) {
-        if (other._mSize == _mSize && other._mIndex == _mIndex && _mSize > 0) {
+        if (other._mSize <= _mSize && other._mIndex == _mIndex && _mSize > 0) {
             memcpy(this, &other, _mSize);
             return true;
         }
@@ -620,6 +620,8 @@
 #endif
 
 private:
+    friend struct _C2ParamInspector;
+
     uint32_t _mOffset; // offset of field
     uint32_t _mSize;   // size of field
 };
@@ -720,6 +722,8 @@
     DEFINE_OTHER_COMPARISON_OPERATORS(C2ParamField)
 
 private:
+    friend struct _C2ParamInspector;
+
     C2Param::Index _mIndex; ///< parameter index
     _C2FieldId _mFieldId;   ///< field identifier
 };
diff --git a/media/libstagefright/codec2/vndk/C2ParamInternal.h b/media/libstagefright/codec2/vndk/C2ParamInternal.h
new file mode 100644
index 0000000..0f3812a
--- /dev/null
+++ b/media/libstagefright/codec2/vndk/C2ParamInternal.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+#ifndef ANDROID_STAGEFRIGHT_C2PARAM_INTERNAL_H_
+#define ANDROID_STAGEFRIGHT_C2PARAM_INTERNAL_H_
+
+#include <C2Param.h>
+
+namespace android {
+
+struct C2_HIDE _C2ParamInspector {
+   inline static uint32_t getIndex(const C2ParamField &pf) {
+        return pf._mIndex;
+    }
+
+    inline static uint32_t getOffset(const C2ParamField &pf) {
+        return pf._mFieldId._mOffset;
+    }
+
+    inline static uint32_t getSize(const C2ParamField &pf) {
+        return pf._mFieldId._mSize;
+    }
+
+    inline static
+    C2ParamField CreateParamField(C2Param::Index index, uint32_t offset, uint32_t size) {
+        return C2ParamField(index, offset, size);
+    }
+};
+
+}
+
+#endif // ANDROID_STAGEFRIGHT_C2PARAM_INTERNAL_H_
+
diff --git a/media/libstagefright/codec2/vndk/include/util/C2ParamUtils.h b/media/libstagefright/codec2/vndk/include/util/C2ParamUtils.h
index 81c5495..3168248 100644
--- a/media/libstagefright/codec2/vndk/include/util/C2ParamUtils.h
+++ b/media/libstagefright/codec2/vndk/include/util/C2ParamUtils.h
@@ -59,6 +59,7 @@
 
 /// \endcond
 
+#undef DEFINE_C2_ENUM_VALUE_AUTO_HELPER
 #define DEFINE_C2_ENUM_VALUE_AUTO_HELPER(name, type, prefix, ...) \
 template<> C2FieldDescriptor::named_values_type C2FieldDescriptor::namedValuesFor(const name &r __unused) { \
     return C2ParamUtils::sanitizeEnumValues( \
@@ -67,6 +68,7 @@
             prefix); \
 }
 
+#undef DEFINE_C2_ENUM_VALUE_CUSTOM_HELPER
 #define DEFINE_C2_ENUM_VALUE_CUSTOM_HELPER(name, type, names, ...) \
 template<> C2FieldDescriptor::named_values_type C2FieldDescriptor::namedValuesFor(const name &r __unused) { \
     return C2ParamUtils::customEnumValues( \
@@ -260,6 +262,21 @@
         }
         return namedValues;
     }
+
+    /// safe(r) parsing from parameter blob
+    static
+    C2Param *ParseFirst(const uint8_t *blob, size_t size) {
+        // _mSize must fit into size, but really C2Param must also to be a valid param
+        if (size < sizeof(C2Param)) {
+            return nullptr;
+        }
+        // _mSize must match length
+        C2Param *param = (C2Param*)blob;
+        if (param->size() > size) {
+            return nullptr;
+        }
+        return param;
+    }
 };
 
 /* ---------------------------- UTILITIES FOR PARAMETER REFLECTION ---------------------------- */