Move Codec2-related code from hardware/google/av

Test: None
Bug: 112362730
Change-Id: Ie2f8ff431d65c40333f267ab9877d47089adeea4
diff --git a/media/codec2/vndk/include/C2AllocatorGralloc.h b/media/codec2/vndk/include/C2AllocatorGralloc.h
new file mode 100644
index 0000000..05d989e
--- /dev/null
+++ b/media/codec2/vndk/include/C2AllocatorGralloc.h
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2016 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 STAGEFRIGHT_CODEC2_ALLOCATOR_GRALLOC_H_
+#define STAGEFRIGHT_CODEC2_ALLOCATOR_GRALLOC_H_
+
+#include <functional>
+
+#include <C2Buffer.h>
+
+namespace android {
+
+/**
+ * Unwrap the native handle from a Codec2 handle allocated by C2AllocatorGralloc.
+ *
+ * @param handle a handle allocated by C2AllocatorGralloc. This includes handles returned for a
+ * graphic block allocation handle returned.
+ *
+ * @return a new NON-OWNING native handle that must be deleted using native_handle_delete.
+ */
+native_handle_t *UnwrapNativeCodec2GrallocHandle(const C2Handle *const handle);
+
+/**
+ * Wrap the gralloc handle and metadata into Codec2 handle recognized by
+ * C2AllocatorGralloc.
+ *
+ * @return a new NON-OWNING C2Handle that must be deleted using native_handle_delete.
+ */
+C2Handle *WrapNativeCodec2GrallocHandle(
+        const native_handle_t *const handle,
+        uint32_t width, uint32_t height, uint32_t format, uint64_t usage, uint32_t stride,
+        uint32_t generation = 0, uint64_t igbp_id = 0, uint32_t igbp_slot = 0);
+
+/**
+ * \todo Get this from the buffer
+ */
+void _UnwrapNativeCodec2GrallocMetadata(
+        const C2Handle *const handle,
+        uint32_t *width, uint32_t *height, uint32_t *format, uint64_t *usage, uint32_t *stride,
+        uint32_t *generation, uint64_t *igbp_id, uint32_t *igbp_slot);
+
+class C2AllocatorGralloc : public C2Allocator {
+public:
+    virtual id_t getId() const override;
+
+    virtual C2String getName() const override;
+
+    virtual std::shared_ptr<const Traits> getTraits() const override;
+
+    virtual c2_status_t newGraphicAllocation(
+            uint32_t width, uint32_t height, uint32_t format, C2MemoryUsage usage,
+            std::shared_ptr<C2GraphicAllocation> *allocation) override;
+
+    virtual c2_status_t priorGraphicAllocation(
+            const C2Handle *handle,
+            std::shared_ptr<C2GraphicAllocation> *allocation) override;
+
+    C2AllocatorGralloc(id_t id, bool bufferQueue = false);
+
+    c2_status_t status() const;
+
+    virtual ~C2AllocatorGralloc() override;
+
+    static bool isValid(const C2Handle* const o);
+
+private:
+    class Impl;
+    Impl *mImpl;
+};
+
+} // namespace android
+
+#endif // STAGEFRIGHT_CODEC2_ALLOCATOR_GRALLOC_H_
diff --git a/media/codec2/vndk/include/C2AllocatorIon.h b/media/codec2/vndk/include/C2AllocatorIon.h
new file mode 100644
index 0000000..1b2051f
--- /dev/null
+++ b/media/codec2/vndk/include/C2AllocatorIon.h
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2016 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 STAGEFRIGHT_CODEC2_ALLOCATOR_ION_H_
+#define STAGEFRIGHT_CODEC2_ALLOCATOR_ION_H_
+
+#include <functional>
+#include <list>
+#include <mutex>
+#include <tuple>
+#include <unordered_map>
+
+#include <C2Buffer.h>
+
+namespace android {
+
+class C2AllocatorIon : public C2Allocator {
+public:
+    // Usage mapper function used by the allocator
+    //   (usage, capacity) => (align, heapMask, flags)
+    //
+    // capacity is aligned to the default block-size (defaults to page size) to reduce caching
+    // overhead
+    typedef std::function<c2_status_t(C2MemoryUsage, size_t,
+                      /* => */ size_t*, unsigned*, unsigned*)> UsageMapperFn;
+
+    virtual id_t getId() const override;
+
+    virtual C2String getName() const override;
+
+    virtual std::shared_ptr<const Traits> getTraits() const override;
+
+    virtual c2_status_t newLinearAllocation(
+            uint32_t capacity, C2MemoryUsage usage,
+            std::shared_ptr<C2LinearAllocation> *allocation) override;
+
+    virtual c2_status_t priorLinearAllocation(
+            const C2Handle *handle,
+            std::shared_ptr<C2LinearAllocation> *allocation) override;
+
+    C2AllocatorIon(id_t id);
+
+    virtual c2_status_t status() const { return mInit; }
+
+    virtual ~C2AllocatorIon() override;
+
+    static bool isValid(const C2Handle* const o);
+
+    /**
+     * Updates the usage mapper for subsequent new allocations, as well as the supported
+     * minimum and maximum usage masks and default block-size to use for the mapper.
+     *
+     * \param mapper this method is called to map Codec 2.0 buffer usage to ion flags
+     *        required by the ion device
+     * \param minUsage minimum buffer usage required for supported allocations (defaults to 0)
+     * \param maxUsage maximum buffer usage supported by the ion allocator (defaults to SW_READ
+     *        | SW_WRITE)
+     * \param blockSize alignment used prior to calling |mapper| for the buffer capacity.
+     *        This also helps reduce the size of cache required for caching mapper results.
+     *        (defaults to the page size)
+     */
+    void setUsageMapper(
+            const UsageMapperFn &mapper, uint64_t minUsage, uint64_t maxUsage, uint64_t blockSize);
+
+private:
+    c2_status_t mapUsage(C2MemoryUsage usage, size_t size,
+                     /* => */ size_t *align, unsigned *heapMask, unsigned *flags);
+
+    c2_status_t mInit;
+    int mIonFd;
+
+    // this locks mTraits, mBlockSize, mUsageMapper, mUsageMapperLru and mUsageMapperCache
+    mutable std::mutex mUsageMapperLock;
+    std::shared_ptr<const Traits> mTraits;
+    size_t mBlockSize;
+    UsageMapperFn mUsageMapper;
+    typedef std::pair<uint64_t, size_t> MapperKey;
+    struct MapperKeyHash {
+        std::size_t operator()(const MapperKey &) const;
+    };
+    typedef std::tuple<size_t, unsigned, unsigned, c2_status_t> MapperValue;
+    typedef std::pair<MapperKey, MapperValue> MapperKeyValue;
+    typedef std::list<MapperKeyValue>::iterator MapperKeyValuePointer;
+    std::list<MapperKeyValue> mUsageMapperLru;
+    std::unordered_map<MapperKey, MapperKeyValuePointer, MapperKeyHash> mUsageMapperCache;
+};
+
+} // namespace android
+
+#endif // STAGEFRIGHT_CODEC2_ALLOCATOR_ION_H_
diff --git a/media/codec2/vndk/include/C2BqBufferPriv.h b/media/codec2/vndk/include/C2BqBufferPriv.h
new file mode 100644
index 0000000..9271a71
--- /dev/null
+++ b/media/codec2/vndk/include/C2BqBufferPriv.h
@@ -0,0 +1,77 @@
+/*
+ * 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 STAGEFRIGHT_CODEC2_BQ_BUFFER_PRIV_H_
+#define STAGEFRIGHT_CODEC2_BQ_BUFFER_PRIV_H_
+
+#include <functional>
+
+#include <C2Buffer.h>
+#include <media/stagefright/bqhelper/WGraphicBufferProducer.h>
+
+class C2BufferQueueBlockPool : public C2BlockPool {
+public:
+    C2BufferQueueBlockPool(const std::shared_ptr<C2Allocator> &allocator, const local_id_t localId);
+
+    virtual ~C2BufferQueueBlockPool() override;
+
+    virtual C2Allocator::id_t getAllocatorId() const override {
+        return mAllocator->getId();
+    };
+
+    virtual local_id_t getLocalId() const override {
+        return mLocalId;
+    };
+
+    virtual c2_status_t fetchGraphicBlock(
+            uint32_t width,
+            uint32_t height,
+            uint32_t format,
+            C2MemoryUsage usage,
+            std::shared_ptr<C2GraphicBlock> *block /* nonnull */) override;
+
+    typedef std::function<void(uint64_t producer, int32_t slot, int64_t nsecs)> OnRenderCallback;
+
+    /**
+     * Sets render callback.
+     *
+     * \param renderCallbak callback to call for all dequeue buffer.
+     */
+    virtual void setRenderCallback(const OnRenderCallback &renderCallback = OnRenderCallback());
+
+    /**
+     * Configures an IGBP in order to create blocks. A newly created block is
+     * dequeued from the configured IGBP. Unique Id of IGBP and the slot number of
+     * blocks are passed via native_handle. Managing IGBP is responsibility of caller.
+     * When IGBP is not configured, block will be created via allocator.
+     * Since zero is not used for Unique Id of IGBP, if IGBP is not configured or producer
+     * is configured as nullptr, unique id which is bundled in native_handle is zero.
+     *
+     * \param producer      the IGBP, which will be used to fetch blocks
+     */
+    virtual void configureProducer(const android::sp<android::HGraphicBufferProducer> &producer);
+
+private:
+    const std::shared_ptr<C2Allocator> mAllocator;
+    const local_id_t mLocalId;
+
+    class Impl;
+    std::shared_ptr<Impl> mImpl;
+
+    friend struct C2BufferQueueBlockPoolData;
+};
+
+#endif // STAGEFRIGHT_CODEC2_BUFFER_PRIV_H_
diff --git a/media/codec2/vndk/include/C2BufferPriv.h b/media/codec2/vndk/include/C2BufferPriv.h
new file mode 100644
index 0000000..d0b9152
--- /dev/null
+++ b/media/codec2/vndk/include/C2BufferPriv.h
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2016 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 STAGEFRIGHT_CODEC2_BUFFER_PRIV_H_
+#define STAGEFRIGHT_CODEC2_BUFFER_PRIV_H_
+
+#include <functional>
+
+#include <C2Buffer.h>
+#include <android/hardware/media/bufferpool/1.0/IAccessor.h>
+
+class C2BasicLinearBlockPool : public C2BlockPool {
+public:
+    explicit C2BasicLinearBlockPool(const std::shared_ptr<C2Allocator> &allocator);
+
+    virtual ~C2BasicLinearBlockPool() override = default;
+
+    virtual C2Allocator::id_t getAllocatorId() const override {
+        return mAllocator->getId();
+    }
+
+    virtual local_id_t getLocalId() const override {
+        return BASIC_LINEAR;
+    }
+
+    virtual c2_status_t fetchLinearBlock(
+            uint32_t capacity,
+            C2MemoryUsage usage,
+            std::shared_ptr<C2LinearBlock> *block /* nonnull */) override;
+
+    // TODO: fetchCircularBlock
+
+private:
+    const std::shared_ptr<C2Allocator> mAllocator;
+};
+
+class C2BasicGraphicBlockPool : public C2BlockPool {
+public:
+    explicit C2BasicGraphicBlockPool(const std::shared_ptr<C2Allocator> &allocator);
+
+    virtual ~C2BasicGraphicBlockPool() override = default;
+
+    virtual C2Allocator::id_t getAllocatorId() const override {
+        return mAllocator->getId();
+    }
+
+    virtual local_id_t getLocalId() const override {
+        return BASIC_GRAPHIC;
+    }
+
+    virtual c2_status_t fetchGraphicBlock(
+            uint32_t width,
+            uint32_t height,
+            uint32_t format,
+            C2MemoryUsage usage,
+            std::shared_ptr<C2GraphicBlock> *block /* nonnull */) override;
+
+private:
+    const std::shared_ptr<C2Allocator> mAllocator;
+};
+
+class C2PooledBlockPool : public C2BlockPool {
+public:
+    C2PooledBlockPool(const std::shared_ptr<C2Allocator> &allocator, const local_id_t localId);
+
+    virtual ~C2PooledBlockPool() override;
+
+    virtual C2Allocator::id_t getAllocatorId() const override {
+        return mAllocator->getId();
+    }
+
+    virtual local_id_t getLocalId() const override {
+        return mLocalId;
+    }
+
+    virtual c2_status_t fetchLinearBlock(
+            uint32_t capacity,
+            C2MemoryUsage usage,
+            std::shared_ptr<C2LinearBlock> *block /* nonnull */) override;
+
+    virtual c2_status_t fetchGraphicBlock(
+            uint32_t width,
+            uint32_t height,
+            uint32_t format,
+            C2MemoryUsage usage,
+            std::shared_ptr<C2GraphicBlock> *block) override;
+
+    /**
+     * Retrieves the connection Id for underlying bufferpool
+     */
+    int64_t getConnectionId();
+
+    /**
+     * Retrieves the accessor which is used by underlying bufferpool. (It can be
+     * passed to receiving process.)
+     *
+     * \param accessor          IAccessor will be written to this out parameter.
+     *
+     * \return true             IAcessor is writen successfully.
+     * \return false            IAccessor is not written.
+     */
+    bool getAccessor(android::sp<android::hardware::media::bufferpool::V1_0::IAccessor> *accessor);
+
+private:
+    const std::shared_ptr<C2Allocator> mAllocator;
+    const local_id_t mLocalId;
+
+    class Impl;
+    std::unique_ptr<Impl> mImpl;
+};
+
+#endif // STAGEFRIGHT_CODEC2_BUFFER_PRIV_H_
diff --git a/media/codec2/vndk/include/C2ComponentFactory.h b/media/codec2/vndk/include/C2ComponentFactory.h
new file mode 100644
index 0000000..f6d8b98
--- /dev/null
+++ b/media/codec2/vndk/include/C2ComponentFactory.h
@@ -0,0 +1,87 @@
+/*
+ * 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 STAGEFRIGHT_CODEC2_COMPONENT_FACTORY_H_
+#define STAGEFRIGHT_CODEC2_COMPONENT_FACTORY_H_
+
+#include <C2Component.h>
+
+#include <functional>
+#include <memory>
+
+/**
+ * Component factory object that enables to create a component and/or interface from a dynamically
+ * linked library. This is needed because the component/interfaces are managed objects, but we
+ * cannot safely create a managed object and pass it in C.
+ *
+ * Components/interfaces typically inherit from std::enable_shared_from_this, but C requires
+ * passing simple pointer, and shared_ptr constructor needs to know the class to be constructed
+ * derives from enable_shared_from_this.
+ *
+ */
+class C2ComponentFactory {
+public:
+    typedef std::function<void(::C2Component*)> ComponentDeleter;
+    typedef std::function<void(::C2ComponentInterface*)> InterfaceDeleter;
+
+    /**
+     * Creates a component.
+     *
+     * This method SHALL return within 100ms.
+     *
+     * \param id        component ID for the created component
+     * \param component shared pointer where the created component is stored. Cleared on
+     *                  failure and updated on success.
+     *
+     * \retval C2_OK        the component was created successfully
+     * \retval C2_TIMED_OUT could not create the component within the time limit (unexpected)
+     * \retval C2_CORRUPTED some unknown error prevented the creation of the component (unexpected)
+     *
+     * \retval C2_NO_MEMORY not enough memory to create the component
+     */
+    virtual c2_status_t createComponent(
+            c2_node_id_t id, std::shared_ptr<C2Component>* const component,
+            ComponentDeleter deleter = std::default_delete<C2Component>()) = 0;
+
+    /**
+     * Creates a component interface.
+     *
+     * This method SHALL return within 100ms.
+     *
+     * \param id        component interface ID for the created interface
+     * \param interface shared pointer where the created interface is stored. Cleared on
+     *                  failure and updated on success.
+     *
+     * \retval C2_OK        the component interface was created successfully
+     * \retval C2_TIMED_OUT could not create the component interface within the time limit
+     *                      (unexpected)
+     * \retval C2_CORRUPTED some unknown error prevented the creation of the component interface
+     *                      (unexpected)
+     *
+     * \retval C2_NO_MEMORY not enough memory to create the component interface
+     */
+    virtual c2_status_t createInterface(
+            c2_node_id_t id, std::shared_ptr<C2ComponentInterface>* const interface,
+            InterfaceDeleter deleter = std::default_delete<C2ComponentInterface>()) = 0;
+
+    virtual ~C2ComponentFactory() = default;
+
+    typedef ::C2ComponentFactory* (*CreateCodec2FactoryFunc)(void);
+    typedef void (*DestroyCodec2FactoryFunc)(::C2ComponentFactory*);
+};
+
+
+#endif // STAGEFRIGHT_CODEC2_COMPONENT_FACTORY_H_
diff --git a/media/codec2/vndk/include/C2Debug.h b/media/codec2/vndk/include/C2Debug.h
new file mode 100644
index 0000000..af1cdab
--- /dev/null
+++ b/media/codec2/vndk/include/C2Debug.h
@@ -0,0 +1,28 @@
+/*
+ * 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 C2UTILS_DEBUG_H_
+#define C2UTILS_DEBUG_H_
+
+#include <util/C2Debug-log.h>
+
+// To allow arbitrary ordering of C2Debug.h and API headers and to keep debug utilities separately
+// from the API definitions, we provide API header specific debug headers.
+#ifdef C2PARAM_H_
+#include <util/C2Debug-param.h>
+#endif
+
+#endif  // C2UTILS_DEBUG_H_
diff --git a/media/codec2/vndk/include/C2ErrnoUtils.h b/media/codec2/vndk/include/C2ErrnoUtils.h
new file mode 100644
index 0000000..5b995f6
--- /dev/null
+++ b/media/codec2/vndk/include/C2ErrnoUtils.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2016 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 STAGEFRIGHT_CODEC2_ERRNO_UTILS_H_
+#define STAGEFRIGHT_CODEC2_ERRNO_UTILS_H_
+
+#include <errno.h>
+#include <C2.h>
+
+// standard ERRNO mappings
+template<int N> constexpr c2_status_t _c2_errno2status_impl();
+template<> constexpr c2_status_t _c2_errno2status_impl<0>()       { return C2_OK; }
+template<> constexpr c2_status_t _c2_errno2status_impl<EINVAL>()  { return C2_BAD_VALUE; }
+template<> constexpr c2_status_t _c2_errno2status_impl<EACCES>()  { return C2_REFUSED; }
+template<> constexpr c2_status_t _c2_errno2status_impl<EPERM>()   { return C2_REFUSED; }
+template<> constexpr c2_status_t _c2_errno2status_impl<ENOMEM>()  { return C2_NO_MEMORY; }
+
+// map standard errno-s to the equivalent c2_status_t
+template<int... N> struct _c2_map_errno_impl;
+template<int E, int ... N> struct _c2_map_errno_impl<E, N...> {
+    static c2_status_t map(int result) {
+        if (result == E) {
+            return _c2_errno2status_impl <E>();
+        } else {
+            return _c2_map_errno_impl<N...>::map(result);
+        }
+    }
+};
+template<> struct _c2_map_errno_impl<> {
+    static c2_status_t map(int result) {
+        return result == 0 ? C2_OK : C2_CORRUPTED;
+    }
+};
+
+template<int... N>
+c2_status_t c2_map_errno(int result) {
+    return _c2_map_errno_impl<N...>::map(result);
+}
+
+#endif // STAGEFRIGHT_CODEC2_ERRNO_UTILS_H_
+
diff --git a/media/codec2/vndk/include/C2PlatformStorePluginLoader.h b/media/codec2/vndk/include/C2PlatformStorePluginLoader.h
new file mode 100644
index 0000000..4c10643
--- /dev/null
+++ b/media/codec2/vndk/include/C2PlatformStorePluginLoader.h
@@ -0,0 +1,98 @@
+/*
+ * Copyright 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 STAGEFRIGHT_C2_PLATFORM_STORE_PLUGIN_LOADER_H_
+
+#define STAGEFRIGHT_C2_PLATFORM_STORE_PLUGIN_LOADER_H_
+
+#include <memory>
+
+#include <utils/Mutex.h>
+
+#include <C2.h>
+#include <C2Buffer.h>
+
+/**
+ * Extern C interface for creating block pool from platform store extension.
+ *
+ * \param alloctorId  the ID of the backing allocator type.
+ * \parem blockPoolId the ID of created block pool.
+ *
+ * \return pointer of created C2BlockPool, nullptr on error.
+ */
+typedef ::C2BlockPool* (*CreateBlockPoolFunc)(::C2Allocator::id_t, ::C2BlockPool::local_id_t);
+
+/**
+ * Extern C interface for creating allocator from platform store extension.
+ *
+ * \param alloctorId  the ID of the allocator to create.
+ * \param status      the returned status from creating allocator.
+ *
+ * \return pointer of created C2Allocator, nullptr on error.
+ */
+typedef ::C2Allocator* (*CreateAllocatorFunc)(::C2Allocator::id_t, ::c2_status_t*);
+
+class C2PlatformStorePluginLoader {
+public:
+    static const std::unique_ptr<C2PlatformStorePluginLoader>& GetInstance();
+    ~C2PlatformStorePluginLoader();
+
+    /**
+     * Creates block pool from platform store extension.
+     *
+     * \param alloctorId  the ID of the backing allocator type.
+     * \param blockPoolId the ID of created block pool.
+     * \param pool        shared pointer where the created block pool is stored.
+     *
+     * \retval C2_OK        the block pool was created successfully.
+     * \retval C2_NOT_FOUND the extension symbol was not found.
+     * \retval C2_BAD_INDEX the input allocatorId is not defined in platform store extension.
+     */
+    c2_status_t createBlockPool(::C2Allocator::id_t allocatorId,
+                                ::C2BlockPool::local_id_t blockPoolId,
+                                std::shared_ptr<C2BlockPool>* pool);
+
+    /**
+     * Creates allocator from platform store extension.
+     *
+     * Note that this allocator is not created as shared singleton as C2AllocatorStore does, because
+     * C interface only allows raw pointer transmission for extension.
+     *
+     * \param alloctorId  the ID of the allocator to create.
+     * \param allocator   shared pointer where the created allocator is stored.
+     *
+     * \retval C2_OK        the allocator was created successfully.
+     * \retval C2_TIMED_OUT could not create the allocator within the time limit (unexpected)
+     * \retval C2_CORRUPTED some unknown error prevented the creation of the allocator (unexpected)
+     * \retval C2_NOT_FOUND the extension symbol was not found.
+     * \retval C2_BAD_INDEX the input allocatorId is not defined in platform store extension.
+     * \retval C2_NO_MEMORY not enough memory to create the allocator
+     */
+    c2_status_t createAllocator(::C2Allocator::id_t allocatorId,
+                                std::shared_ptr<C2Allocator>* const allocator);
+
+private:
+    explicit C2PlatformStorePluginLoader(const char *libPath);
+
+    static android::Mutex sMutex;
+    static std::unique_ptr<C2PlatformStorePluginLoader> sInstance;
+
+    void *mLibHandle;
+    CreateBlockPoolFunc mCreateBlockPool;
+    CreateAllocatorFunc mCreateAllocator;
+};
+
+#endif  // STAGEFRIGHT_C2_PLATFORM_STORE_PLUGIN_LOADER_H_
diff --git a/media/codec2/vndk/include/C2PlatformSupport.h b/media/codec2/vndk/include/C2PlatformSupport.h
new file mode 100644
index 0000000..f31282c
--- /dev/null
+++ b/media/codec2/vndk/include/C2PlatformSupport.h
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2017 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 STAGEFRIGHT_CODEC2_PLATFORM_SUPPORT_H_
+#define STAGEFRIGHT_CODEC2_PLATFORM_SUPPORT_H_
+
+#include <C2Component.h>
+#include <C2ComponentFactory.h>
+
+#include <memory>
+
+namespace android {
+
+/**
+ * Returns the platform allocator store.
+ * \retval nullptr if the platform allocator store could not be obtained
+ */
+std::shared_ptr<C2AllocatorStore> GetCodec2PlatformAllocatorStore();
+
+/**
+ * Platform allocator store IDs
+ */
+class C2PlatformAllocatorStore : public C2AllocatorStore {
+public:
+    enum : id_t {
+        /**
+         * ID of the ion backed platform allocator.
+         *
+         * C2Handle consists of:
+         *   fd  shared ion buffer handle
+         *   int size (lo 32 bits)
+         *   int size (hi 32 bits)
+         *   int magic '\xc2io\x00'
+         */
+        ION = PLATFORM_START,
+
+        /**
+         * ID of the gralloc backed platform allocator.
+         *
+         * C2Handle layout is not public. Use C2AllocatorGralloc::UnwrapNativeCodec2GrallocHandle
+         * to get the underlying gralloc handle from a C2Handle, and WrapNativeCodec2GrallocHandle
+         * to create a C2Handle from a gralloc handle - for C2Allocator::priorAllocation.
+         */
+        GRALLOC,
+
+        /**
+         * ID of the bufferqueue backed platform allocator.
+         *
+         * C2Handle layout is not public. Use C2AllocatorGralloc::UnwrapNativeCodec2GrallocHandle
+         * to get the underlying handle from a C2Handle, and WrapNativeCodec2GrallocHandle
+         * to create a C2Handle from a handle - for C2Allocator::priorAllocation.
+         */
+        BUFFERQUEUE,
+
+        /**
+         * ID of indicating the end of platform allocator definition.
+         *
+         * \note always put this macro in the last place.
+         *
+         * Extended platform store plugin should use this macro as the start ID of its own allocator
+         * types.
+         */
+        PLATFORM_END,
+    };
+};
+
+/**
+ * Retrieves a block pool for a component.
+ *
+ * \param id        the local ID of the block pool
+ * \param component the component using the block pool (must be non-null)
+ * \param pool      pointer to where the obtained block pool shall be stored on success. nullptr
+ *                  will be stored here on failure
+ *
+ * \retval C2_OK        the operation was successful
+ * \retval C2_BAD_VALUE the component is null
+ * \retval C2_NOT_FOUND if the block pool does not exist
+ * \retval C2_NO_MEMORY not enough memory to fetch the block pool (this return value is only
+ *                      possible for basic pools)
+ * \retval C2_TIMED_OUT the operation timed out (this return value is only possible for basic pools)
+ * \retval C2_REFUSED   no permission to complete any required allocation (this return value is only
+ *                      possible for basic pools)
+ * \retval C2_CORRUPTED some unknown, unrecoverable error occured during operation (unexpected,
+ *                      this return value is only possible for basic pools)
+ */
+c2_status_t GetCodec2BlockPool(
+        C2BlockPool::local_id_t id, std::shared_ptr<const C2Component> component,
+        std::shared_ptr<C2BlockPool> *pool);
+
+/**
+ * Creates a block pool.
+ * \param allocatorId  the allocator ID which is used to allocate blocks
+ * \param component     the component using the block pool (must be non-null)
+ * \param pool          pointer to where the created block pool shall be store on success.
+ *                      nullptr will be stored here on failure
+ *
+ * \retval C2_OK        the operation was successful
+ * \retval C2_BAD_VALUE the component is null
+ * \retval C2_NOT_FOUND if the allocator does not exist
+ * \retval C2_NO_MEMORY not enough memory to create a block pool
+ */
+c2_status_t CreateCodec2BlockPool(
+        C2PlatformAllocatorStore::id_t allocatorId,
+        std::shared_ptr<const C2Component> component,
+        std::shared_ptr<C2BlockPool> *pool);
+
+/**
+ * Returns the platform component store.
+ * \retval nullptr if the platform component store could not be obtained
+ */
+std::shared_ptr<C2ComponentStore> GetCodec2PlatformComponentStore();
+
+/**
+ * Sets the preferred component store in this process for the sole purpose of accessing its
+ * interface. If this is not called, the default IComponentStore HAL (if exists) is the preferred
+ * store for this purpose. If the default IComponentStore HAL is not present, the platform
+ * component store is used.
+ */
+void SetPreferredCodec2ComponentStore(std::shared_ptr<C2ComponentStore> store);
+
+} // namespace android
+
+#endif // STAGEFRIGHT_CODEC2_PLATFORM_SUPPORT_H_
diff --git a/media/codec2/vndk/include/android-C2Debug-log.h b/media/codec2/vndk/include/android-C2Debug-log.h
new file mode 100644
index 0000000..5910228
--- /dev/null
+++ b/media/codec2/vndk/include/android-C2Debug-log.h
@@ -0,0 +1,67 @@
+/*
+ * 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 C2UTILS_ANDROID_DEBUG_LOG_H_
+#define C2UTILS_ANDROID_DEBUG_LOG_H_
+
+/*
+ * Android provides logging and debug macros. Redefine them with C2 prefix and add support for
+ * opting out of verbose logs.
+ */
+
+#ifdef C2_LOG_TAG
+#define LOG_TAG C2_LOG_TAG
+#endif
+
+#include <android-base/logging.h>
+
+#ifdef C2_LOG_VERBOSE
+#define C2_LOG(LEVEL) LOG(::android::base::LEVEL)
+#else
+/**
+ * Use as follows:
+ *
+ * #define C2_LOG_TAG "tag"
+ * //#define C2_LOG_VERBOSE  // enable verbose logs in this file
+ * #include <C2Debug.h>
+ *
+ * C2_LOG(DEBUG) << expr ...;
+ *
+ * Log levels are: VERBOSE, DEBUG, INFO, WARNING, ERROR, FATAL (aborts).
+ *
+ * No endl is required.
+ */
+#define C2_LOG(LEVEL) \
+        (::android::base::LEVEL != ::android::base::VERBOSE) && LOG(::android::base::LEVEL)
+#endif
+
+#define C2_CHECK    CHECK
+#define C2_CHECK_LT CHECK_LT
+#define C2_CHECK_LE CHECK_LE
+#define C2_CHECK_EQ CHECK_EQ
+#define C2_CHECK_GE CHECK_GE
+#define C2_CHECK_GT CHECK_GT
+#define C2_CHECK_NE CHECK_NE
+
+#define C2_DCHECK    DCHECK
+#define C2_DCHECK_LT DCHECK_LT
+#define C2_DCHECK_LE DCHECK_LE
+#define C2_DCHECK_EQ DCHECK_EQ
+#define C2_DCHECK_GE DCHECK_GE
+#define C2_DCHECK_GT DCHECK_GT
+#define C2_DCHECK_NE DCHECK_NE
+
+#endif  // C2UTILS_ANDROID_DEBUG_LOG_H_
diff --git a/media/codec2/vndk/include/util/C2Debug-base.h b/media/codec2/vndk/include/util/C2Debug-base.h
new file mode 100644
index 0000000..a040e42
--- /dev/null
+++ b/media/codec2/vndk/include/util/C2Debug-base.h
@@ -0,0 +1,36 @@
+/*
+ * 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 C2UTILS_DEBUG_BASE_H_
+#define C2UTILS_DEBUG_BASE_H_
+
+#include <iostream>
+
+/**
+ * Debug print utilities for Codec 2.0 base objects.
+ */
+
+#define C2_DECLARE_AS_STRING_AND_DEFINE_STREAM_OUT(type) \
+const char *asString(type i, const char *def = "??"); \
+inline std::ostream& operator<<(std::ostream& os, const type &i) { \
+    return os << asString(i); \
+}
+
+C2_DECLARE_AS_STRING_AND_DEFINE_STREAM_OUT(c2_status_t)
+
+
+#endif  // C2UTILS_DEBUG_BASE_H_
+
diff --git a/media/codec2/vndk/include/util/C2Debug-interface.h b/media/codec2/vndk/include/util/C2Debug-interface.h
new file mode 100644
index 0000000..3f31875
--- /dev/null
+++ b/media/codec2/vndk/include/util/C2Debug-interface.h
@@ -0,0 +1,34 @@
+/*
+ * 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 C2UTILS_DEBUG_INTERFACE_H_
+#define C2UTILS_DEBUG_INTERFACE_H_
+
+#include <util/C2Debug-base.h>
+#include <util/C2InterfaceUtils.h>
+
+#include <iostream>
+
+template<typename T>
+std::ostream& operator<<(std::ostream& os, const C2SupportedRange<T> &i);
+
+template<typename T>
+std::ostream& operator<<(std::ostream& os, const C2SupportedValueSet<T> &i);
+
+template<typename T>
+std::ostream& operator<<(std::ostream& os, const C2FieldSupportedValuesHelper<T> &i);
+
+#endif  // C2UTILS_DEBUG_INTERFACE_H_
diff --git a/media/codec2/vndk/include/util/C2Debug-log.h b/media/codec2/vndk/include/util/C2Debug-log.h
new file mode 100644
index 0000000..195c4c1
--- /dev/null
+++ b/media/codec2/vndk/include/util/C2Debug-log.h
@@ -0,0 +1,27 @@
+/*
+ * 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 C2UTILS_DEBUG_LOG_H_
+#define C2UTILS_DEBUG_LOG_H_
+
+// Platform specific debug utilities
+#ifdef __ANDROID__
+#include <android-C2Debug-log.h>
+#else
+// TODO: implement base debug utils
+#endif
+
+#endif  // C2UTILS_DEBUG_LOG_H_
diff --git a/media/codec2/vndk/include/util/C2Debug-param.h b/media/codec2/vndk/include/util/C2Debug-param.h
new file mode 100644
index 0000000..e1c1de0
--- /dev/null
+++ b/media/codec2/vndk/include/util/C2Debug-param.h
@@ -0,0 +1,37 @@
+/*
+ * 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 C2UTILS_DEBUG_PARAM_H_
+#define C2UTILS_DEBUG_PARAM_H_
+
+#include <C2Param.h>
+#include <util/C2Debug-base.h>
+
+#include <iostream>
+
+/**
+ * Debug/print declarations for objects defined in C2Param.h
+ */
+C2_DECLARE_AS_STRING_AND_DEFINE_STREAM_OUT(C2FieldDescriptor::type_t)
+
+std::ostream& operator<<(std::ostream& os, const C2Param::CoreIndex &i);
+std::ostream& operator<<(std::ostream& os, const C2Param::Type &i);
+std::ostream& operator<<(std::ostream& os, const C2Param::Index &i);
+std::ostream& operator<<(std::ostream& os, const _C2FieldId &i);
+std::ostream& operator<<(std::ostream& os, const C2FieldDescriptor &i);
+std::ostream& operator<<(std::ostream& os, const C2ParamField &i);
+
+#endif  // C2UTILS_DEBUG_PARAM_H_
diff --git a/media/codec2/vndk/include/util/C2InterfaceHelper.h b/media/codec2/vndk/include/util/C2InterfaceHelper.h
new file mode 100644
index 0000000..bfb43af
--- /dev/null
+++ b/media/codec2/vndk/include/util/C2InterfaceHelper.h
@@ -0,0 +1,752 @@
+/*
+ * 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 C2UTILS_INTERFACE_HELPER_H_
+#define C2UTILS_INTERFACE_HELPER_H_
+
+#include <C2Component.h>
+#include <util/C2InterfaceUtils.h>
+
+#include <map>
+#include <mutex>
+#include <vector>
+
+#include <stddef.h>
+
+/**
+ * Interface Helper
+ */
+using C2R = C2SettingResultsBuilder;
+
+template<typename T, bool E=std::is_enum<T>::value>
+struct _c2_reduce_enum_to_underlying_type {
+    typedef T type;
+};
+
+template<typename T>
+struct _c2_reduce_enum_to_underlying_type<T, true> {
+    typedef typename std::underlying_type<T>::type type;
+};
+
+/**
+ * Helper class to implement parameter reflectors. This class is dynamic and is designed to be
+ * shared by multiple interfaces. This allows interfaces to add structure descriptors as needed.
+ */
+class C2ReflectorHelper : public C2ParamReflector {
+public:
+    C2ReflectorHelper() = default;
+    virtual ~C2ReflectorHelper() = default;
+    virtual std::unique_ptr<C2StructDescriptor> describe(
+            C2Param::CoreIndex paramIndex) const override;
+
+    /**
+     * Adds support for describing the given parameters.
+     *
+     * \param Params types of codec 2.0 structs (or parameters) to describe
+     */
+    template<typename... Params>
+    C2_INLINE void addStructDescriptors() {
+        std::vector<C2StructDescriptor> structs;
+        addStructDescriptors(structs, (_Tuple<Params...> *)nullptr);
+    }
+
+    /**
+     * Adds support for describing a specific struct.
+     *
+     * \param strukt descriptor for the struct that will be moved out.
+     */
+    void addStructDescriptor(C2StructDescriptor &&strukt);
+
+private:
+    template<typename... Params>
+    class C2_HIDE _Tuple { };
+
+    /**
+     * Adds support for describing the given descriptors.
+     *
+     * \param structs List of structure descriptors to add support for
+     */
+    void addStructDescriptors(
+            std::vector<C2StructDescriptor> &structs, _Tuple<> *);
+
+    /**
+     * Utility method that adds support for describing the given descriptors in a recursive manner
+     * one structure at a time using a list of structure descriptors temporary.
+     *
+     * \param T the type of codec 2.0 struct to describe
+     * \param Params rest of the structs
+     * \param structs Temporary list of structure descriptors used to optimize the operation.
+     */
+    template<typename T, typename... Params>
+    C2_INLINE void addStructDescriptors(
+            std::vector<C2StructDescriptor> &structs, _Tuple<T, Params...> *) {
+        structs.emplace_back((T*)nullptr);
+        addStructDescriptors(structs, (_Tuple<Params...> *)nullptr);
+    }
+
+    mutable std::mutex _mMutex;
+    std::map<C2Param::CoreIndex, const C2StructDescriptor> _mStructs; ///< descriptors
+};
+
+/**
+ * Utility class that implements the codec 2.0 interface API-s for some parameters.
+ *
+ * This class must be subclassed.
+ */
+class C2InterfaceHelper {
+public:
+    /**
+     * Returns the base offset of a field at |offset| that could be part of an array or part of a
+     * sub-structure.
+     *
+     * This method does not do field size verification, e.g. if offset if obtained from a structure,
+     * it will not stop at the structure boundary - this is okay, as we just want the base offset
+     * here, which is the same.
+     */
+    static
+    size_t GetBaseOffset(const std::shared_ptr<C2ParamReflector> &reflector,
+                                C2Param::CoreIndex index, size_t offset);
+
+    /**
+     * The interface helper class uses references to std::shared_ptr<T> config parameters.
+     * Internally, these need to be generalized to std::shared_ptr<C2Param> refs, but the cast is
+     * not allowed (as these are references). As such, this class never returns pointer to the
+     * shared_ptrs.
+     */
+    struct ParamRef {
+        template<typename T, typename enable=
+                typename std::enable_if<std::is_convertible<T, C2Param>::value>::type>
+        inline C2_HIDE ParamRef(std::shared_ptr<T> &param)
+            : _mRef(reinterpret_cast<std::shared_ptr<C2Param>*>(&param)) { }
+
+        // used by comparison operator for containers
+        operator std::shared_ptr<C2Param> *() const { return _mRef; }
+
+        /**
+         * Returns a shared pointer to the parameter.
+         */
+        std::shared_ptr<C2Param> get() const { return *_mRef; }
+
+    private:
+        std::shared_ptr<C2Param> *_mRef;
+    };
+
+    /**
+     * Field helper.
+     *
+     * Contains additional information for the field: possible values, and currently supported
+     * values.
+     */
+    class FieldHelper {
+    public:
+        /**
+         * Creates helper for a field with given possible values.
+         *
+         * \param param parameter reference. The parameter does not have to be initialized at this
+         *        point.
+         * \param field field identifier
+         * \param values possible values for the field
+         */
+        FieldHelper(const ParamRef &param, const _C2FieldId &field,
+                    std::unique_ptr<C2FieldSupportedValues> &&values);
+
+        /**
+         * Creates a param-field identifier for this field. This method is called after the
+         * underlying parameter has been initialized.
+         *
+         * \aram index
+         *
+         * @return C2ParamField
+         */
+        C2ParamField makeParamField(C2Param::Index index) const;
+
+        /**
+         * Sets the currently supported values for this field.
+         *
+         * \param values currently supported values that will be moved out
+         */
+        void setSupportedValues(std::unique_ptr<C2FieldSupportedValues> &&values);
+
+        /**
+         * Gets the currently supported values for this field. This defaults to the possible values
+         * if currently supported values were never set.
+         */
+        const C2FieldSupportedValues *getSupportedValues() const;
+
+        /**
+         * Gets the possible values for this field.
+         */
+        const C2FieldSupportedValues *getPossibleValues() const;
+
+    protected:
+        // TODO: move to impl for safety
+        ParamRef mParam;
+        _C2FieldId mFieldId;
+        std::unique_ptr<C2FieldSupportedValues> mPossible;
+        std::unique_ptr<C2FieldSupportedValues> mSupported; ///< if different from possible
+    };
+
+    template<typename T>
+    struct C2_HIDE Param;
+    class ParamHelper;
+
+    /**
+     * Factory is an interface to get the parameter helpers from a std::shared_ptr<T> &.
+     */
+    class Factory {
+        // \todo this may be already in ParamHelper
+        virtual std::shared_ptr<C2ParamReflector> getReflector() const = 0;
+
+        virtual std::shared_ptr<ParamHelper> getParamHelper(const ParamRef &param) const = 0;
+
+    public:
+        virtual ~Factory() = default;
+
+        template<typename T>
+        Param<T> get(std::shared_ptr<T> &param, std::shared_ptr<T> altValue = nullptr) const {
+            return Param<T>(getParamHelper(ParamRef(param)),
+                            altValue == nullptr ? param : altValue,
+                            getReflector());
+        }
+    };
+
+    /**
+     * Typed field helper.
+     */
+    template<typename T>
+    struct Field {
+        /**
+         * Constructor.
+         *
+         * \param helper helper for this field
+         * \param index  parameter index (this is needed as it is not available during parameter
+         *        construction) \todo remove
+         */
+        Field(std::shared_ptr<FieldHelper> helper, C2Param::Index index);
+
+        bool supportsAtAll(T value) const {
+            return C2FieldSupportedValuesHelper<T>(*_mHelper->getPossibleValues()).supports(value);
+        }
+
+        bool supportsNow(T value) const {
+            return C2FieldSupportedValuesHelper<T>(*_mHelper->getSupportedValues()).supports(value);
+        }
+
+        /**
+         * Creates a conflict resolution suggestion builder for this field.
+         */
+        C2ParamFieldValuesBuilder<T> shouldBe() const;
+
+        /**
+         * Creates a currently supported values builder for this field. This is only supported
+         * for non-const fields to disallow setting supported values for dependencies.
+         */
+        C2ParamFieldValuesBuilder<T> mustBe();
+
+        operator C2ParamField() const {
+            return _mField;
+        }
+
+        // TODO
+        C2R validatePossible(const T &value __unused) const {
+            /// TODO
+            return C2R::Ok();
+        }
+
+    private:
+        std::shared_ptr<FieldHelper> _mHelper;
+        C2ParamField _mField;
+    };
+
+    class ParamHelper {
+    public:
+        ParamHelper(ParamRef param, C2StringLiteral name, C2StructDescriptor &&);
+        ParamHelper(ParamHelper &&);
+        ~ParamHelper();
+
+        /**
+         * Finds a field descriptor.
+         */
+        std::shared_ptr<FieldHelper> findField(size_t baseOffs, size_t baseSize) const;
+
+        /// returns the parameter ref for this parameter
+        const ParamRef ref() const;
+
+        /// returns the current value of this parameter as modifiable. The constness of this
+        /// object determines the constness of the returned value.
+        std::shared_ptr<C2Param> value();
+
+        /// returns the current value of this parameter as const
+        std::shared_ptr<const C2Param> value() const;
+
+        /**
+         * Performs a configuration change request for this parameter.
+         *
+         * \param value    the value that is being assigned to this parameter.
+         *                 This could be pointing to the current value of the
+         *                 parameter. This must not change.
+         * \param mayBlock whether blocking is allowed
+         * \param endValue the resulting value
+         * \param factory  parameter factory (to access dependencies)
+         * \param failures vector of failures to append any failures from this
+         *                 operation
+         *
+         * \retval C2_OK        configuration was successful
+         * \retval C2_BAD_VALUE value is incorrect (TBD)
+         * \retval C2_NO_MEMORY not enough memory to perform the assignment
+         * \retval C2_TIMED_OUT configuration timed out
+         * \retval C2_BLOCKING  configuration requires blocking to be allowed
+         * \retval C2_CORRUPTED interface is corrupted
+         */
+        c2_status_t trySet(
+                const C2Param *value, bool mayBlock,
+                bool *changed,
+                Factory &factory,
+                std::vector<std::unique_ptr<C2SettingResult>>* const failures);
+
+        /// returns parameter indices that depend on this parameter
+        const std::vector<C2Param::Index> getDownDependencies() const;
+
+        /// adds a dependent parameter
+        void addDownDependency(C2Param::Index index);
+
+        /// returns that parameter refs for parameters that depend on this
+        const std::vector<ParamRef> getDependenciesAsRefs() const;
+
+        /// returns and moves out stored struct descriptor
+        C2StructDescriptor retrieveStructDescriptor();
+
+        /// returns the name of this parameter
+        C2String name() const;
+
+        /// returns the index of this parameter
+        C2Param::Index index() const;
+
+        /// returns the parameter descriptor
+        std::shared_ptr<const C2ParamDescriptor> getDescriptor() const;
+
+        /**
+         * Validates param helper.
+         *
+         * For now, this fills field info for const params.
+         *
+         * \retval C2_CORRUPTED the parameter cannot be added as such
+         */
+        c2_status_t validate(const std::shared_ptr<C2ParamReflector> &reflector);
+
+    protected:
+        typedef C2ParamDescriptor::attrib_t attrib_t;
+        attrib_t& attrib();
+
+        /// sets the default value of this parameter
+        void setDefaultValue(std::shared_ptr<C2Param> default_);
+
+        /// sets the setter method
+        void setSetter(std::function<C2R(const C2Param *, bool, bool *, Factory &)> setter);
+
+        /// sets the getter method
+        void setGetter(std::function<std::shared_ptr<C2Param>(bool)> getter);
+
+        /// sets the dependencies
+        void setDependencies(std::vector<C2Param::Index> indices, std::vector<ParamRef> refs);
+
+        /// sets the fields and their supported values
+        void setFields(std::vector<C2ParamFieldValues> &&fields);
+
+        /// build this into a final ParamHelper object
+        std::shared_ptr<ParamHelper> build();
+
+        class Impl;
+        std::unique_ptr<Impl> mImpl;
+    };
+
+    /**
+     * Typed parameter helper. This provides access to members as well as field helpers.
+     */
+    template<typename T>
+    struct C2_HIDE Param {
+        Param(
+                std::shared_ptr<ParamHelper> helper, std::shared_ptr<T> &param,
+                std::shared_ptr<C2ParamReflector> reflector)
+            : v(*param.get()),
+              _mTypedParam(param),
+              _mHelper(helper),
+              _mReflector(reflector) { }
+
+        template<typename S>
+        using FieldType = Field<
+                typename _c2_reduce_enum_to_underlying_type<
+                        typename std::remove_const<
+                                typename std::remove_extent<S>::type>::type>::type>;
+
+        template<typename S>
+        FieldType<S> F(S &field) {
+            size_t offs = (uintptr_t)&field - (uintptr_t)&get();
+            // this must fall either within sizeof(T) + FLEX_SIZE or param->size()
+            // size_t size = sizeof(field);
+            // mParam may be null
+            size_t baseSize = sizeof(typename std::remove_extent<S>::type);
+            size_t baseOffs = GetBaseOffset(
+                    _mReflector, T::CORE_INDEX, offs - sizeof(C2Param));
+            if (~baseOffs == 0) {
+                // C2_LOG(FATAL) << "unknown field at offset " << offs << " size " << sizeof(S)
+                //       << " base-size " << baseSize;
+                // __builtin_trap();
+            } else {
+                baseOffs += sizeof(C2Param);
+            }
+
+            std::shared_ptr<FieldHelper> helper = _mHelper->findField(baseOffs, baseSize);
+            return FieldType<S>(helper, _mTypedParam->index());
+        }
+
+        // const Param have const Fields; however, remove const from S
+        template<typename S>
+        const FieldType<S> F(S &field) const {
+            return const_cast<const FieldType<S>>(const_cast<Param *>(this)->F(field));
+        }
+
+        /// Returns a const ref value of this const param.
+        const T &get() const {
+            return *_mTypedParam.get();
+        }
+
+        /// Returns a modifiable ref value of this non-const param.
+        T &set() {
+            return *_mTypedParam.get();
+        }
+
+        /// Const-reference to the value.s
+        T const &v;
+
+    private:
+        std::shared_ptr<T> _mTypedParam;
+        std::shared_ptr<ParamHelper> _mHelper;
+        std::shared_ptr<C2ParamReflector> _mReflector;
+    };
+
+    template<typename T>
+    using C2P = Param<T>;
+
+    /**
+     * Templated move builder class for a parameter helper.
+     */
+    template<typename T>
+    class C2_HIDE ParamBuilder : private ParamHelper {
+    public:
+        /** Construct the parameter builder from minimal info required. */
+        ParamBuilder(std::shared_ptr<T> &param, C2StringLiteral name)
+            : ParamHelper(param, name, C2StructDescriptor((T*)nullptr)),
+              mTypedParam(&param) {
+            attrib() = attrib_t::IS_PERSISTENT;
+        }
+
+        /** Makes this parameter required. */
+        inline ParamBuilder &required() {
+            attrib() |= attrib_t::IS_REQUIRED;
+            return *this;
+        }
+
+        /** Makes this parameter transient (not persistent). */
+        inline ParamBuilder &transient() {
+            attrib() &= ~attrib_t::IS_PERSISTENT;
+            return *this;
+        }
+
+        /** Makes this parameter hidden (not exposed in JAVA API). */
+        inline ParamBuilder &hidden() {
+            attrib() |= attrib_t::IS_HIDDEN;
+            return *this;
+        }
+
+        /** Makes this parameter internal (not exposed to query/settings). */
+        inline ParamBuilder &internal() {
+            attrib() |= attrib_t::IS_INTERNAL;
+            return *this;
+        }
+
+        /** Adds default value. Must be added exactly once. */
+        inline ParamBuilder &withDefault(std::shared_ptr<T> default_) {
+            // CHECK(!mDefaultValue);
+            // WARN_IF(!default_); // could be nullptr if OOM
+            // technically, this could be in the parent
+            *mTypedParam = std::shared_ptr<T>(T::From(C2Param::Copy(*default_).release()));
+            setDefaultValue(default_);
+            std::shared_ptr<T> *typedParam = mTypedParam;
+            setGetter([typedParam](bool) -> std::shared_ptr<C2Param> {
+                return std::static_pointer_cast<C2Param>(*typedParam);
+            });
+            return *this;
+        }
+
+        /** Adds default value. Must be added exactly once. */
+        inline ParamBuilder &withDefault(T *default_) {
+            return withDefault(std::shared_ptr<T>(default_));
+        }
+
+        /** Adds all fields to this parameter with their possible values. */
+        inline ParamBuilder &withFields(std::vector<C2ParamFieldValues> &&fields_) {
+            setFields(std::move(fields_));
+            return *this;
+        }
+
+        /**
+         * Adds a constant value (also as default). Must be added exactly once.
+         *
+         * Const parameters by definition have no dependencies.
+         */
+        inline ParamBuilder &withConstValue(std::shared_ptr<T> default_) {
+            attrib() |= attrib_t::IS_CONST;
+            setSetter([default_](
+                    const C2Param *value, bool mayBlock __unused, bool *changed, Factory &) -> C2R {
+                *changed = false;
+                const T *typedValue = T::From(value);
+                if (typedValue == nullptr) {
+                    return C2R::Corrupted(); // TODO BadValue/Invalid. This should not happen here.
+                }
+                if (*typedValue != *default_) {
+                    return C2R::Corrupted(); // TODO ReadOnly(*default_);
+                }
+                *changed = false;
+                return C2R::Ok();
+            });
+            return withDefault(default_);
+        }
+
+        /** Adds constant value (also as default). Must be added exactly once. */
+        inline ParamBuilder &withConstValue(T *default_) {
+            return withConstValue(std::shared_ptr<T>(default_));
+        }
+
+        /**
+         * Use a strict setter.
+         *
+         * \param fn   strict setter
+         * \param deps dependencies (references)
+         */
+        template<typename ... Deps>
+        inline ParamBuilder &withSetter(
+                C2R (*fn)(bool, const C2P<T> &, C2P<T> &, const C2P<Deps> &...),
+                std::shared_ptr<Deps>& ... deps) {
+            attrib() |= attrib_t::IS_STRICT;
+            std::shared_ptr<T> *typedParam = mTypedParam;
+            setSetter([typedParam, fn, &deps...](
+                    const C2Param *value, bool mayBlock, bool *changed, Factory &factory) -> C2R {
+                *changed = false;
+                const T *typedValue = T::From(value);
+                if (typedValue == nullptr) {
+                    return C2R::Corrupted(); // TODO BadValue/Invalid. This should not happen here.
+                }
+                // Do copy-on-change for parameters in this helper so change can be detected by
+                // a change of the pointer. Do this by working on a proposed value.
+                std::shared_ptr<T> proposedValue =
+                    std::shared_ptr<T>(T::From(C2Param::Copy(*value).release()));
+                if (proposedValue == nullptr) {
+                    return C2R::NoMemory(value->index());
+                }
+                C2P<T> oldValue = factory.get(*typedParam);
+                // Get a parameter helper with value pointing to proposedValue
+                C2P<T> helper = factory.get(*typedParam, proposedValue);
+                C2R result = fn(mayBlock, oldValue, helper, factory.get(deps)...);
+
+                // If value changed, copy result to current value
+                if (helper.get() != *typedParam->get()) {
+                    *typedParam = proposedValue;
+                    *changed = true;
+                }
+                return result;
+            });
+            setDependencies(std::vector<C2Param::Index>{ deps->index()... },
+                            std::vector<ParamRef>{ ParamRef(deps)... });
+            return *this;
+        }
+
+        /**
+         * Use a non-strict setter.
+         *
+         * \param fn   non-strict setter
+         * \param deps dependencies (references)
+         */
+        template<typename ... Deps>
+        inline ParamBuilder &withSetter(
+                C2R (*fn)(bool, C2P<T> &, const C2P<Deps> &...), std::shared_ptr<Deps>& ... deps) {
+            std::shared_ptr<T> *typedParam = mTypedParam;
+            setSetter([typedParam, fn, &deps...](
+                    const C2Param *value, bool mayBlock, bool *changed, Factory &factory) -> C2R {
+                *changed = false;
+                const T *typedValue = T::From(value);
+                if (typedValue == nullptr) {
+                    return C2R::Corrupted(); // TODO BadValue/Invalid. This should not happen here.
+                }
+                // Do copy-on-change for parameters in this helper so change can be detected by
+                // a change of the pointer. Do this by working on a proposed value.
+                std::shared_ptr<T> proposedValue =
+                    std::shared_ptr<T>(T::From(C2Param::Copy(*value).release()));
+                if (proposedValue == nullptr) {
+                    return C2R::NoMemory(value->index());
+                }
+                // Get a parameter helper with value pointing to proposedValue
+                C2P<T> helper = factory.get(*typedParam, proposedValue);
+                C2R result = fn(mayBlock, helper, factory.get(deps)...);
+
+                // If value changed, copy result to current value
+                if (helper.get() != *typedParam->get()) {
+                    *typedParam = proposedValue;
+                    *changed = true;
+                }
+                return result;
+            });
+            setDependencies(std::vector<C2Param::Index>{ deps->index()... },
+                            std::vector<ParamRef>{ ParamRef(deps)... });
+            return *this;
+        }
+
+        /**
+         * Marks this a calculated (read-only) field.
+         *
+         * \param fn   non-strict setter (calculator)
+         * \param deps dependencies (references)
+         */
+        template<typename ... Deps>
+        inline ParamBuilder &calculatedAs(
+                C2R (*fn)(bool, C2P<T> &, const C2P<Deps> &...), std::shared_ptr<Deps>& ... deps) {
+            attrib() |= attrib_t::IS_READ_ONLY;
+            return withSetter(fn, std::forward<decltype(deps)>(deps)...);
+        }
+
+        inline std::shared_ptr<ParamHelper> build() {
+            return ParamHelper::build();
+        }
+
+    protected:
+        std::shared_ptr<T> *mTypedParam;
+    };
+
+    template<typename T>
+    static ParamBuilder<T> DefineParam(std::shared_ptr<T> &param, C2StringLiteral name) {
+        return ParamBuilder<T>(param, name);
+    }
+
+public:
+    c2_status_t query(
+            const std::vector<C2Param*> &stackParams,
+            const std::vector<C2Param::Index> &heapParamIndices,
+            c2_blocking_t mayBlock,
+            std::vector<std::unique_ptr<C2Param>>* const heapParams) const;
+
+    /**
+     * Helper implementing config calls as well as other configuration updates.
+     *
+     * This method is virtual, so implementations may provide wrappers around it (and perform
+     * actions just before and after a configuration).
+     *
+     * \param params
+     * \param mayBlock
+     * \param failures
+     * \param updateParams if true, the updated parameter values are copied back into the arguments
+     *                     passed in |params|
+     * \param changes      pointed to a vector to receive settings with their values changed. If not
+     *                     null, settings with their values changed are added to this.
+     * \return result from config
+     */
+    virtual c2_status_t config(
+            const std::vector<C2Param*> &params, c2_blocking_t mayBlock,
+            std::vector<std::unique_ptr<C2SettingResult>>* const failures,
+            bool updateParams = true,
+            std::vector<std::shared_ptr<C2Param>> *changes = nullptr);
+
+    c2_status_t querySupportedParams(
+            std::vector<std::shared_ptr<C2ParamDescriptor>> *const params) const;
+
+    c2_status_t querySupportedValues(
+            std::vector<C2FieldSupportedValuesQuery> &fields, c2_blocking_t mayBlock) const;
+
+    std::shared_ptr<C2ReflectorHelper> getReflector() {
+        return mReflector;
+    }
+
+    typedef std::unique_lock<std::mutex> Lock;
+
+    /**
+     * Locks the interface and returns a lock. This lock must be unlocked or released without
+     * calling any other blocking call.
+     */
+    Lock lock() const;
+
+private:
+    void setInterfaceAddressBounds(uintptr_t start, uintptr_t end) {
+        // TODO: exclude this helper
+        (void)start;
+        (void)end;
+    }
+
+protected:
+    mutable std::mutex mMutex;
+    std::shared_ptr<C2ReflectorHelper> mReflector;
+    struct FactoryImpl;
+    std::shared_ptr<FactoryImpl> _mFactory;
+
+    C2InterfaceHelper(std::shared_ptr<C2ReflectorHelper> reflector);
+
+    /**
+     * Adds a parameter to this interface.
+     * \note This method CHECKs.
+     *
+     * \param param parameter to add.
+     */
+    void addParameter(std::shared_ptr<ParamHelper> param);
+
+    /**
+     * Returns the dependency index for a parameter.
+     *
+     * \param ix the index of the parameter
+     */
+    size_t getDependencyIndex_l(C2Param::Index ix) const;
+
+    virtual ~C2InterfaceHelper() = default;
+
+    /**
+     * Sets subclass instance's address and size.
+     *
+     * \todo allow subclass to specify parameter address range directly (e.g. do not assume that
+     *       they are local to the subclass instance)
+     *
+     * \param T type of the derived instance
+     * \param instance pointer to the derived instance
+     */
+    template<typename T>
+    inline C2_HIDE void setDerivedInstance(T *instance) {
+        setInterfaceAddressBounds((uintptr_t)instance, (uintptr_t)(instance + 1));
+    }
+
+    C2_DO_NOT_COPY(C2InterfaceHelper);
+};
+
+/**
+ * Creates a C2ParamFieldValuesBuilder class for a field of a parameter
+ *
+ * \param spParam a configuration parameter in an interface class subclassed from C2InterfaceHelper.
+ * \param field   a field of such parameter
+ */
+#define C2F(spParam, field) \
+    C2ParamFieldValuesBuilder< \
+            typename _c2_reduce_enum_to_underlying_type< \
+                    typename std::remove_reference< \
+                            typename std::remove_extent< \
+                                    decltype(spParam->field)>::type>::type>::type>( \
+                                            C2ParamField(spParam.get(), &spParam->field))
+
+#endif  // C2UTILS_INTERFACE_HELPER_H_
diff --git a/media/codec2/vndk/include/util/C2InterfaceUtils.h b/media/codec2/vndk/include/util/C2InterfaceUtils.h
new file mode 100644
index 0000000..e9037e5
--- /dev/null
+++ b/media/codec2/vndk/include/util/C2InterfaceUtils.h
@@ -0,0 +1,1135 @@
+/*
+ * 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 C2UTILS_INTERFACE_UTILS_H_
+#define C2UTILS_INTERFACE_UTILS_H_
+
+#include <C2Param.h>
+#include <C2Work.h>
+
+#include <cmath>
+#include <iterator>
+#include <limits>
+#include <type_traits>
+
+/**
+ * Helper class to map underlying types to C2Value types as well as to print field values. This is
+ * generally the same as simply the underlying type except for characters (STRING) and bytes (BLOB).
+ */
+template<typename T>
+struct C2_HIDE _C2FieldValueHelper {
+    typedef T ValueType;
+    inline static std::ostream& put(std::ostream &os, const C2Value::Primitive &p) {
+        return os << p.ref<T>();
+    }
+};
+
+template<>
+struct C2_HIDE _C2FieldValueHelper<uint8_t> {
+    typedef uint32_t ValueType;
+    static std::ostream& put(std::ostream &os, const C2Value::Primitive &p);
+};
+
+template<>
+struct C2_HIDE _C2FieldValueHelper<char> {
+    typedef int32_t ValueType;
+    static std::ostream& put(std::ostream &os, const C2Value::Primitive &p);
+};
+
+/**
+ * Supported value range utility for a field of a given type.
+ *
+ * This mimics C2FieldSupportedValue for RANGE type.
+ */
+template<typename T>
+class C2SupportedRange {
+    typedef typename _C2FieldValueHelper<T>::ValueType ValueType;
+
+//private:
+    constexpr static T MIN_VALUE = std::numeric_limits<T>::min();
+    constexpr static T MAX_VALUE = std::numeric_limits<T>::max();
+    constexpr static T MIN_STEP = std::is_floating_point<T>::value ? 0 : 1;
+
+public:
+    /**
+     * Constructs an empty range with no supported values.
+     *
+     * \note This is a specializated supported range representation that is only used for
+     * this object - it is equivalent to the EMPTY type in C2FieldSupportedValues.
+     */
+    inline static constexpr C2SupportedRange<T> None() {
+        return C2SupportedRange(MAX_VALUE, MIN_VALUE);
+    }
+
+    /**
+     * Constructs a range with all values supported.
+     */
+    inline static constexpr C2SupportedRange<T> Any() {
+        return C2SupportedRange(MIN_VALUE, MAX_VALUE);
+    }
+
+    /**
+     * Constructs a range with a single supported value.
+     *
+     * \param value the sole supported value
+     */
+    inline static constexpr C2SupportedRange<T> EqualTo(T value) {
+        return C2SupportedRange(value, value);
+    }
+
+    /**
+     * Constructs a range with supported values greater than a given value.
+     *
+     * \param value the given value
+     */
+    inline static C2SupportedRange<T> GreaterThan(T value) {
+        return (value == MAX_VALUE ? None() :
+                std::is_floating_point<T>::value ?
+                        C2SupportedRange(std::nextafter(value, MAX_VALUE), MAX_VALUE) :
+                        C2SupportedRange(value + MIN_STEP, MAX_VALUE));
+    }
+
+    /**
+     * Constructs a range with supported values greater than or equal to a given value.
+     *
+     * \param value the given value
+     */
+    inline static constexpr C2SupportedRange<T> GreaterThanOrEqualTo(T value) {
+        return C2SupportedRange(value, MAX_VALUE);
+    }
+
+    /**
+     * Constructs a range with supported values greater than or equal to (aka not less than) a given
+     * value.
+     *
+     * \param value the given value
+     */
+    inline static constexpr C2SupportedRange<T> NotLessThan(T value) {
+        return GreaterThanOrEqualTo(value);
+    }
+
+    /**
+     * Constructs a range with supported values less than or equal to a given value.
+     *
+     * \param value the given value
+     */
+    inline static constexpr C2SupportedRange<T> LessThanOrEqualTo(T value) {
+        return C2SupportedRange(MIN_VALUE, value);
+    }
+
+    /**
+     * Constructs a range with supported values less than or equal to (aka not greater than) a given
+     * value.
+     *
+     * \param value the given value
+     */
+    inline static constexpr C2SupportedRange<T> NotGreaterThan(T value) {
+        return LessThanOrEqualTo(value);
+    }
+
+    /**
+     * Constructs a range with supported values less than a given value.
+     *
+     * \param value the given value
+     */
+    inline static C2SupportedRange<T> LessThan(T value) {
+        return (value == MIN_VALUE ? None() :
+                std::is_floating_point<T>::value ?
+                        C2SupportedRange(MIN_VALUE, std::nextafter(value, MIN_VALUE)) :
+                        C2SupportedRange(MIN_VALUE, value - MIN_STEP));
+    }
+
+    /**
+     * Constructs a continuous or arithmetic range between two values.
+     *
+     * \param min the lower value
+     * \param max the higher value (if this is lower than |min| the range will be empty)
+     * \param step the step of the arithmetic range. (If this is 0 for floating point types or 1 for
+     *        integer types, the constructed range is continuous)
+     */
+    inline static constexpr
+    C2SupportedRange<T> InRange(T min, T max, T step = MIN_STEP) {
+        return C2SupportedRange(min, max, step);
+    }
+
+    /**
+     * Constructs a range over a geometric series between two values.
+     *
+     * \param min the lower bound of the range. This value is always part of the constructed range
+     *        as long as it is not greater than |max|.
+     * \param max the upper bound of the range. This value is only part of the constructed
+     *        range if it is part of the geometric series.
+     * \param num the numerator of the geometric series.
+     * \param denom the denominator of the geometric series.
+     */
+    inline static constexpr
+    C2SupportedRange<T> InSeries(T min, T max, T num, T denom) {
+        return C2SupportedRange(min, max, 0, num, denom);
+    }
+
+    /**
+     * Constructs a range over a multiply-accumulate series between two values.
+     *
+     * \param min the lower bound of the range. This value is always part of the constructed range
+     *        as long as it is not greater than |max|.
+     * \param max the upper bound of the range. This value is only part of the constructed
+     *        range if it is part of the series.
+     * \param step the accumulator of the multiply-accumulate series
+     * \param num the numerator of the multiply-accumulate series.
+     * \param denom the denominator of the multiply-accumulate series.
+     */
+    inline static constexpr
+    C2SupportedRange<T> InMacSeries(T min, T max, T step, T num, T denom) {
+        return C2SupportedRange(min, max, step, num, denom);
+    }
+
+    /**
+     * Constructs a range from a generic C2FieldSupportedValues object. This will be an empty
+     * range if the supported values are not of RANGE type.
+     *
+     * \param values the supported values object
+     */
+    C2SupportedRange(const C2FieldSupportedValues &values);
+
+    /**
+     * Returns whether this range is empty.
+     */
+    inline constexpr bool isEmpty() const {
+        return _mMin > _mMax;
+    }
+
+    /**
+     * Returns whether this range is valid.
+     *
+     * Ranges are valid if they are continuous or monotonic.
+     */
+    inline constexpr bool isValid() const {
+        // TODO: handle overflow or negative series
+        return _mDenom > 0 && _mNum >= _mDenom && _mMin * (_mDenom - _mNum) < _mStep * _mDenom;
+    }
+
+    /**
+     * Returns whether a value is part of this range.
+     *
+     * \param value the value to check.
+     */
+    bool contains(T value) const;
+
+    /**
+     * Returns a new range that is the intersection of this range and another, if it is
+     * representable as a range object.
+     *
+     * \param limit the other range
+     */
+    C2SupportedRange<T> limitedTo(const C2SupportedRange<T> &limit) const;
+
+    /**
+     * Converts this object to a C2FieldSupportedValues object.
+     */
+    inline operator C2FieldSupportedValues() const {
+        return C2FieldSupportedValues(_mMin, _mMax, _mStep, _mNum, _mDenom);
+    }
+
+    /**
+     * Returns the lower bound and starting point of this range.
+     */
+    inline C2_HIDE constexpr T min() const   { return _mMin;   }
+
+    /**
+     * Returns the upper bound of this range.
+     */
+    inline C2_HIDE constexpr T max() const   { return _mMax;   }
+
+    /**
+     * Returns the step of this range.
+     */
+    inline C2_HIDE constexpr T step() const  { return _mStep;  }
+
+    /**
+     * Returns the numerator of this range.
+     */
+    inline C2_HIDE constexpr T num() const   { return _mNum;   }
+
+    /**
+     * Returns the denominator of this range.
+     */
+    inline C2_HIDE constexpr T denom() const { return _mDenom; }
+
+private:
+    /**
+     * Returns whether x[i...] is all values between _mMin and _mMax.
+     */
+    inline C2_HIDE constexpr bool isSimpleRange() const {
+        return _mStep == MIN_STEP && _mNum == 1 && _mDenom == 1;
+    }
+
+    /**
+     * Returns whether x[i...] is defined as such:
+     * x[i + 1] = x[i] + _mStep, where _mStep > 0 and _mMin <= x[i] <= _mMax
+     */
+    inline C2_HIDE constexpr bool isArithmeticSeries() const {
+        return _mStep > MIN_STEP && _mNum == 1 && _mDenom == 1;
+    }
+
+    /**
+     * Returns whether x[i...] is defined as such:
+     * x[i] = x[0] * (_mNum / _mDenom) ^ i (with rounding), where _mNum > _mDenom > 0 and x[0] > 0
+     */
+    inline C2_HIDE constexpr bool isGeometricSeries() const {
+        return _mMin > 0 && _mStep == 0 && _mNum > _mDenom && _mDenom > 0;
+    }
+
+    /**
+     * Returns whether x[i...] is defined as such:
+     * x[i + 1] = x[i] * _mNum / _mDenom + _mStep (with rounding), while x[i + 1] > x[i], where
+     * _mStep != 0, _mDenom > 0 and _mNum > 0
+     */
+    inline C2_HIDE constexpr bool isMacSeries() const {
+        return _mStep != 0 && _mNum > 0 && _mDenom > 0;
+    }
+
+    /**
+     * Constructs an arithmetic or continuous range.
+     *
+     * \param min the lower value
+     * \param max the higher value (if this is lower than |min| the range will be empty)
+     * \param step the step of the arithmetic range. (If this is 0 for floating point types or 1 for
+     *        integer types, the constructed range is continuous)
+     */
+    constexpr C2_HIDE C2SupportedRange(T min, T max, T step = T(std::is_floating_point<T>::value ? 0 : 1))
+        : _mMin(min), _mMax(max), _mStep(step), _mNum(1), _mDenom(1) { }
+
+    /**
+     * Constructs a range over a geomertic sor multiply-accumulate series.
+     *
+     * \param min the lower bound of the range. This value is always part of the constructed range
+     *        as long as it is not greater than |max|.
+     * \param max the upper bound of the range. This value is only part of the constructed
+     *        range if it is part of the geometric series.
+     * \param step the accumulator of the multiply-accumulate series. This is 0 for a pure geometric
+     *        series
+     * \param num the numerator of the geometric series.
+     * \param denom the denominator of the geometric series.
+     */
+    constexpr C2_HIDE C2SupportedRange(T min, T max, T step, T num, T den)
+        : _mMin(min), _mMax(max), _mStep(step), _mNum(num), _mDenom(den) { }
+
+    T _mMin; ///< lower bound and starting point
+    T _mMax; ///< upper bound
+    T _mStep; ///< step of an arithmetic series (0 if continuous floating point range)
+    T _mNum; ///< numerator of a geometric series
+    T _mDenom; ///< denominator of a geometric series
+};
+
+/**
+ * Ordered supported flag set for a field of a given type.
+ */
+template<typename T>
+class C2SupportedFlags {
+    typedef typename _C2FieldValueHelper<T>::ValueType ValueType;
+
+public:
+    /**
+     * Constructs an empty flag set.
+     *
+     * \note This is a specializated supported flags representation that is only used for
+     * this object - it is equivalent to the EMPTY type in C2FieldSupportedValues.
+     */
+    static inline C2SupportedFlags<T> None() {
+        return C2SupportedFlags(std::initializer_list<C2Value::Primitive>());
+    }
+
+    /**
+     * Constructs a flags set of given flags.
+     *
+     * \param flags the ordered set of flags as an initializer list.
+     * \param min minimum set of flags to be set.
+     */
+    static inline C2SupportedFlags<T> Flags(const std::initializer_list<T> flags, T min = T(0)) {
+        return C2SupportedFlags(min, flags);
+    }
+
+    /**
+     * Constructs a flags set of given flags.
+     *
+     * \param flags the ordered set of flags.
+     * \param min minimum set of flags to be set.
+     */
+    static inline C2SupportedFlags<T> Flags(const std::vector<T> &flags, T min = T(0)) {
+        return C2SupportedFlags(min, flags);
+    }
+
+    /**
+     * Constructs a flag set from a generic C2FieldSupportedValues object. This will be an empty
+     * set if the supported values are not of FLAGS type.
+     *
+     * \param values the supported values object
+     */
+    C2SupportedFlags<T>(const C2FieldSupportedValues &values) {
+        if (values.type == C2FieldSupportedValues::FLAGS) {
+            _mValues.insert(_mValues.end(), values.values.begin(), values.values.end());
+        }
+    }
+
+    /**
+     * Returns whether this set is empty.
+     */
+    constexpr bool isEmpty() const {
+        return _mValues.empty();
+    }
+
+    /**
+     * Returns whether a value is part of this set.
+     *
+     * \param value the value to check.
+     */
+    bool contains(T value) const;
+
+    /**
+     * Returns a new flag set that is the intersection of this set and another.
+     *
+     * \param limit the other value set
+     */
+    C2SupportedFlags<T> limitedTo(const C2SupportedFlags<T> &limit) const;
+
+    /**
+     * Converts this object to a C2FieldSupportedValues object.
+     */
+    operator C2FieldSupportedValues() const {
+        return C2FieldSupportedValues(!isEmpty() /* flags */, _mValues);
+    }
+
+    /**
+     * Returns the ordered set of flags of this object.
+     */
+    const std::vector<T> flags() const;
+
+    /**
+     * Returns the minimum set of flags for this object.
+     */
+    T min() const;
+
+    /**
+     * Clears this supported value set.
+     */
+    inline void clear() {
+        _mValues.clear();
+    }
+
+private:
+    /**
+     * Constructs a flag set directly from an internal representation.
+     *
+     * \param values a vector containing the minimum flag set followed by the set of flags
+     */
+    C2SupportedFlags(std::vector<C2Value::Primitive> &&values)
+        : _mValues(values) {
+    }
+
+    /**
+     * Constructs a flag set from a set of flags and a minimum flag set.
+     *
+     * \param flags the set
+     */
+    C2SupportedFlags(T min, const std::vector<T> &flags) {
+        _mValues.emplace_back(min);
+        for (T elem : flags) {
+            _mValues.emplace_back(elem);
+        }
+    }
+
+    /**
+     * Constructs a flag set from a set of initializer list values and a minimum flag set
+     *
+     * \param flags the set
+     */
+    C2SupportedFlags(T min, const std::initializer_list<T> flags) {
+        _mValues.emplace_back(min);
+        for (T elem : flags) {
+            _mValues.emplace_back(elem);
+        }
+    }
+
+    std::vector<C2Value::Primitive> _mValues; ///< the minimum flag set followed by the set of flags
+};
+
+/**
+ * Ordered supported value set for a field of a given type.
+ */
+template<typename T>
+class C2SupportedValueSet {
+    typedef typename _C2FieldValueHelper<T>::ValueType ValueType;
+
+public:
+    /**
+     * Constructs an empty value set.
+     *
+     * \note This is a specializated supported range representation that is only used for
+     * this object - it is equivalent to the EMPTY type in C2FieldSupportedValues.
+     */
+    static inline C2SupportedValueSet<T> None() {
+        return C2SupportedValueSet({ });
+    }
+
+    /**
+     * Constructs a value set of given values.
+     *
+     * \param values the ordered set of values as an initializer list.
+     */
+    static inline C2SupportedValueSet<T> OneOf(const std::initializer_list<T> values) {
+        return C2SupportedValueSet(values);
+    }
+
+    /**
+     * Constructs a value set of given values.
+     *
+     * \param values the ordered set of values.
+     */
+    static inline C2SupportedValueSet<T> OneOf(const std::vector<T> &values) {
+        return C2SupportedValueSet(values);
+    }
+
+    /**
+     * Constructs a value set from a generic C2FieldSupportedValues object. This will be an empty
+     * set if the supported values are not of VALUES type.
+     *
+     * \param values the supported values object
+     */
+    C2SupportedValueSet<T>(const C2FieldSupportedValues &values) {
+        if (values.type == C2FieldSupportedValues::VALUES) {
+            _mValues.insert(_mValues.end(), values.values.begin(), values.values.end());
+        }
+    }
+
+    /**
+     * Returns whether this range is empty.
+     */
+    constexpr bool isEmpty() const {
+        return _mValues.empty();
+    }
+
+    /**
+     * Returns whether a value is part of this set.
+     *
+     * \param value the value to check.
+     */
+    bool contains(T value) const;
+
+    /**
+     * Returns a new value set that is the intersection of this set and another.
+     *
+     * \param limit the other value set
+     */
+    C2SupportedValueSet<T> limitedTo(const C2SupportedValueSet<T> &limit) const;
+
+    /**
+     * Returns a new value set that is the intersection of this set and a value range.
+     *
+     * \param limit the other range
+     */
+    C2SupportedValueSet<T> limitedTo(const C2SupportedRange<T> &limit) const;
+
+    /**
+     * Returns a new value set that is the intersection of this set and a flag set.
+     *
+     * \param limit the other flag set
+     */
+    C2SupportedValueSet<T> limitedTo(const C2SupportedFlags<T> &limit) const;
+
+    /**
+     * Converts this object to a C2FieldSupportedValues object.
+     */
+    operator C2FieldSupportedValues() const {
+        return C2FieldSupportedValues(false /* flags */, _mValues);
+    }
+
+    /**
+     * Returns the ordered set of values of this object.
+     */
+    const std::vector<T> values() const;
+
+    /**
+     * Clears this supported value set.
+     */
+    inline void clear() {
+        _mValues.clear();
+    }
+
+private:
+    /**
+     * Constructs a value set from a set of C2Value::Primitive values.
+     *
+     * \param values the set
+     */
+    C2SupportedValueSet(std::vector<C2Value::Primitive> &&values)
+        : _mValues(values) {
+    }
+
+    /**
+     * Constructs a value set from a set of values.
+     *
+     * \param values the set
+     */
+    C2SupportedValueSet(const std::vector<T> &values) {
+        for (T elem : values) {
+            _mValues.emplace_back(elem);
+        }
+    }
+
+    /**
+     * Constructs a value set from a set of initializer list values
+     *
+     * \param values the set
+     */
+    C2SupportedValueSet(const std::initializer_list<T> values) {
+        for (T elem : values) {
+            _mValues.emplace_back(elem);
+        }
+    }
+
+    std::vector<C2Value::Primitive> _mValues; ///< the supported set of values
+};
+
+/**
+ * Helper class to handle C2FieldSupporteValues object for fields of various types.
+ */
+template<typename T>
+class C2FieldSupportedValuesHelper;
+
+// templated operator must be predeclared for friend declaration
+template<typename T>
+std::ostream& operator<<(std::ostream& os, const C2FieldSupportedValuesHelper<T> &i);
+
+template<typename T>
+class C2FieldSupportedValuesHelper {
+public:
+    /**
+     * Creates a helper for a specific type from a generic C2FieldSupportedValues struct.
+     */
+    C2FieldSupportedValuesHelper(const C2FieldSupportedValues &values);
+
+    // TRICKY: needed for std::unique_ptr<Impl> declaration
+    ~C2FieldSupportedValuesHelper();
+
+    // support copy constructor/operator
+    C2FieldSupportedValuesHelper(const C2FieldSupportedValuesHelper &);
+    C2FieldSupportedValuesHelper& operator=(const C2FieldSupportedValuesHelper &);
+
+    bool supports(T value) const;
+
+private:
+    // use pimpl as implementation may change in the future
+    struct Impl;
+    std::unique_ptr<Impl> _mImpl;
+
+    friend std::ostream& operator<< <T>(std::ostream& os, const C2FieldSupportedValuesHelper<T> &i);
+    //friend std::ostream& operator<<(std::ostream& os, const C2FieldSupportedValuesHelper &i);
+};
+
+/**
+ * Builder for supported values for a field of a given type.
+ *
+ * This builder can be used to successively restrict the supported values for a field. Upon
+ * creation, there are no supported values specified - which for this builder means that all
+ * values are supported.
+ */
+template<typename T>
+class C2ParamFieldValuesBuilder {
+public:
+    /**
+     * Creates a builder with no defined values - but implicitly any value allowed.
+     */
+    C2ParamFieldValuesBuilder(const C2ParamField &field);
+
+    /**
+     * Get C2ParamFieldValues from this builder.
+     */
+    operator C2ParamFieldValues() const;
+
+    /**
+     * Define the supported values as the currently supported values of this builder.
+     */
+    C2ParamFieldValuesBuilder<T> &any();
+
+    /**
+     * Restrict (and thus define) the supported values to none.
+     *
+     * \note This really should not be used from the builder as all params must have supported
+     *       values, but is here in case this is really the case.
+     */
+    C2ParamFieldValuesBuilder<T> &none();
+
+    /**
+     * Restrict (and thus define) the supported values to |value| alone.
+     */
+    C2ParamFieldValuesBuilder<T> &equalTo(T value);
+
+    /**
+     * Restrict (and thus define) the supported values to values greater than |value|.
+     */
+    inline C2ParamFieldValuesBuilder<T> &greaterThan(T value) {
+        return limitTo(C2SupportedRange<T>::GreaterThan(value));
+    }
+
+    /**
+     * Restrict (and thus define) the supported values to values greater than or equal to |value|.
+     */
+    C2ParamFieldValuesBuilder<T> &greaterThanOrEqualTo(T value) {
+        return limitTo(C2SupportedRange<T>::GreaterThanOrEqualTo(value));
+    }
+
+    /**
+     * Restrict (and thus define) the supported values to values greater than or equal to |value|.
+     */
+    C2ParamFieldValuesBuilder<T> &notLessThan(T value) {
+        return limitTo(C2SupportedRange<T>::NotLessThan(value));
+    }
+
+    /**
+     * Restrict (and thus define) the supported values to values less than or equal to |value|.
+     */
+    C2ParamFieldValuesBuilder<T> &lessThanOrEqualTo(T value) {
+        return limitTo(C2SupportedRange<T>::LessThanOrEqualTo(value));
+    }
+
+    /**
+     * Restrict (and thus define) the supported values to values less than or equal to |value|.
+     */
+    C2ParamFieldValuesBuilder<T> &notGreaterThan(T value) {
+        return limitTo(C2SupportedRange<T>::NotGreaterThan(value));
+    }
+
+    /**
+     * Restrict (and thus define) the supported values to values less than |value|.
+     */
+    C2ParamFieldValuesBuilder<T> &lessThan(T value) {
+        return limitTo(C2SupportedRange<T>::LessThan(value));
+    }
+
+    /**
+     * Restrict (and thus define) the supported values to values in the range of [ |min|, |max| ]
+     * with optional |step|.
+     */
+    C2ParamFieldValuesBuilder<T> &inRange(
+            T min, T max, T step = std::is_floating_point<T>::value ? T(0) : T(1))  {
+        return limitTo(C2SupportedRange<T>::InRange(min, max, step));
+    }
+
+    /**
+     * Restrict (and thus define) the supported values to values in the geometric series starting
+     * from |min| with factor |num| / |denom|, not greater than |max|.
+     */
+    C2ParamFieldValuesBuilder<T> &inSeries(T min, T max, T num, T denom) {
+        return limitTo(C2SupportedRange<T>::InSeries(min, max, num, denom));
+    }
+
+    /**
+     * Restrict (and thus define) the supported values to values in the multiply-accumulate series
+     * starting from |min| with factor |num| / |denom| and |step|, not greater than |max|.
+     */
+    C2ParamFieldValuesBuilder<T> &inMacSeries(T min, T max, T step, T num, T denom) {
+        return limitTo(C2SupportedRange<T>::InMacSeries(min, max, step, num, denom));
+    }
+
+    /**
+     * Restrict (and thus define) the supported values to values in |values|.
+     */
+    C2ParamFieldValuesBuilder<T> &oneOf(const std::initializer_list<T> values) {
+        return limitTo(C2SupportedValueSet<T>::OneOf(values));
+    }
+
+    /**
+     * Restrict (and thus define) the supported values to values in |values|.
+     */
+    C2ParamFieldValuesBuilder<T> &oneOf(const std::vector<T> &values) {
+        return limitTo(C2SupportedValueSet<T>::OneOf(values));
+    }
+
+    /**
+     * Restrict (and thus define) the supported values to flags in |flags| with at least |min|
+     * set.
+     */
+    C2ParamFieldValuesBuilder<T> &flags(const std::vector<T> &flags, T min = T(0)) {
+        return limitTo(C2SupportedFlags<T>::Flags(flags, min));
+    }
+
+    /**
+     * Restrict (and thus define) the supported values to flags in |values| with at least |min|
+     * set.
+     */
+    C2ParamFieldValuesBuilder<T> &flags(const std::initializer_list<T> flags, T min = T(0)) {
+        return limitTo(C2SupportedFlags<T>::Flags(flags, min));
+    }
+
+    virtual ~C2ParamFieldValuesBuilder();
+
+    // support copy constructor/operator
+    C2ParamFieldValuesBuilder(const C2ParamFieldValuesBuilder &);
+    C2ParamFieldValuesBuilder& operator=(const C2ParamFieldValuesBuilder &);
+
+private:
+    /**
+     * Restrict (and thus define) the supported values to a value set.
+     */
+    C2ParamFieldValuesBuilder<T> &limitTo(const C2SupportedValueSet<T> &limit);
+
+    /**
+     * Restrict (and thus define) the supported values to a value set.
+     */
+    C2ParamFieldValuesBuilder<T> &limitTo(const C2SupportedFlags<T> &limit);
+
+    /**
+     * Restrict (and thus define) the supported values to a range.
+     */
+    C2ParamFieldValuesBuilder<T> &limitTo(const C2SupportedRange<T> &limit);
+
+    struct Impl;
+    std::unique_ptr<Impl> _mImpl;
+};
+
+/**
+ * Builder for a list of setting conflicts.
+ */
+class C2SettingConflictsBuilder {
+public:
+    /**
+     * Creates an empty list of setting conflicts.
+     */
+    C2SettingConflictsBuilder();
+
+    /**
+     * Creates a list containing a single setting conflict.
+     */
+    C2SettingConflictsBuilder(C2ParamFieldValues &&conflict);
+
+    /**
+     * Adds a conflict to the current list of conflicts and returns this
+     */
+    C2SettingConflictsBuilder& with(C2ParamFieldValues &&conflict);
+
+    /**
+     * Gets the current list of conflicts (and moves them out of this builder.)
+     * (this is why it is not const)
+     */
+    std::vector<C2ParamFieldValues> retrieveConflicts();
+
+    /**
+     * Returns whether the current list is empty.
+     */
+    inline bool empty() const { return _mConflicts.empty(); }
+
+    inline operator bool() const { return empty(); }
+
+private:
+    std::vector<C2ParamFieldValues> _mConflicts;
+};
+
+/**
+ * Setting result builder for a parameter.
+ */
+struct C2SettingResultBuilder {
+    /**
+     * Creates a read-only setting result failure.
+     *
+     * This does not take FSV as only the current value of the field is supported.
+     */
+    static C2SettingResult ReadOnly(const C2ParamField &param);
+
+    /**
+     * Creates a bad-value or infoinformational bad-value setting result failure.
+     *
+     * This does not take FSV as the value is outside of the possible values. As such, there are no
+     * conflicts for this case either.
+     */
+    static C2SettingResult BadValue(const C2ParamField &paramField, bool isInfo = false);
+
+    /**
+     * Creates a conflict (or informational conflict) setting result failure.
+     *
+     * This takes FSV so use paramFieldValues and optional conflicts.
+     */
+    static C2SettingResult Conflict(
+            C2ParamFieldValues &&paramFieldValues, C2SettingConflictsBuilder &conflicts,
+            bool isInfo = false);
+
+    // TODO: retrieve results
+
+
+private:
+    C2ParamField _mParamField;
+    C2SettingResult _mResult;
+
+    C2SettingResultBuilder(const C2SettingResultBuilder &) = delete;
+};
+
+/**
+ * Setting results (PLURAL) builder.
+ *
+ * Setting results contain a failure status along with a list of failing fields or params.
+ */
+struct C2SettingResultsBuilder {
+    C2SettingResultsBuilder(const C2SettingResultsBuilder&) = delete;
+    C2SettingResultsBuilder(C2SettingResultsBuilder&&) = default;
+    C2SettingResultsBuilder &operator=(C2SettingResultsBuilder&&) = default;
+
+    /** \returns (default) successful result with no details. */
+    inline static C2SettingResultsBuilder Ok() {
+        return C2SettingResultsBuilder(C2_OK);
+    }
+
+    /** \returns Interface is in bad state, with no further details. */
+    inline static C2SettingResultsBuilder BadState() {
+        return C2SettingResultsBuilder(C2_BAD_STATE);
+    }
+
+    /** \returns Interface connection timed out, with no further details. */
+    inline static C2SettingResultsBuilder TimedOut() {
+        return C2SettingResultsBuilder(C2_TIMED_OUT);
+    }
+
+    /** \returns Interface connection is corrupted, with no further details. */
+    inline static C2SettingResultsBuilder Corrupted() {
+        return C2SettingResultsBuilder(C2_CORRUPTED);
+    }
+
+    inline static C2SettingResultsBuilder NoMemory(C2Param::Index index_ __unused) {
+        // TODO: try to add failure result
+        return C2SettingResultsBuilder(C2_NO_MEMORY);
+    }
+
+    // TODO: this should not be a constructor
+    /** Creates a builder with a single bad value setting result. */
+    C2SettingResultsBuilder(C2SettingResult &&result);
+
+    /** Combines this results with other results. */
+    C2SettingResultsBuilder plus(C2SettingResultsBuilder&& results);
+
+    /** Retrieve (get and move out) failures and return the failure status. */
+    c2_status_t retrieveFailures(std::vector<std::unique_ptr<C2SettingResult>>* const failures);
+
+private:
+    /** Setting results based on a single status. This is used when actual setting could not be
+     *  attempted to get a single C2SettingResult, or when a setting succeeded without
+     *  'complaints'. */
+    C2SettingResultsBuilder(c2_status_t status);
+        // status must be one of OK, BAD_STATE, TIMED_OUT, CORRUPTED or NO_MEMORY
+        // mainly: BLOCKING, BAD_INDEX, BAD_VALUE and NO_MEMORY requires a setting attempt, but
+        // NO_MEMORY may not allow us to create a results structure.
+
+    /**
+     * One of OK, BAD_INDEX, BAD_VALUE, BAD_STATE, NO_MEMORY, TIMED_OUT, BLOCKING or CORRUPTED.
+     */
+    c2_status_t _mStatus __unused;
+
+    /**
+     * Vector of individual setting result details.
+     */
+    std::vector<std::unique_ptr<C2SettingResult>> _mResults;
+};
+
+/**
+ * Utility class to enumerate fields of parameters.
+ */
+struct C2FieldUtils {
+    struct _Inspector;
+
+    /**
+     * An extended field descriptor object with structural information (lineage back to the root of
+     * the param).
+     */
+    struct Info {
+        typedef C2FieldDescriptor::type_t type_t; ///< field type
+        typedef C2FieldDescriptor::NamedValuesType NamedValuesType; ///< named values list type
+
+        /// returns the name of the field
+        C2String name() const;
+
+        /// returns the type of this field
+        type_t type() const;
+
+        /**
+         * Returns the defined name-value pairings for this field. The returned reference is
+         * only valid during the validity of this object
+         */
+        const NamedValuesType &namedValues() const;
+
+        /**
+         * The index of this field. E.g. param.field or param.field[0] has an index of 0, and
+         * param.struct[2].field[3] has an index of 3.
+         */
+        size_t index() const;
+
+        /// returns the length of the field in case it is an array. Returns 0 for
+        /// T[] arrays if this info comes from a C2Param::Index object, and the currently used
+        /// extent if it comes from a C2Param object. Returns 1 for T[1] arrays as well as if the
+        /// field is not an array.
+        size_t extent() const;
+
+        /**
+         * The (structural) depth of this field. E.g. param.field or param.field[0] has a depth of
+         *  0, and param.struct.field or param.struct[0].field[0] has a depth of 1.
+         */
+        size_t depth() const;
+
+        /**
+         * Returns the offset of this field in the parameter in bytes.
+         */
+        size_t offset() const;
+
+        /**
+         * Returns the size of this field in bytes.
+         */
+        size_t size() const;
+
+        /**
+         * The offset of this field's array. E.g. for param.struct[2].field[3] this is the offset
+         * of its smallest sibling: param.struct[2].field[0].
+         */
+        size_t arrayOffset() const;
+
+        /**
+         * Returns the size of this field's array. This is equivalent to extent() * size()
+         */
+        size_t arraySize() const;
+
+        /**
+         * The offset of the base field. The base field is a cousin of the current field where
+         * all indices are 0. E.g. the the base field for param.struct[2].field[3] is
+         * param.struct[0].field[0]. Base fields are used to specify supported values for
+         * all cousin fields.
+         */
+        size_t baseFieldOffset() const;
+
+        /**
+         * Returns whether this field is an arithmetic (integral, counter or float) field.
+         */
+        bool isArithmetic() const;
+
+        /**
+         * Returns whether this field can have a flexible extent. extent() returns the current
+         * extent.
+         */
+        bool isFlexible() const;
+
+        /// returns whether this info is valid
+        inline bool isValid() const { return _mImpl != nullptr; }
+
+        /// returns the info for the parent of this field, or an invalid Info object if it has no
+        /// parents
+        Info parent() const;
+
+        /// returns whether this info is valid
+        inline operator bool() const { return isValid(); }
+
+        struct Impl;
+        Info(std::shared_ptr<Impl>);
+
+    private:
+        std::shared_ptr<Impl> _mImpl;
+        friend struct _Inspector;
+    };
+
+    /**
+     * An (input) iterator object over fields using Info objects.
+     */
+    struct Iterator {
+        typedef Info const value_type;
+        typedef ptrdiff_t difference_type;
+        typedef Info const * pointer;
+        typedef Info const reference;
+        typedef std::input_iterator_tag iterator_category;
+
+        /// return Info at current position
+        virtual reference operator*() const;
+
+        /// move to the next field
+        virtual Iterator& operator++();
+
+        virtual bool operator==(const Iterator &) const;
+        inline bool operator!=(const Iterator &other) const { return !operator==(other); }
+
+        virtual ~Iterator() = default;
+
+        struct Impl;
+        Iterator(std::shared_ptr<Impl>);
+
+    protected:
+        std::shared_ptr<Impl> mImpl;
+    };
+
+    /**
+     * An (input) iterable object representing a list of fields.
+     */
+    struct List {
+        /// returns an iterator to the beginning of the list
+        virtual Iterator begin() const;
+
+        /// returns an iterator to the end of the list
+        virtual Iterator end() const;
+
+        virtual ~List() = default;
+
+        struct Impl;
+        List(std::shared_ptr<Impl>);
+
+    protected:
+        std::shared_ptr<Impl> mImpl;
+    };
+
+    /**
+     * Enumerates all (base) fields at index 0 of the parameter. The order of iteration is the
+     * following:
+     *   Fields of a structure are enumerated in field order. However, sub-fields of a structure
+     *   are enumerated directly after the structure field, and prior to sibling fields.
+     *
+     * In essence the order of enumeration is first by increasing offset, then by decreasing size.
+     *
+     * \param param parameter to enumerate its fields
+     * \param reflector parameter reflector used for enumeration
+     *
+     * \return an iterable object
+     */
+    static List enumerateFields(
+            const C2Param &param,
+            const std::shared_ptr<C2ParamReflector> &reflector);
+
+    /**
+     * Enumerates all cousin fields up to depth - level for a field. If level is 0, it enumerates
+     * only the field. For level 1, it enumerates all fields in its current array (which may be
+     * itself if extent is 1). The order of iteration is by increasing field offset.
+     */
+    static List enumerateCousins(
+            const Info &field,
+            uint32_t level = ~0);
+
+    /**
+     * Locates the field in a parameter and returns a list of 2 elements - the most-specific field
+     * array of the parameter that contains the entire field. If the field is not a valid field
+     * specifier for this parameter (e.g. it is outside the bounds of the parameter), it returns
+     * an empty list.
+     */
+    static std::vector<Info> locateField(
+            const C2Param &param, const _C2FieldId &field,
+            const std::shared_ptr<C2ParamReflector> &reflector);
+
+    static std::vector<Info> locateField(
+            const C2ParamField &pf, const std::shared_ptr<C2ParamReflector> &reflector);
+
+};
+
+#include <util/C2Debug-interface.h>
+
+#endif  // C2UTILS_INTERFACE_UTILS_H_
diff --git a/media/codec2/vndk/include/util/C2ParamUtils.h b/media/codec2/vndk/include/util/C2ParamUtils.h
new file mode 100644
index 0000000..b51bd94
--- /dev/null
+++ b/media/codec2/vndk/include/util/C2ParamUtils.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2016 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 C2UTILS_PARAM_UTILS_H_
+#define C2UTILS_PARAM_UTILS_H_
+
+#include <utility>
+#include <vector>
+
+/** \file
+ * Utilities for parameter handling to be used by Codec2 implementations.
+ */
+
+/// \cond INTERNAL
+
+struct C2Param;
+
+class C2ParamUtils {
+    friend class C2UtilTest_ParamUtilsTest_Test;
+
+public:
+
+    /// safe(r) parsing from parameter blob
+    static
+    C2Param *ParseFirst(const uint8_t *blob, size_t size);
+};
+
+/// \endcond
+
+#endif  // C2UTILS_PARAM_UTILS_H_
+