Merge "ServiceStateEvents don't need to called with the mServiceState lock anymore."
diff --git a/media/libaudioprocessing/AudioMixer.cpp b/media/libaudioprocessing/AudioMixer.cpp
index 238925d..3e72c89 100644
--- a/media/libaudioprocessing/AudioMixer.cpp
+++ b/media/libaudioprocessing/AudioMixer.cpp
@@ -813,7 +813,7 @@
                 mMixerInFormat, sampleRate, playbackRate);
         reconfigureBufferProviders();
     } else {
-        reinterpret_cast<TimestretchBufferProvider*>(mTimestretchBufferProvider)
+        static_cast<TimestretchBufferProvider*>(mTimestretchBufferProvider)
                 ->setPlaybackRate(playbackRate);
     }
     return true;
diff --git a/media/libstagefright/Android.bp b/media/libstagefright/Android.bp
index 7ba4b7d..0c71487 100644
--- a/media/libstagefright/Android.bp
+++ b/media/libstagefright/Android.bp
@@ -100,8 +100,10 @@
         "libui",
         "libutils",
         "libmedia_helper",
-        "libstagefright_omx_utils",
         "libstagefright_foundation",
+        "libstagefright_omx",
+        "libstagefright_omx_utils",
+        "libstagefright_xmlparser",
         "libdl",
         "libRScpp",
         "libhidlbase",
diff --git a/media/libstagefright/OmxInfoBuilder.cpp b/media/libstagefright/OmxInfoBuilder.cpp
index c174371..a6ebadd 100644
--- a/media/libstagefright/OmxInfoBuilder.cpp
+++ b/media/libstagefright/OmxInfoBuilder.cpp
@@ -35,6 +35,7 @@
 
 #include <media/IOMX.h>
 #include <media/omx/1.0/WOmx.h>
+#include <media/stagefright/omx/1.0/OmxStore.h>
 
 #include <media/openmax/OMX_Index.h>
 #include <media/openmax/OMX_IndexExt.h>
@@ -89,8 +90,6 @@
 }
 
 status_t OmxInfoBuilder::buildMediaCodecList(MediaCodecListWriter* writer) {
-    hidl_vec<IOmxStore::RoleInfo> roles;
-
     // Obtain IOmxStore
     sp<IOmxStore> omxStore = IOmxStore::getService();
     if (omxStore == nullptr) {
@@ -100,8 +99,37 @@
 
     // List service attributes (global settings)
     Status status;
+    hidl_vec<IOmxStore::RoleInfo> roles;
+    auto transStatus = omxStore->listRoles(
+            [&roles] (
+            const hidl_vec<IOmxStore::RoleInfo>& inRoleList) {
+                roles = inRoleList;
+            });
+    if (!transStatus.isOk()) {
+        ALOGE("Fail to obtain codec roles from IOmxStore.");
+        return NO_INIT;
+    } else if (roles.size() == 0) {
+        ALOGW("IOmxStore has empty implementation. "
+                "Creating a local default instance...");
+        omxStore = new implementation::OmxStore();
+        if (omxStore == nullptr) {
+            ALOGE("Cannot create a local default instance.");
+            return NO_INIT;
+        }
+        ALOGI("IOmxStore local default instance created.");
+        transStatus = omxStore->listRoles(
+                [&roles] (
+                const hidl_vec<IOmxStore::RoleInfo>& inRoleList) {
+                    roles = inRoleList;
+                });
+        if (!transStatus.isOk()) {
+            ALOGE("Fail to obtain codec roles from local IOmxStore.");
+            return NO_INIT;
+        }
+    }
+
     hidl_vec<IOmxStore::ServiceAttribute> serviceAttributes;
-    auto transStatus = omxStore->listServiceAttributes(
+    transStatus = omxStore->listServiceAttributes(
             [&status, &serviceAttributes] (
             Status inStatus,
             const hidl_vec<IOmxStore::ServiceAttribute>& inAttributes) {
@@ -121,16 +149,6 @@
                 p.key.c_str(), p.value.c_str());
     }
 
-    transStatus = omxStore->listRoles(
-            [&roles] (
-            const hidl_vec<IOmxStore::RoleInfo>& inRoleList) {
-                roles = inRoleList;
-            });
-    if (!transStatus.isOk()) {
-        ALOGE("Fail to obtain codec roles from IOmxStore.");
-        return NO_INIT;
-    }
-
     // Convert roles to lists of codecs
 
     // codec name -> index into swCodecs/hwCodecs
diff --git a/media/libstagefright/codec2/include/C2.h b/media/libstagefright/codec2/include/C2.h
index 7d00a03..213d5a0 100644
--- a/media/libstagefright/codec2/include/C2.h
+++ b/media/libstagefright/codec2/include/C2.h
@@ -101,10 +101,10 @@
 typedef const char *C2StringLiteral;
 
 /**
- * C2Error: status codes used.
+ * C2Status: status codes used.
  */
-typedef int32_t C2Error;
-enum {
+//typedef int32_t C2Status;
+enum C2Status : int32_t {
 #ifndef __ANDROID__
     OK                  = 0,
     BAD_VALUE           = -EINVAL,
@@ -141,6 +141,7 @@
 
     // unknown fatal
     C2_CORRUPTED        = UNKNOWN_ERROR,        ///< some unexpected error prevented the operation
+    C2_NO_INIT          = NO_INIT,              ///< status has not been initialized
 };
 
 /// @}
diff --git a/media/libstagefright/codec2/include/C2Buffer.h b/media/libstagefright/codec2/include/C2Buffer.h
index 9580449..2a3e599 100644
--- a/media/libstagefright/codec2/include/C2Buffer.h
+++ b/media/libstagefright/codec2/include/C2Buffer.h
@@ -91,7 +91,7 @@
      * \retval C2_NO_PERMISSION no permission to wait for the fence (unexpected - system)
      * \retval C2_CORRUPTED     some unknown error prevented waiting for the fence (unexpected)
      */
-    C2Error wait(nsecs_t timeoutNs);
+    C2Status wait(nsecs_t timeoutNs);
 
     /**
      * Used to check if this fence is valid (if there is a chance for it to be signaled.)
@@ -158,7 +158,7 @@
      * \retval C2_NO_PERMISSION no permission to signal the fence (unexpected - system)
      * \retval C2_CORRUPTED     some unknown error prevented signaling the fence(s) (unexpected)
      */
-    C2Error fire();
+    C2Status fire();
 
     /**
      * Trigger this event from the merging of the supplied fences. This means that it will be
@@ -172,7 +172,7 @@
      * \retval C2_NO_PERMISSION no permission to merge the fence (unexpected - system)
      * \retval C2_CORRUPTED     some unknown error prevented merging the fence(s) (unexpected)
      */
-    C2Error merge(std::vector<C2Fence> fences);
+    C2Status merge(std::vector<C2Fence> fences);
 
     /**
      * Abandons the event and any associated fence(s).
@@ -186,7 +186,7 @@
      * \retval C2_NO_PERMISSION no permission to abandon the fence (unexpected - system)
      * \retval C2_CORRUPTED     some unknown error prevented signaling the fence(s) (unexpected)
      */
-    C2Error abandon();
+    C2Status abandon();
 
 private:
     class Impl;
@@ -197,15 +197,15 @@
 /// @{
 
 /**
- * Interface for objects that encapsulate an updatable error value.
+ * Interface for objects that encapsulate an updatable status value.
  */
-struct _C2InnateError {
-    inline C2Error error() const { return mError; }
+struct _C2InnateStatus {
+    inline C2Status status() const { return mStatus; }
 
 protected:
-    _C2InnateError(C2Error error) : mError(error) { }
+    _C2InnateStatus(C2Status status) : mStatus(status) { }
 
-    C2Error mError; // this error is updatable by the object
+    C2Status mStatus; // this status is updatable by the object
 };
 
 /// @}
@@ -230,10 +230,10 @@
     }
 
 protected:
-    C2Acquirable(C2Error error, C2Fence fence, T t) : C2Fence(fence), mInitialError(error), mT(t) { }
+    C2Acquirable(C2Status error, C2Fence fence, T t) : C2Fence(fence), mInitialError(error), mT(t) { }
 
 private:
-    C2Error mInitialError;
+    C2Status mInitialError;
     T mT; // TODO: move instead of copy
 };
 
@@ -449,11 +449,11 @@
     /**
      * \return error during the creation/mapping of this view.
      */
-    C2Error error();
+    C2Status error() const;
 
 protected:
     C2ReadView(const _C2LinearCapacityAspect *parent, const uint8_t *data);
-    explicit C2ReadView(C2Error error);
+    explicit C2ReadView(C2Status error);
 
 private:
     class Impl;
@@ -482,11 +482,11 @@
     /**
      * \return error during the creation/mapping of this view.
      */
-    C2Error error();
+    C2Status error() const;
 
 protected:
     C2WriteView(const _C2LinearRangeAspect *parent, uint8_t *base);
-    explicit C2WriteView(C2Error error);
+    explicit C2WriteView(C2Status error);
 
 private:
     class Impl;
@@ -631,7 +631,7 @@
      * \retval C2_TIMED_OUT     the reservation timed out \todo when?
      * \retval C2_CORRUPTED     some unknown error prevented reserving space. (unexpected)
      */
-    C2Error reserve(size_t size, C2Fence *fence /* nullable */);
+    C2Status reserve(size_t size, C2Fence *fence /* nullable */);
 
     /**
      * Abandons a portion of this segment. This will move to the beginning of this segment.
@@ -644,7 +644,7 @@
      * \retval C2_TIMED_OUT     the operation timed out (unexpected)
      * \retval C2_CORRUPTED     some unknown error prevented abandoning the data (unexpected)
      */
-    C2Error abandon(size_t size);
+    C2Status abandon(size_t size);
 
     /**
      * Share a portion as block(s) with consumers (these are moved to the used section).
@@ -661,7 +661,7 @@
      * \retval C2_TIMED_OUT     the operation timed out (unexpected)
      * \retval C2_CORRUPTED     some unknown error prevented sharing the data (unexpected)
      */
-    C2Error share(size_t size, C2Fence fence, std::list<C2ConstLinearBlock> &blocks);
+    C2Status share(size_t size, C2Fence fence, std::list<C2ConstLinearBlock> &blocks);
 
     /**
      * Returns the beginning offset of this segment from the start of this circular block.
@@ -695,7 +695,7 @@
     /**
      * \return error during the creation/mapping of this view.
      */
-    C2Error error();
+    C2Status error() const;
 };
 
 /**
@@ -716,7 +716,7 @@
      * \param size    number of bytes to commit to the next segment
      * \param fence   fence used for the commit (the fence must signal before the data is committed)
      */
-    C2Error commit(size_t size, C2Fence fence);
+    C2Status commit(size_t size, C2Fence fence);
 
     /**
      * Maps this block into memory and returns a write view for it.
@@ -1016,14 +1016,14 @@
     /**
      * \return error during the creation/mapping of this view.
      */
-    C2Error error() const;
+    C2Status error() const;
 
 protected:
     C2GraphicView(
             const _C2PlanarCapacityAspect *parent,
             uint8_t *const *data,
             const C2PlaneLayout& layout);
-    explicit C2GraphicView(C2Error error);
+    explicit C2GraphicView(C2Status error);
 
 private:
     class Impl;
@@ -1224,7 +1224,7 @@
      * \retval C2_NO_MEMORY not enough memory to register for this callback
      * \retval C2_CORRUPTED an unknown error prevented the registration (unexpected)
      */
-    C2Error registerOnDestroyNotify(OnDestroyNotify onDestroyNotify, void *arg = nullptr);
+    C2Status registerOnDestroyNotify(OnDestroyNotify onDestroyNotify, void *arg = nullptr);
 
     /**
      * Unregisters a previously registered pre-destroy notification.
@@ -1236,7 +1236,7 @@
      * \retval C2_NOT_FOUND the notification was not found
      * \retval C2_CORRUPTED an unknown error prevented the registration (unexpected)
      */
-    C2Error unregisterOnDestroyNotify(OnDestroyNotify onDestroyNotify, void *arg = nullptr);
+    C2Status unregisterOnDestroyNotify(OnDestroyNotify onDestroyNotify, void *arg = nullptr);
 
     ///@}
 
@@ -1262,7 +1262,7 @@
      * \retval C2_NO_MEMORY not enough memory to attach the metadata (this return value is not
      *                      used if the same kind of metadata is already attached to the buffer).
      */
-    C2Error setInfo(const std::shared_ptr<C2Info> &info);
+    C2Status setInfo(const std::shared_ptr<C2Info> &info);
 
     /**
      * Checks if there is a certain type of metadata attached to this buffer.
@@ -1385,7 +1385,7 @@
      *                      the usage flags are invalid (caller error)
      * \retval C2_CORRUPTED some unknown error prevented the operation from completing (unexpected)
      */
-    virtual C2Error map(
+    virtual C2Status map(
             size_t offset, size_t size, C2MemoryUsage usage, int *fenceFd /* nullable */,
             void **addr /* nonnull */) = 0;
 
@@ -1409,7 +1409,7 @@
      * \retval C2_CORRUPTED some unknown error prevented the operation from completing (unexpected)
      * \retval C2_NO_PERMISSION no permission to unmap the portion (unexpected - system)
      */
-    virtual C2Error unmap(void *addr, size_t size, int *fenceFd /* nullable */) = 0;
+    virtual C2Status unmap(void *addr, size_t size, int *fenceFd /* nullable */) = 0;
 
     /**
      * Returns true if this is a valid allocation.
@@ -1472,7 +1472,7 @@
      * \retval C2_CORRUPTED some unknown error prevented the operation from completing (unexpected)
 
      */
-    virtual C2Error map(
+    virtual C2Status map(
             C2Rect rect, C2MemoryUsage usage, int *fenceFd,
             // TODO: return <addr, size> buffers with plane sizes
             C2PlaneLayout *layout /* nonnull */, uint8_t **addr /* nonnull */) = 0;
@@ -1492,7 +1492,7 @@
      * \retval C2_CORRUPTED some unknown error prevented the operation from completing (unexpected)
      * \retval C2_NO_PERMISSION no permission to unmap the section (unexpected - system)
      */
-    virtual C2Error unmap(C2Fence *fenceFd /* nullable */) = 0;
+    virtual C2Status unmap(C2Fence *fenceFd /* nullable */) = 0;
 
     /**
      * Returns true if this is a valid allocation.
@@ -1550,7 +1550,7 @@
      * \retval C2_UNSUPPORTED       this allocator does not support 1D allocations
      * \retval C2_CORRUPTED some unknown, unrecoverable error occured during allocation (unexpected)
      */
-    virtual C2Error allocateLinearBuffer(
+    virtual C2Status allocateLinearBuffer(
             uint32_t capacity __unused, C2MemoryUsage usage __unused,
             std::shared_ptr<C2LinearAllocation> *allocation /* nonnull */) {
         *allocation = nullptr;
@@ -1573,7 +1573,7 @@
      * \retval C2_UNSUPPORTED       this allocator does not support 1D allocations
      * \retval C2_CORRUPTED some unknown, unrecoverable error occured during allocation (unexpected)
      */
-    virtual C2Error recreateLinearBuffer(
+    virtual C2Status recreateLinearBuffer(
             const C2Handle *handle __unused,
             std::shared_ptr<C2LinearAllocation> *allocation /* nonnull */) {
         *allocation = nullptr;
@@ -1606,7 +1606,7 @@
      * \retval C2_UNSUPPORTED       this allocator does not support 2D allocations
      * \retval C2_CORRUPTED some unknown, unrecoverable error occured during allocation (unexpected)
      */
-    virtual C2Error allocateGraphicBuffer(
+    virtual C2Status allocateGraphicBuffer(
             uint32_t width __unused, uint32_t height __unused, uint32_t format __unused,
             C2MemoryUsage usage __unused,
             std::shared_ptr<C2GraphicAllocation> *allocation /* nonnull */) {
@@ -1630,7 +1630,7 @@
      * \retval C2_UNSUPPORTED       this allocator does not support 2D allocations
      * \retval C2_CORRUPTED some unknown, unrecoverable error occured during recreation (unexpected)
      */
-    virtual C2Error recreateGraphicBuffer(
+    virtual C2Status recreateGraphicBuffer(
             const C2Handle *handle __unused,
             std::shared_ptr<C2GraphicAllocation> *allocation /* nonnull */) {
         *allocation = nullptr;
@@ -1674,7 +1674,7 @@
      * \retval C2_UNSUPPORTED       this allocator does not support linear allocations
      * \retval C2_CORRUPTED some unknown, unrecoverable error occured during allocation (unexpected)
      */
-    virtual C2Error allocateLinearBlock(
+    virtual C2Status allocateLinearBlock(
             uint32_t capacity __unused, C2MemoryUsage usage __unused,
             std::shared_ptr<C2LinearBlock> *block /* nonnull */) {
         *block = nullptr;
@@ -1703,7 +1703,7 @@
      * \retval C2_UNSUPPORTED   this allocator does not support circular allocations
      * \retval C2_CORRUPTED     some unknown, unrecoverable error occured during allocation (unexpected)
      */
-    virtual C2Error allocateCircularBlock(
+    virtual C2Status allocateCircularBlock(
             uint32_t capacity __unused, C2MemoryUsage usage __unused,
             std::shared_ptr<C2CircularBlock> *block /* nonnull */) {
         *block = nullptr;
@@ -1736,7 +1736,7 @@
      * \retval C2_UNSUPPORTED   this allocator does not support 2D allocations
      * \retval C2_CORRUPTED     some unknown, unrecoverable error occured during allocation (unexpected)
      */
-    virtual C2Error allocateGraphicBlock(
+    virtual C2Status allocateGraphicBlock(
             uint32_t width __unused, uint32_t height __unused, uint32_t format __unused,
             C2MemoryUsage usage __unused,
             std::shared_ptr<C2GraphicBlock> *block /* nonnull */) {
diff --git a/media/libstagefright/codec2/include/C2Component.h b/media/libstagefright/codec2/include/C2Component.h
index a9b1702..4eea800 100644
--- a/media/libstagefright/codec2/include/C2Component.h
+++ b/media/libstagefright/codec2/include/C2Component.h
@@ -55,6 +55,31 @@
     virtual ~C2ComponentListener() = default;
 };
 
+struct C2FieldSupportedValuesQuery {
+    enum Type : uint32_t {
+        POSSIBLE, ///< query all possible values regardless of other settings
+        CURRENT,  ///< query currently possible values given dependent settings
+    };
+
+    const C2ParamField field;
+    const Type type;
+    C2Status status;
+    C2FieldSupportedValues values;
+
+    C2FieldSupportedValuesQuery(const C2ParamField &field_, Type type_)
+        : field(field_), type(type_), status(C2_NO_INIT) { }
+
+    static C2FieldSupportedValuesQuery&&
+    Current(const C2ParamField &field_) {
+        return std::move(C2FieldSupportedValuesQuery(field_, CURRENT));
+    }
+
+    static C2FieldSupportedValuesQuery&&
+    Possible(const C2ParamField &field_) {
+        return std::move(C2FieldSupportedValuesQuery(field_, POSSIBLE));
+    }
+};
+
 /**
  * Component interface object. This object contains all of the configuration of a potential or
  * actual component. It can be created and used independently of an actual C2Component instance to
@@ -129,7 +154,7 @@
      * \retval C2_CORRUPTED some unknown error prevented the querying of the parameters
      *                      (unexpected)
      */
-    virtual status_t query_nb(
+    virtual C2Status query_nb(
         const std::vector<C2Param* const> &stackParams,
         const std::vector<C2Param::Index> &heapParamIndices,
         std::vector<std::unique_ptr<C2Param>>* const heapParams) const = 0;
@@ -166,7 +191,7 @@
      * \retval C2_CORRUPTED some unknown error prevented the update of the parameters
      *                      (unexpected)
      */
-    virtual status_t config_nb(
+    virtual C2Status config_nb(
             const std::vector<C2Param* const> &params,
             std::vector<std::unique_ptr<C2SettingResult>>* const failures) = 0;
 
@@ -205,7 +230,7 @@
      * \retval C2_CORRUPTED some unknown error prevented the update of the parameters
      *                      (unexpected)
      */
-    virtual status_t commit_sm(
+    virtual C2Status commit_sm(
             const std::vector<C2Param* const> &params,
             std::vector<std::unique_ptr<C2SettingResult>>* const failures) = 0;
 
@@ -230,7 +255,7 @@
      * \retval C2_TIMED_OUT could not create the tunnel within the time limit (unexpected)
      * \retval C2_CORRUPTED some unknown error prevented the creation of the tunnel (unexpected)
      */
-    virtual status_t createTunnel_sm(node_id targetComponent) = 0;
+    virtual C2Status createTunnel_sm(node_id targetComponent) = 0;
 
     /**
      * Releases a tunnel from this component to the target component.
@@ -250,7 +275,7 @@
      * \retval C2_TIMED_OUT could not mark the tunnel for release within the time limit (unexpected)
      * \retval C2_CORRUPTED some unknown error prevented the release of the tunnel (unexpected)
      */
-    virtual status_t releaseTunnel_sm(node_id targetComponent) = 0;
+    virtual C2Status releaseTunnel_sm(node_id targetComponent) = 0;
 
 
     // REFLECTION MECHANISM (USED FOR EXTENSION)
@@ -273,7 +298,7 @@
      * \retval C2_OK        the operation completed successfully.
      * \retval C2_NO_MEMORY not enough memory to complete this method.
      */
-    virtual status_t getSupportedParams(
+    virtual C2Status getSupportedParams(
             std::vector<std::shared_ptr<C2ParamDescriptor>> * const params) const = 0;
 
     /**
@@ -281,9 +306,8 @@
      * \todo should this take a list considering that setting some fields may further limit other
      * fields in the same list?
      */
-    virtual status_t getSupportedValues(
-            const std::vector<const C2ParamField> &fields,
-            std::vector<C2FieldSupportedValues>* const values) const = 0;
+    virtual C2Status getSupportedValues(
+            std::vector<C2FieldSupportedValuesQuery> &fields) const = 0;
 
     virtual ~C2ComponentInterface() = default;
 };
@@ -310,7 +334,7 @@
      * \retval C2_NO_MEMORY not enough memory to queue the work
      * \retval C2_CORRUPTED some unknown error prevented queuing the work (unexpected)
      */
-    virtual status_t queue_nb(std::list<std::unique_ptr<C2Work>>* const items) = 0;
+    virtual C2Status queue_nb(std::list<std::unique_ptr<C2Work>>* const items) = 0;
 
     /**
      * Announces a work to be queued later for the component. This reserves a slot for the queue
@@ -329,7 +353,7 @@
      *
      * \todo Can this be rolled into queue_nb?
      */
-    virtual status_t announce_nb(const std::vector<C2WorkOutline> &items) = 0;
+    virtual C2Status announce_nb(const std::vector<C2WorkOutline> &items) = 0;
 
     /**
      * Discards and abandons any pending work for the component, and optionally any component
@@ -361,7 +385,7 @@
      * \retval C2_TIMED_OUT the flush could not be completed within the time limit (unexpected)
      * \retval C2_CORRUPTED some unknown error prevented flushing from completion (unexpected)
      */
-    virtual status_t flush_sm(bool flushThrough, std::list<std::unique_ptr<C2Work>>* const flushedWork) = 0;
+    virtual C2Status flush_sm(bool flushThrough, std::list<std::unique_ptr<C2Work>>* const flushedWork) = 0;
 
     /**
      * Drains the component, and optionally downstream components
@@ -390,7 +414,7 @@
      * \retval C2_TIMED_OUT the flush could not be completed within the time limit (unexpected)
      * \retval C2_CORRUPTED some unknown error prevented flushing from completion (unexpected)
      */
-    virtual status_t drain_nb(bool drainThrough) = 0;
+    virtual C2Status drain_nb(bool drainThrough) = 0;
 
     // STATE CHANGE METHODS
     // =============================================================================================
@@ -411,7 +435,7 @@
      * \retval C2_TIMED_OUT the component could not be started within the time limit (unexpected)
      * \retval C2_CORRUPTED some unknown error prevented starting the component (unexpected)
      */
-    virtual status_t start() = 0;
+    virtual C2Status start() = 0;
 
     /**
      * Stops the component.
@@ -428,7 +452,7 @@
      * This does not alter any settings and tunings that may have resulted in a tripped state.
      * (Is this material given the definition? Perhaps in case we want to start again.)
      */
-    virtual status_t stop() = 0;
+    virtual C2Status stop() = 0;
 
     /**
      * Resets the component.
@@ -502,9 +526,9 @@
      * \retval C2_TIMED_OUT could not reset the parser within the time limit (unexpected)
      * \retval C2_CORRUPTED some unknown error prevented the resetting of the parser (unexpected)
      */
-    virtual status_t reset() { return C2_OK; }
+    virtual C2Status reset() { return C2_OK; }
 
-    virtual status_t parseFrame(C2BufferPack &frame);
+    virtual C2Status parseFrame(C2BufferPack &frame);
 
     virtual ~C2FrameInfoParser() = default;
 };
@@ -542,7 +566,7 @@
      * \retval C2_NOT_FOUND no such allocator
      * \retval C2_NO_MEMORY not enough memory to create the allocator
      */
-    virtual status_t createAllocator(ID id, std::shared_ptr<C2Allocator>* const allocator) = 0;
+    virtual C2Status createAllocator(ID id, std::shared_ptr<C2Allocator>* const allocator) = 0;
 
     virtual ~C2AllocatorStore() = default;
 };
@@ -565,7 +589,7 @@
      * \retval C2_NOT_FOUND no such component
      * \retval C2_NO_MEMORY not enough memory to create the component
      */
-    virtual status_t createComponent(C2String name, std::shared_ptr<C2Component>* const component);
+    virtual C2Status createComponent(C2String name, std::shared_ptr<C2Component>* const component);
 
     /**
      * Creates a component interface.
@@ -586,7 +610,7 @@
      *
      * \todo Do we need an interface, or could this just be a component that is never started?
      */
-    virtual status_t createInterface(C2String name, std::shared_ptr<C2ComponentInterface>* const interface);
+    virtual C2Status createInterface(C2String name, std::shared_ptr<C2ComponentInterface>* const interface);
 
     /**
      * Returns the list of components supported by this component store.
@@ -600,9 +624,9 @@
     // -------------------------------------- UTILITY METHODS --------------------------------------
 
     // on-demand buffer layout conversion (swizzling)
-    virtual status_t copyBuffer(std::shared_ptr<C2GraphicBuffer> src, std::shared_ptr<C2GraphicBuffer> dst);
+    virtual C2Status copyBuffer(std::shared_ptr<C2GraphicBuffer> src, std::shared_ptr<C2GraphicBuffer> dst);
 
-    // status_t selectPreferredColor(formats<A>, formats<B>);
+    // C2Status selectPreferredColor(formats<A>, formats<B>);
 
     // GLOBAL SETTINGS
     // system-wide stride & slice-height (???)
@@ -636,7 +660,7 @@
      * \retval C2_CORRUPTED some unknown error prevented the querying of the parameters
      *                      (unexpected)
      */
-    virtual status_t query_sm(
+    virtual C2Status query_sm(
         const std::vector<C2Param* const> &stackParams,
         const std::vector<C2Param::Index> &heapParamIndices,
         std::vector<std::unique_ptr<C2Param>>* const heapParams) const = 0;
@@ -675,7 +699,7 @@
      * \retval C2_CORRUPTED some unknown error prevented the update of the parameters
      *                      (unexpected)
      */
-    virtual status_t config_nb(
+    virtual C2Status config_nb(
             const std::vector<C2Param* const> &params,
             std::list<std::unique_ptr<C2SettingResult>>* const failures) = 0;
 
diff --git a/media/libstagefright/codec2/include/C2Param.h b/media/libstagefright/codec2/include/C2Param.h
index 02403c5..f0b92a3 100644
--- a/media/libstagefright/codec2/include/C2Param.h
+++ b/media/libstagefright/codec2/include/C2Param.h
@@ -344,6 +344,10 @@
     /// returns the parameter type: the parameter index without the stream ID
     inline uint32_t type() const { return _mIndex.type(); }
 
+    /// returns the index of this parameter
+    /// \todo: should we restrict this to C2ParamField?
+    inline uint32_t index() const { return (uint32_t)_mIndex; }
+
     /// returns the kind of this parameter
     inline Kind kind() const { return _mIndex.kind(); }
 
@@ -562,7 +566,6 @@
     /**
      * Constructor used to identify a field in an object.
      *
-     * \param U[type] pointer to the object that contains this field
      * \param pm[im] member pointer to the field
      */
     template<typename R, typename T, typename B=typename std::remove_extent<R>::type>
@@ -597,23 +600,93 @@
 };
 
 /**
- * Structure uniquely specifying a field in a configuration
+ * Structure uniquely specifying a 'field' in a configuration. The field
+ * can be a field of a configuration, a subfield of a field of a configuration,
+ * and even the whole configuration. Moreover, if the field can point to an
+ * element in a array field, or to the entire array field.
+ *
+ * This structure is used for querying supported values for a field, as well
+ * as communicating configuration failures and conflicts when trying to change
+ * a configuration for a component/interface or a store.
  */
 struct C2ParamField {
 //public:
-    // TODO: fix what this is for T[] (for now size becomes T[1])
+    /**
+     * Create a field identifier using a configuration parameter (variable),
+     * and a pointer to member.
+     *
+     * ~~~~~~~~~~~~~ (.cpp)
+     *
+     * struct C2SomeParam {
+     *   uint32_t mField;
+     *   uint32_t mArray[2];
+     *   C2OtherStruct mStruct;
+     *   uint32_t mFlexArray[];
+     * } *mParam;
+     *
+     * C2ParamField(mParam, &mParam->mField);
+     * C2ParamField(mParam, &mParam->mArray);
+     * C2ParamField(mParam, &mParam->mArray[0]);
+     * C2ParamField(mParam, &mParam->mStruct.mSubField);
+     * C2ParamField(mParam, &mParam->mFlexArray);
+     * C2ParamField(mParam, &mParam->mFlexArray[2]);
+     *
+     * ~~~~~~~~~~~~~
+     *
+     * \todo fix what this is for T[] (for now size becomes T[1])
+     *
+     * \param param pointer to parameter
+     * \param offset member pointer
+     */
     template<typename S, typename T>
     inline C2ParamField(S* param, T* offset)
         : _mIndex(param->index()),
           _mFieldId(offset) {}
 
+    /**
+     * Create a field identifier using a configuration parameter (variable),
+     * and a member pointer. This method cannot be used to refer to an
+     * array element or a subfield.
+     *
+     * ~~~~~~~~~~~~~ (.cpp)
+     *
+     * C2SomeParam mParam;
+     * C2ParamField(&mParam, &C2SomeParam::mMemberField);
+     *
+     * ~~~~~~~~~~~~~
+     *
+     * \param p pointer to parameter
+     * \param T member pointer to the field member
+     */
     template<typename R, typename T, typename U>
-    inline C2ParamField(U *p, R T::* pm) : _mIndex(p->type()), _mFieldId(p, pm) { }
+    inline C2ParamField(U *p, R T::* pm) : _mIndex(p->index()), _mFieldId(p, pm) { }
 
+    /**
+     * Create a field identifier to a configuration parameter (variable).
+     *
+     * ~~~~~~~~~~~~~ (.cpp)
+     *
+     * C2SomeParam mParam;
+     * C2ParamField(&mParam);
+     *
+     * ~~~~~~~~~~~~~
+     *
+     * \param param pointer to parameter
+     */
+    template<typename S>
+    inline C2ParamField(S* param)
+        : _mIndex(param->index()), _mFieldId(0u, param->size()) {}
+
+    /**
+     * Equality operator.
+     */
     inline bool operator==(const C2ParamField &other) const {
         return _mIndex == other._mIndex && _mFieldId == other._mFieldId;
     }
 
+    /**
+     * Ordering operator.
+     */
     inline bool operator<(const C2ParamField &other) const {
         return _mIndex < other._mIndex ||
             (_mIndex == other._mIndex && _mFieldId < other._mFieldId);
@@ -622,8 +695,8 @@
     DEFINE_OTHER_COMPARISON_OPERATORS(C2ParamField)
 
 private:
-    C2Param::Index _mIndex;
-    _C2FieldId _mFieldId;
+    C2Param::Index _mIndex; ///< parameter index
+    _C2FieldId _mFieldId;   ///< field identifier
 };
 
 /**
@@ -1153,6 +1226,7 @@
 struct C2FieldSupportedValues {
 //public:
     enum Type {
+        EMPTY,      ///< no supported values
         RANGE,      ///< a numeric range that can be continuous or discrete
         VALUES,     ///< a list of values
         FLAGS       ///< a list of flags that can be OR-ed
@@ -1171,6 +1245,10 @@
     } range;
     std::vector<Primitive> values;
 
+    C2FieldSupportedValues()
+        : type(EMPTY) {
+    }
+
     template<typename T>
     C2FieldSupportedValues(T min, T max, T step = T(std::is_floating_point<T>::value ? 0 : 1))
         : type(RANGE),
@@ -1199,6 +1277,9 @@
         }
     }
 
+    /// \internal
+    /// \todo: create separate values vs. flags initializer as for flags we want
+    /// to list both allowed and disallowed flags
     template<typename T, typename E=decltype(C2FieldDescriptor::namedValuesFor(*(T*)0))>
     C2FieldSupportedValues(bool flags, const T*)
         : type(flags ? FLAGS : VALUES),
@@ -1210,6 +1291,21 @@
     }
 };
 
+/**
+ * Spported values for a specific field.
+ *
+ * This is a pair of the field specifier together with an optional supported values object.
+ * This structure is used when reporting parameter configuration failures and conflicts.
+ */
+struct C2ParamFieldValues {
+    C2ParamField paramOrField; ///< the field or parameter
+    /// optional supported values for the field if paramOrField specifies an actual field that is
+    /// numeric (non struct, blob or string). Supported values for arrays (including string and
+    /// blobs) describe the supported values for each element (character for string, and bytes for
+    /// blobs). It is optional for read-only strings and blobs.
+    std::unique_ptr<C2FieldSupportedValues> values;
+};
+
 /// @}
 
 }  // namespace android
diff --git a/media/libstagefright/codec2/include/C2Work.h b/media/libstagefright/codec2/include/C2Work.h
index a378623..69c16ab 100644
--- a/media/libstagefright/codec2/include/C2Work.h
+++ b/media/libstagefright/codec2/include/C2Work.h
@@ -28,28 +28,47 @@
 #include <list>
 #include <vector>
 
-typedef int status_t;
-
 namespace android {
 
 /// \defgroup work Work and data processing
 /// @{
 
+/**
+ * Information describing the reason a parameter settings may fail, or
+ * may be overriden.
+ */
 struct C2SettingResult {
-    enum Failure {
+    enum Failure : uint32_t {
         READ_ONLY,  ///< parameter is read-only and cannot be set
         MISMATCH,   ///< parameter mismatches input data
         BAD_VALUE,  ///< parameter does not accept value
         BAD_TYPE,   ///< parameter is not supported
         BAD_PORT,   ///< parameter is not supported on the specific port
         BAD_INDEX,  ///< parameter is not supported on the specific stream
-        CONFLICT,   ///< parameter is in conflict with another setting
+        CONFLICT,   ///< parameter is in conflict with an/other setting(s)
+        /// parameter is out of range due to other settings (this failure mode
+        /// can only be used for strict parameters)
+        UNSUPPORTED,
+
+
+        /// requested parameter value is in conflict with an/other setting(s)
+        /// and has been corrected to the closest supported value. This failure
+        /// mode is given to provide suggestion to the client as to how to
+        /// enable the requested parameter value.
+        INFO_CONFLICT,
     };
 
-    C2ParamField field;
-    Failure failure;
-    std::unique_ptr<C2FieldSupportedValues> supportedValues; //< if different from normal (e.g. in conflict w/another param or input data)
-    std::list<C2ParamField> conflictingFields;
+    Failure failure;    ///< failure code
+
+    /// Failing (or corrected) field. Currently supported values for the field. This is set if
+    /// different from the globally supported values (e.g. due to restrictions by another param or
+    /// input data)
+    /// \todo need to define suggestions for masks to be set and unset.
+    C2ParamFieldValues field;
+
+    /// Conflicting parameters or fields with optional suggestions with (optional) suggested values
+    /// for any conflicting fields to avoid the conflict.
+    std::list<C2ParamFieldValues> conflicts;
 };
 
 // ================================================================================================
@@ -146,7 +165,7 @@
     std::list<std::unique_ptr<C2Worklet>> worklets;
 
     uint32_t worklets_processed;
-    status_t result;
+    C2Status result;
 };
 
 struct C2WorkOutline {
diff --git a/media/libstagefright/codec2/tests/C2ComponentInterface_test.cpp b/media/libstagefright/codec2/tests/C2ComponentInterface_test.cpp
index 0c8ca3e..b725d76 100644
--- a/media/libstagefright/codec2/tests/C2ComponentInterface_test.cpp
+++ b/media/libstagefright/codec2/tests/C2ComponentInterface_test.cpp
@@ -112,11 +112,11 @@
     // check if a component has a parameter whose type is |T|.
     // If a component has, the value should be copied into an argument, that is
     // |p| in queryOnStack() and |heapParams| in queryOnHeap().
-    // The return value is status_t (e.g. C2_OK).
-    template <typename T> status_t queryOnStack(T *const p);
+    // The return value is C2Status (e.g. C2_OK).
+    template <typename T> C2Status queryOnStack(T *const p);
 
     template <typename T>
-    status_t queryOnHeap(const T &p,
+    C2Status queryOnHeap(const T &p,
                          std::vector<std::unique_ptr<C2Param>> *const heapParams);
 
     // Get a value whose type is |T| in a component. The value is copied to |param|.
@@ -139,7 +139,7 @@
     // Execute an interface's config_nb(). |T| is a single parameter type, not std::vector.
     // config() creates std::vector<C2Param *const> {p} and passes it to config_nb().
     template <typename T>
-    status_t
+    C2Status
     config(T *const p,
            std::vector<std::unique_ptr<C2SettingResult>> *const failures);
 
@@ -150,7 +150,7 @@
     // Test if config works correctly for writable parameters.
     // This changes the parameter's value to |newParam|.
     // |stConfig| is a return value of config().
-    template <typename T> void configWritableParamValidValue(const T &newParam, status_t *stConfig);
+    template <typename T> void configWritableParamValidValue(const T &newParam, C2Status *stConfig);
 
     // Test if config works correctly in the case an invalid value |newParam| is tried to write
     // to an writable parameter.
@@ -162,7 +162,7 @@
     //                   config() should be failed if these values are used as new values.
     // This function should be called only for writable and supported parameters.
     template <typename TField>
-    void getTestValues(const std::vector<C2FieldSupportedValues> &validValueInfos,
+    void getTestValues(const C2FieldSupportedValues &validValueInfos,
                        std::vector<TField> *const validValues,
                        std::vector<TField> *const invalidValues);
 
@@ -194,13 +194,13 @@
         }                                               \
     } while (false)
 
-template <typename T> status_t C2CompIntfTest::queryOnStack(T *const p) {
+template <typename T> C2Status C2CompIntfTest::queryOnStack(T *const p) {
     std::vector<C2Param *const> stackParams{p};
     return mIntf->query_nb(stackParams, {}, nullptr);
 }
 
 template <typename T>
-status_t C2CompIntfTest::queryOnHeap(
+C2Status C2CompIntfTest::queryOnHeap(
         const T &p, std::vector<std::unique_ptr<C2Param>> *const heapParams) {
     uint32_t index = p.type();
     if (p.forStream()) {
@@ -258,7 +258,7 @@
 }
 
 template <typename T>
-status_t C2CompIntfTest::config(
+C2Status C2CompIntfTest::config(
         T *const p, std::vector<std::unique_ptr<C2SettingResult>> *const failures) {
     std::vector<C2Param *const> params{p};
     return mIntf->config_nb(params, failures);
@@ -286,7 +286,7 @@
 }
 
 template <typename T>
-void C2CompIntfTest::configWritableParamValidValue(const T &newParam, status_t *configResult) {
+void C2CompIntfTest::configWritableParamValidValue(const T &newParam, C2Status *configResult) {
     std::unique_ptr<T> p = makeParamFrom(newParam);
 
     std::vector<C2Param *const> params{p.get()};
@@ -297,7 +297,7 @@
     // because there may be dependent limitations between fields or between parameters.
     // TODO(hiroh): I have to fill the return value. Comments in C2Component.h doesn't mention
     // about the return value when conflict happens. I set C2_BAD_VALUE to it temporarily now.
-    status_t stConfig = mIntf->config_nb(params, &failures);
+    C2Status stConfig = mIntf->config_nb(params, &failures);
     if (stConfig == C2_OK) {
         EXPECT_EQ(0u, failures.size());
     } else {
@@ -325,7 +325,7 @@
 // If another field type is added, it is necessary to add function for that.
 template <>
 void C2CompIntfTest::getTestValues(
-        const std::vector<C2FieldSupportedValues> &validValueInfos,
+        const C2FieldSupportedValues &validValueInfos,
         std::vector<C2DomainKind> *const validValues,
         std::vector<C2DomainKind> *const invalidValues) {
     UNUSED(validValueInfos);
@@ -339,7 +339,7 @@
 
 template <typename TField>
 void C2CompIntfTest::getTestValues(
-        const std::vector<C2FieldSupportedValues> &validValueInfos,
+        const C2FieldSupportedValues &validValueInfos,
         std::vector<TField> *const validValues,
         std::vector<TField> *const invalidValues) {
 
@@ -366,9 +366,14 @@
     };
 
     // The size of validValueInfos is one.
-    const auto &c2FSV = validValueInfos[0];
+    const auto &c2FSV = validValueInfos;
 
     switch (c2FSV.type) {
+    case C2FieldSupportedValues::Type::EMPTY: {
+        invalidValues->emplace_back(TField(0));
+        // TODO(hiroh) : Should other invalid values be tested?
+        break;
+    }
     case C2FieldSupportedValues::Type::RANGE: {
         const auto &range = c2FSV.range;
         auto rmin = prim2Value(range.min);
@@ -476,7 +481,7 @@
         TParam *const param, TRealField *const writableField,
         const std::vector<TField> &validValues,
         const std::vector<TField> &invalidValues) {
-    status_t stConfig;
+    C2Status stConfig;
 
     // Get the parameter's value in the beginning in order to reset the value at the end.
     TRACED_FAILURE(getValue(param));
@@ -550,7 +555,7 @@
     std::vector<std::unique_ptr<C2SettingResult>> failures;
     // Config does not change the parameter, because param is the present param.
     // This config is executed to find out if a parameter is read-only or writable.
-    status_t stStack = config(param.get(), &failures);
+    C2Status stStack = config(param.get(), &failures);
     if (stStack == C2_BAD_VALUE) {
         // Read-only
         std::unique_ptr<T> newParam = makeParam<T>();
@@ -584,15 +589,16 @@
 #define TEST_GENERAL_WRITABLE_FIELD(TParam_, field_type_name_, field_name_) \
     do {                                                                \
         std::unique_ptr<TParam_> param = makeParam<TParam_>();          \
-        std::vector<C2FieldSupportedValues> validValueInfos;            \
+        std::vector<C2FieldSupportedValuesQuery> validValueInfos = {    \
+            C2FieldSupportedValuesQuery::Current(                       \
+                    C2ParamField(param.get(), &field_type_name_::field_name_)) \
+        };                                                              \
         ASSERT_EQ(C2_OK,                                                \
-                  mIntf->getSupportedValues(                            \
-                          {C2ParamField(param.get(), &field_type_name_::field_name_)}, \
-                          &validValueInfos));                           \
+                  mIntf->getSupportedValues(validValueInfos));          \
         ASSERT_EQ(1u, validValueInfos.size());                          \
         std::vector<decltype(param->field_name_)> validValues;          \
         std::vector<decltype(param->field_name_)> invalidValues;        \
-        getTestValues(validValueInfos, &validValues, &invalidValues);   \
+        getTestValues(validValueInfos[0].values, &validValues, &invalidValues);   \
         testWritableParam(param.get(), &param->field_name_, validValues,\
                           invalidValues);                               \
     } while (0)
diff --git a/media/libstagefright/codec2/tests/C2Param_test.cpp b/media/libstagefright/codec2/tests/C2Param_test.cpp
index 0e71b2a..0140f5c 100644
--- a/media/libstagefright/codec2/tests/C2Param_test.cpp
+++ b/media/libstagefright/codec2/tests/C2Param_test.cpp
@@ -2403,7 +2403,7 @@
         return 0;
     }
 
-    virtual status_t commit_sm(
+    virtual C2Status commit_sm(
             const std::vector<C2Param* const> &params,
             std::vector<std::unique_ptr<C2SettingResult>>* const failures) {
         (void)params;
@@ -2411,7 +2411,7 @@
         return C2_UNSUPPORTED;
     }
 
-    virtual status_t config_nb(
+    virtual C2Status config_nb(
             const std::vector<C2Param* const> &params,
             std::vector<std::unique_ptr<C2SettingResult>>* const failures) {
         (void)params;
@@ -2419,12 +2419,12 @@
         return C2_UNSUPPORTED;
     }
 
-    virtual status_t createTunnel_sm(node_id targetComponent) {
+    virtual C2Status createTunnel_sm(node_id targetComponent) {
         (void)targetComponent;
         return C2_UNSUPPORTED;
     }
 
-    virtual status_t query_nb(
+    virtual C2Status query_nb(
             const std::vector<C2Param* const> &stackParams,
             const std::vector<C2Param::Index> &heapParamIndices,
             std::vector<std::unique_ptr<C2Param>>* const heapParams) const {
@@ -2466,7 +2466,7 @@
         mMyParams.insert({mDomainInfo.type(), mDomainInfo});
     }
 
-    virtual status_t releaseTunnel_sm(node_id targetComponent) {
+    virtual C2Status releaseTunnel_sm(node_id targetComponent) {
         (void)targetComponent;
         return C2_UNSUPPORTED;
     }
@@ -2490,17 +2490,19 @@
         }
     };
 
-    virtual status_t getSupportedValues(
-            const std::vector<const C2ParamField> &fields,
-            std::vector<C2FieldSupportedValues>* const values) const {
-        for (const C2ParamField &field : fields) {
-            if (field == C2ParamField(&mDomainInfo, &C2ComponentDomainInfo::mValue)) {
-                values->push_back(C2FieldSupportedValues(
+    virtual C2Status getSupportedValues(
+            std::vector<C2FieldSupportedValuesQuery> &fields) const {
+        for (C2FieldSupportedValuesQuery &query : fields) {
+            if (query.field == C2ParamField(&mDomainInfo, &C2ComponentDomainInfo::mValue)) {
+                query.values = C2FieldSupportedValues(
                     false /* flag */,
                     &mDomainInfo.mValue
                     //,
                     //{(int32_t)C2DomainVideo}
-                ));
+                );
+                query.status = C2_OK;
+            } else {
+                query.status = C2_BAD_INDEX;
             }
         }
         return C2_OK;
@@ -2510,13 +2512,13 @@
         return std::shared_ptr<C2ParamReflector>(new MyParamReflector(this));
     }
 
-    virtual status_t getSupportedParams(std::vector<std::shared_ptr<C2ParamDescriptor>> * const params) const {
+    virtual C2Status getSupportedParams(std::vector<std::shared_ptr<C2ParamDescriptor>> * const params) const {
         params->push_back(std::make_shared<C2ParamDescriptor>(
                 true /* required */, "_domain", &mDomainInfo));
         return C2_OK;
     }
 
-    status_t getSupportedParams2(std::vector<std::shared_ptr<C2ParamDescriptor>> * const params) {
+    C2Status getSupportedParams2(std::vector<std::shared_ptr<C2ParamDescriptor>> * const params) {
         params->push_back(std::shared_ptr<C2ParamDescriptor>(
                 new C2ParamDescriptor(true /* required */, "_domain", &mDomainInfo)));
         return C2_OK;
@@ -2699,21 +2701,23 @@
 TEST_F(C2ParamTest, ReflectorTest) {
     C2ComponentDomainInfo domainInfo;
     std::shared_ptr<C2ComponentInterface> comp(new MyComponentInstance);
-    std::vector<C2FieldSupportedValues> values;
 
     std::unique_ptr<C2StructDescriptor> desc{
         comp->getParamReflector()->describe(C2ComponentDomainInfo::indexFlags)};
     dumpStruct(*desc);
 
-    EXPECT_EQ(
-        C2_OK,
-        comp->getSupportedValues(
-            { C2ParamField(&domainInfo, &C2ComponentDomainInfo::mValue) },
-            &values)
-    );
+    std::vector<C2FieldSupportedValuesQuery> query = {
+        { C2ParamField(&domainInfo, &C2ComponentDomainInfo::mValue),
+          C2FieldSupportedValuesQuery::CURRENT },
+        C2FieldSupportedValuesQuery(C2ParamField(&domainInfo, &C2ComponentDomainInfo::mValue),
+          C2FieldSupportedValuesQuery::CURRENT),
+        C2FieldSupportedValuesQuery::Current(C2ParamField(&domainInfo, &C2ComponentDomainInfo::mValue)),
+    };
 
-    for (const C2FieldSupportedValues &sv : values) {
-        dumpFSV(sv, &domainInfo.mValue);
+    EXPECT_EQ(C2_OK, comp->getSupportedValues(query));
+
+    for (const C2FieldSupportedValuesQuery &q : query) {
+        dumpFSV(q.values, &domainInfo.mValue);
     }
 }
 
diff --git a/media/libstagefright/codec2/tests/vndk/C2BufferTest.cpp b/media/libstagefright/codec2/tests/vndk/C2BufferTest.cpp
index a185880..8c78334 100644
--- a/media/libstagefright/codec2/tests/vndk/C2BufferTest.cpp
+++ b/media/libstagefright/codec2/tests/vndk/C2BufferTest.cpp
@@ -38,7 +38,7 @@
     ~C2BufferTest() = default;
 
     void allocateLinear(size_t capacity) {
-        C2Error err = mLinearAllocator->allocateLinearBuffer(
+        C2Status err = mLinearAllocator->allocateLinearBuffer(
                 capacity,
                 { C2MemoryUsage::kSoftwareRead, C2MemoryUsage::kSoftwareWrite },
                 &mLinearAllocation);
@@ -50,7 +50,7 @@
 
     void mapLinear(size_t offset, size_t size, uint8_t **addr) {
         ASSERT_TRUE(mLinearAllocation);
-        C2Error err = mLinearAllocation->map(
+        C2Status err = mLinearAllocation->map(
                 offset,
                 size,
                 { C2MemoryUsage::kSoftwareRead, C2MemoryUsage::kSoftwareWrite },
@@ -82,7 +82,7 @@
     }
 
     void allocateGraphic(uint32_t width, uint32_t height) {
-        C2Error err = mGraphicAllocator->allocateGraphicBuffer(
+        C2Status err = mGraphicAllocator->allocateGraphicBuffer(
                 width,
                 height,
                 HAL_PIXEL_FORMAT_YCBCR_420_888,
@@ -96,7 +96,7 @@
 
     void mapGraphic(C2Rect rect, C2PlaneLayout *layout, uint8_t **addr) {
         ASSERT_TRUE(mGraphicAllocation);
-        C2Error err = mGraphicAllocation->map(
+        C2Status err = mGraphicAllocation->map(
                 rect,
                 { C2MemoryUsage::kSoftwareRead, C2MemoryUsage::kSoftwareWrite },
                 // TODO: fence
diff --git a/media/libstagefright/codec2/vndk/C2AllocatorGralloc.cpp b/media/libstagefright/codec2/vndk/C2AllocatorGralloc.cpp
index baa6637..537a411 100644
--- a/media/libstagefright/codec2/vndk/C2AllocatorGralloc.cpp
+++ b/media/libstagefright/codec2/vndk/C2AllocatorGralloc.cpp
@@ -38,7 +38,7 @@
 using ::android::hardware::hidl_vec;
 
 /* ===================================== GRALLOC ALLOCATION ==================================== */
-static C2Error maperr2error(Error maperr) {
+static C2Status maperr2error(Error maperr) {
     switch (maperr) {
         case Error::NONE:           return C2_OK;
         case Error::BAD_DESCRIPTOR: return C2_BAD_VALUE;
@@ -54,10 +54,10 @@
 public:
     virtual ~C2AllocationGralloc();
 
-    virtual C2Error map(
+    virtual C2Status map(
             C2Rect rect, C2MemoryUsage usage, int *fenceFd,
             C2PlaneLayout *layout /* nonnull */, uint8_t **addr /* nonnull */) override;
-    virtual C2Error unmap(C2Fence *fenceFd /* nullable */) override;
+    virtual C2Status unmap(C2Fence *fenceFd /* nullable */) override;
     virtual bool isValid() const override { return true; }
     virtual const C2Handle *handle() const override { return mHandle; }
     virtual bool equals(const std::shared_ptr<const C2GraphicAllocation> &other) const override;
@@ -69,7 +69,7 @@
               const sp<IMapper> &mapper,
               hidl_handle &handle);
     int dup() const;
-    C2Error status() const;
+    C2Status status() const;
 
 private:
     const IMapper::BufferDescriptorInfo mInfo;
@@ -100,7 +100,7 @@
     mMapper->freeBuffer(const_cast<native_handle_t *>(mBuffer));
 }
 
-C2Error C2AllocationGralloc::map(
+C2Status C2AllocationGralloc::map(
         C2Rect rect, C2MemoryUsage usage, int *fenceFd,
         C2PlaneLayout *layout /* nonnull */, uint8_t **addr /* nonnull */) {
     // TODO
@@ -114,7 +114,7 @@
         return C2_BAD_VALUE;
     }
 
-    C2Error err = C2_OK;
+    C2Status err = C2_OK;
     if (!mBuffer) {
         mMapper->importBuffer(
                 mHandle, [&err, this](const auto &maperr, const auto &buffer) {
@@ -202,9 +202,9 @@
     return C2_OK;
 }
 
-C2Error C2AllocationGralloc::unmap(C2Fence *fenceFd /* nullable */) {
+C2Status C2AllocationGralloc::unmap(C2Fence *fenceFd /* nullable */) {
     // TODO: fence
-    C2Error err = C2_OK;
+    C2Status err = C2_OK;
     mMapper->unlock(
             const_cast<native_handle_t *>(mBuffer),
             [&err, &fenceFd](const auto &maperr, const auto &releaseFence) {
@@ -231,18 +231,18 @@
 public:
     Impl();
 
-    C2Error allocateGraphicBuffer(
+    C2Status allocateGraphicBuffer(
             uint32_t width, uint32_t height, uint32_t format, const C2MemoryUsage &usage,
             std::shared_ptr<C2GraphicAllocation> *allocation);
 
-    C2Error recreateGraphicBuffer(
+    C2Status recreateGraphicBuffer(
             const C2Handle *handle,
             std::shared_ptr<C2GraphicAllocation> *allocation);
 
-    C2Error status() const { return mInit; }
+    C2Status status() const { return mInit; }
 
 private:
-    C2Error mInit;
+    C2Status mInit;
     sp<IAllocator> mAllocator;
     sp<IMapper> mMapper;
 };
@@ -256,7 +256,7 @@
     }
 }
 
-C2Error C2AllocatorGralloc::Impl::allocateGraphicBuffer(
+C2Status C2AllocatorGralloc::Impl::allocateGraphicBuffer(
         uint32_t width, uint32_t height, uint32_t format, const C2MemoryUsage &usage,
         std::shared_ptr<C2GraphicAllocation> *allocation) {
     // TODO: buffer usage should be determined according to |usage|
@@ -269,7 +269,7 @@
         (PixelFormat)format,
         BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN,
     };
-    C2Error err = C2_OK;
+    C2Status err = C2_OK;
     BufferDescriptor desc;
     mMapper->createDescriptor(
             info, [&err, &desc](const auto &maperr, const auto &descriptor) {
@@ -307,7 +307,7 @@
     return C2_OK;
 }
 
-C2Error C2AllocatorGralloc::Impl::recreateGraphicBuffer(
+C2Status C2AllocatorGralloc::Impl::recreateGraphicBuffer(
         const C2Handle *handle,
         std::shared_ptr<C2GraphicAllocation> *allocation) {
     (void) handle;
@@ -321,19 +321,19 @@
 
 C2AllocatorGralloc::~C2AllocatorGralloc() { delete mImpl; }
 
-C2Error C2AllocatorGralloc::allocateGraphicBuffer(
+C2Status C2AllocatorGralloc::allocateGraphicBuffer(
         uint32_t width, uint32_t height, uint32_t format, C2MemoryUsage usage,
         std::shared_ptr<C2GraphicAllocation> *allocation) {
     return mImpl->allocateGraphicBuffer(width, height, format, usage, allocation);
 }
 
-C2Error C2AllocatorGralloc::recreateGraphicBuffer(
+C2Status C2AllocatorGralloc::recreateGraphicBuffer(
         const C2Handle *handle,
         std::shared_ptr<C2GraphicAllocation> *allocation) {
     return mImpl->recreateGraphicBuffer(handle, allocation);
 }
 
-C2Error C2AllocatorGralloc::status() const {
+C2Status C2AllocatorGralloc::status() const {
     return mImpl->status();
 }
 
diff --git a/media/libstagefright/codec2/vndk/C2AllocatorIon.cpp b/media/libstagefright/codec2/vndk/C2AllocatorIon.cpp
index 7aa7769..4d23270 100644
--- a/media/libstagefright/codec2/vndk/C2AllocatorIon.cpp
+++ b/media/libstagefright/codec2/vndk/C2AllocatorIon.cpp
@@ -82,10 +82,10 @@
 /* ======================================= ION ALLOCATION ====================================== */
 class C2AllocationIon : public C2LinearAllocation {
 public:
-    virtual C2Error map(
+    virtual C2Status map(
         size_t offset, size_t size, C2MemoryUsage usage, int *fence,
         void **addr /* nonnull */);
-    virtual C2Error unmap(void *addr, size_t size, int *fenceFd);
+    virtual C2Status unmap(void *addr, size_t size, int *fenceFd);
     virtual bool isValid() const;
     virtual ~C2AllocationIon();
     virtual const C2Handle *handle() const;
@@ -95,7 +95,7 @@
     C2AllocationIon(int ionFd, size_t size, size_t align, unsigned heapMask, unsigned flags);
     C2AllocationIon(int ionFd, size_t size, int shareFd);
     int dup() const;
-    C2Error status() const;
+    C2Status status() const;
 
 protected:
     class Impl;
@@ -121,18 +121,28 @@
     }
 
     Impl(int ionFd, size_t capacity, int shareFd)
-        : mHandle(ionFd, -1),
+        : mInit(C2_OK),
+          mHandle(ionFd, -1),
           mMapFd(-1),
           mCapacity(capacity) {
         ion_user_handle_t buffer;
-        mInit = ion_import(mHandle.ionFd(), shareFd, &buffer);
-        if (mInit == 0) {
+        int ret = ion_import(mHandle.ionFd(), shareFd, &buffer);
+        switch (-ret) {
+        case 0:
             mHandle.setBuffer(buffer);
+            break;
+        case EBADF: // bad ion handle - should not happen
+        case ENOTTY: // bad ion driver
+            mInit = C2_CORRUPTED;
+            break;
+        default:
+            mInit = c2_map_errno<ENOMEM, EACCES, EINVAL>(-ret);
+            break;
         }
         (void)mCapacity; // TODO
     }
 
-    C2Error map(size_t offset, size_t size, C2MemoryUsage usage, int *fenceFd, void **addr) {
+    C2Status map(size_t offset, size_t size, C2MemoryUsage usage, int *fenceFd, void **addr) {
         (void)fenceFd; // TODO: wait for fence
         *addr = nullptr;
         int prot = PROT_NONE;
@@ -149,7 +159,7 @@
         size_t mapOffset = offset - alignmentBytes;
         size_t mapSize = size + alignmentBytes;
 
-        C2Error err = C2_OK;
+        C2Status err = C2_OK;
         if (mMapFd == -1) {
             int ret = ion_map(mHandle.ionFd(), mHandle.buffer(), mapSize, prot,
                               flags, mapOffset, (unsigned char**)&mMapAddr, &mMapFd);
@@ -176,7 +186,7 @@
         return err;
     }
 
-    C2Error unmap(void *addr, size_t size, int *fenceFd) {
+    C2Status unmap(void *addr, size_t size, int *fenceFd) {
         if (addr != (uint8_t *)mMapAddr + mMapAlignmentBytes ||
                 size + mMapAlignmentBytes != mMapSize) {
             return C2_BAD_VALUE;
@@ -200,7 +210,7 @@
         (void)ion_free(mHandle.ionFd(), mHandle.buffer());
     }
 
-    C2Error status() const {
+    C2Status status() const {
         return mInit;
     }
 
@@ -217,7 +227,7 @@
     }
 
 private:
-    C2Error mInit;
+    C2Status mInit;
     C2HandleIon mHandle;
     int mMapFd; // only one for now
     void *mMapAddr;
@@ -226,12 +236,12 @@
     size_t mCapacity;
 };
 
-C2Error C2AllocationIon::map(
+C2Status C2AllocationIon::map(
     size_t offset, size_t size, C2MemoryUsage usage, int *fenceFd, void **addr) {
     return mImpl->map(offset, size, usage, fenceFd, addr);
 }
 
-C2Error C2AllocationIon::unmap(void *addr, size_t size, int *fenceFd) {
+C2Status C2AllocationIon::unmap(void *addr, size_t size, int *fenceFd) {
     return mImpl->unmap(addr, size, fenceFd);
 }
 
@@ -239,7 +249,7 @@
     return mImpl->status() == C2_OK;
 }
 
-C2Error C2AllocationIon::status() const {
+C2Status C2AllocationIon::status() const {
     return mImpl->status();
 }
 
@@ -284,7 +294,7 @@
     }
 }
 
-C2Error C2AllocatorIon::allocateLinearBuffer(
+C2Status C2AllocatorIon::allocateLinearBuffer(
         uint32_t capacity, C2MemoryUsage usage, std::shared_ptr<C2LinearAllocation> *allocation) {
     if (allocation == nullptr) {
         return C2_BAD_VALUE;
@@ -311,14 +321,14 @@
 
     std::shared_ptr<C2AllocationIon> alloc
         = std::make_shared<C2AllocationIon>(mIonFd, capacity, align, heapMask, flags);
-    C2Error ret = alloc->status();
+    C2Status ret = alloc->status();
     if (ret == C2_OK) {
         *allocation = alloc;
     }
     return ret;
 }
 
-C2Error C2AllocatorIon::recreateLinearBuffer(
+C2Status C2AllocatorIon::recreateLinearBuffer(
         const C2Handle *handle, std::shared_ptr<C2LinearAllocation> *allocation) {
     *allocation = nullptr;
     if (mInit != C2_OK) {
@@ -333,7 +343,7 @@
     const C2HandleIon *h = static_cast<const C2HandleIon*>(handle);
     std::shared_ptr<C2AllocationIon> alloc
         = std::make_shared<C2AllocationIon>(mIonFd, 0 /* capacity */, h->buffer());
-    C2Error ret = alloc->status();
+    C2Status ret = alloc->status();
     if (ret == C2_OK) {
         *allocation = alloc;
     }
diff --git a/media/libstagefright/codec2/vndk/C2Buffer.cpp b/media/libstagefright/codec2/vndk/C2Buffer.cpp
index 1ffbf49..d3f0d70 100644
--- a/media/libstagefright/codec2/vndk/C2Buffer.cpp
+++ b/media/libstagefright/codec2/vndk/C2Buffer.cpp
@@ -129,26 +129,26 @@
     explicit Impl(const uint8_t *data)
         : mData(data), mError(C2_OK) {}
 
-    explicit Impl(C2Error error)
+    explicit Impl(C2Status error)
         : mData(nullptr), mError(error) {}
 
     const uint8_t *data() const {
         return mData;
     }
 
-    C2Error error() const {
+    C2Status error() const {
         return mError;
     }
 
 private:
     const uint8_t *mData;
-    C2Error mError;
+    C2Status mError;
 };
 
 C2ReadView::C2ReadView(const _C2LinearCapacityAspect *parent, const uint8_t *data)
     : _C2LinearCapacityAspect(parent), mImpl(std::make_shared<Impl>(data)) {}
 
-C2ReadView::C2ReadView(C2Error error)
+C2ReadView::C2ReadView(C2Status error)
     : _C2LinearCapacityAspect(0u), mImpl(std::make_shared<Impl>(error)) {}
 
 const uint8_t *C2ReadView::data() const {
@@ -167,7 +167,7 @@
     return C2ReadView(&newCapacity, data() + offset);
 }
 
-C2Error C2ReadView::error() {
+C2Status C2ReadView::error() const {
     return mImpl->error();
 }
 
@@ -176,33 +176,33 @@
     explicit Impl(uint8_t *base)
         : mBase(base), mError(C2_OK) {}
 
-    explicit Impl(C2Error error)
+    explicit Impl(C2Status error)
         : mBase(nullptr), mError(error) {}
 
     uint8_t *base() const {
         return mBase;
     }
 
-    C2Error error() const {
+    C2Status error() const {
         return mError;
     }
 
 private:
     uint8_t *mBase;
-    C2Error mError;
+    C2Status mError;
 };
 
 C2WriteView::C2WriteView(const _C2LinearRangeAspect *parent, uint8_t *base)
     : _C2EditableLinearRange(parent), mImpl(std::make_shared<Impl>(base)) {}
 
-C2WriteView::C2WriteView(C2Error error)
+C2WriteView::C2WriteView(C2Status error)
     : _C2EditableLinearRange(nullptr), mImpl(std::make_shared<Impl>(error)) {}
 
 uint8_t *C2WriteView::base() { return mImpl->base(); }
 
 uint8_t *C2WriteView::data() { return mImpl->base() + offset(); }
 
-C2Error C2WriteView::error() { return mImpl->error(); }
+C2Status C2WriteView::error() const { return mImpl->error(); }
 
 class C2ConstLinearBlock::Impl {
 public:
@@ -212,7 +212,7 @@
     ~Impl() {
         if (mBase != nullptr) {
             // TODO: fence
-            C2Error err = mAllocation->unmap(mBase, mSize, nullptr);
+            C2Status err = mAllocation->unmap(mBase, mSize, nullptr);
             if (err != C2_OK) {
                 // TODO: Log?
             }
@@ -238,13 +238,13 @@
 
     const uint8_t *base() const { return mBase; }
 
-    C2Error error() const { return mError; }
+    C2Status error() const { return mError; }
 
 private:
     std::shared_ptr<C2LinearAllocation> mAllocation;
     uint8_t *mBase;
     size_t mSize;
-    C2Error mError;
+    C2Status mError;
 };
 
 C2ConstLinearBlock::C2ConstLinearBlock(std::shared_ptr<C2LinearAllocation> alloc)
@@ -277,7 +277,7 @@
     ~Impl() {
         if (mBase != nullptr) {
             // TODO: fence
-            C2Error err = mAllocation->unmap(mBase, mSize, nullptr);
+            C2Status err = mAllocation->unmap(mBase, mSize, nullptr);
             if (err != C2_OK) {
                 // TODO: Log?
             }
@@ -309,7 +309,7 @@
 
     uint8_t *base() const { return mBase; }
 
-    C2Error error() const { return mError; }
+    C2Status error() const { return mError; }
 
     C2Fence fence() const { return mFence; }
 
@@ -317,7 +317,7 @@
     std::shared_ptr<C2LinearAllocation> mAllocation;
     uint8_t *mBase;
     size_t mSize;
-    C2Error mError;
+    C2Status mError;
     C2Fence mFence;
 };
 
@@ -349,14 +349,14 @@
         const std::shared_ptr<C2Allocator> &allocator)
   : mAllocator(allocator) {}
 
-C2Error C2DefaultBlockAllocator::allocateLinearBlock(
+C2Status C2DefaultBlockAllocator::allocateLinearBlock(
         uint32_t capacity,
         C2MemoryUsage usage,
         std::shared_ptr<C2LinearBlock> *block /* nonnull */) {
     block->reset();
 
     std::shared_ptr<C2LinearAllocation> alloc;
-    C2Error err = mAllocator->allocateLinearBuffer(capacity, usage, &alloc);
+    C2Status err = mAllocator->allocateLinearBuffer(capacity, usage, &alloc);
     if (err != C2_OK) {
         return err;
     }
@@ -392,16 +392,16 @@
 public:
     Impl(uint8_t *const *data, const C2PlaneLayout &layout)
         : mData(data), mLayout(layout), mError(C2_OK) {}
-    explicit Impl(C2Error error) : mData(nullptr), mError(error) {}
+    explicit Impl(C2Status error) : mData(nullptr), mError(error) {}
 
     uint8_t *const *data() const { return mData; }
     const C2PlaneLayout &layout() const { return mLayout; }
-    C2Error error() const { return mError; }
+    C2Status error() const { return mError; }
 
 private:
     uint8_t *const *mData;
     C2PlaneLayout mLayout;
-    C2Error mError;
+    C2Status mError;
 };
 
 C2GraphicView::C2GraphicView(
@@ -410,7 +410,7 @@
         const C2PlaneLayout& layout)
     : _C2PlanarSection(parent), mImpl(new Impl(data, layout)) {}
 
-C2GraphicView::C2GraphicView(C2Error error)
+C2GraphicView::C2GraphicView(C2Status error)
     : _C2PlanarSection(nullptr), mImpl(new Impl(error)) {}
 
 const uint8_t *const *C2GraphicView::data() const {
@@ -437,7 +437,7 @@
     return view;
 }
 
-C2Error C2GraphicView::error() const {
+C2Status C2GraphicView::error() const {
     return mImpl->error();
 }
 
@@ -453,12 +453,12 @@
         }
     }
 
-    C2Error map(C2Rect rect) {
+    C2Status map(C2Rect rect) {
         if (mData[0] != nullptr) {
             // Already mapped.
             return C2_OK;
         }
-        C2Error err = mAllocation->map(
+        C2Status err = mAllocation->map(
                 rect,
                 { C2MemoryUsage::kSoftwareRead, 0 },
                 nullptr,
@@ -493,7 +493,7 @@
     : C2Block2D(alloc), mImpl(new Impl(alloc)), mFence(fence) {}
 
 C2Acquirable<const C2GraphicView> C2ConstGraphicBlock::map() const {
-    C2Error err = mImpl->map(crop());
+    C2Status err = mImpl->map(crop());
     if (err != C2_OK) {
         C2DefaultGraphicView view(err);
         return C2AcquirableConstGraphicView(err, mFence, view);
@@ -518,13 +518,13 @@
         }
     }
 
-    C2Error map(C2Rect rect) {
+    C2Status map(C2Rect rect) {
         if (mData[0] != nullptr) {
             // Already mapped.
             return C2_OK;
         }
         uint8_t *data[C2PlaneLayout::MAX_NUM_PLANES];
-        C2Error err = mAllocation->map(
+        C2Status err = mAllocation->map(
                 rect,
                 { C2MemoryUsage::kSoftwareRead, C2MemoryUsage::kSoftwareWrite },
                 nullptr,
@@ -560,7 +560,7 @@
     : C2Block2D(alloc), mImpl(new Impl(alloc)) {}
 
 C2Acquirable<C2GraphicView> C2GraphicBlock::map() {
-    C2Error err = mImpl->map(crop());
+    C2Status err = mImpl->map(crop());
     if (err != C2_OK) {
         C2DefaultGraphicView view(err);
         // TODO: fence
@@ -579,7 +579,7 @@
         const std::shared_ptr<C2Allocator> &allocator)
   : mAllocator(allocator) {}
 
-C2Error C2DefaultGraphicBlockAllocator::allocateGraphicBlock(
+C2Status C2DefaultGraphicBlockAllocator::allocateGraphicBlock(
         uint32_t width,
         uint32_t height,
         uint32_t format,
@@ -588,7 +588,7 @@
     block->reset();
 
     std::shared_ptr<C2GraphicAllocation> alloc;
-    C2Error err = mAllocator->allocateGraphicBuffer(width, height, format, usage, &alloc);
+    C2Status err = mAllocator->allocateGraphicBuffer(width, height, format, usage, &alloc);
     if (err != C2_OK) {
         return err;
     }
@@ -650,7 +650,7 @@
 
     const C2BufferData &data() const { return mData; }
 
-    C2Error registerOnDestroyNotify(OnDestroyNotify onDestroyNotify, void *arg) {
+    C2Status registerOnDestroyNotify(OnDestroyNotify onDestroyNotify, void *arg) {
         auto it = std::find_if(
                 mNotify.begin(), mNotify.end(),
                 [onDestroyNotify, arg] (const auto &pair) {
@@ -663,7 +663,7 @@
         return C2_OK;
     }
 
-    C2Error unregisterOnDestroyNotify(OnDestroyNotify onDestroyNotify, void *arg) {
+    C2Status unregisterOnDestroyNotify(OnDestroyNotify onDestroyNotify, void *arg) {
         auto it = std::find_if(
                 mNotify.begin(), mNotify.end(),
                 [onDestroyNotify, arg] (const auto &pair) {
@@ -684,7 +684,7 @@
         return result;
     }
 
-    C2Error setInfo(const std::shared_ptr<C2Info> &info) {
+    C2Status setInfo(const std::shared_ptr<C2Info> &info) {
         // To "update" you need to erase the existing one if any, and then insert.
         (void) mInfos.erase(info->type());
         (void) mInfos.insert({ info->type(), info });
@@ -720,11 +720,11 @@
 
 const C2BufferData C2Buffer::data() const { return mImpl->data(); }
 
-C2Error C2Buffer::registerOnDestroyNotify(OnDestroyNotify onDestroyNotify, void *arg) {
+C2Status C2Buffer::registerOnDestroyNotify(OnDestroyNotify onDestroyNotify, void *arg) {
     return mImpl->registerOnDestroyNotify(onDestroyNotify, arg);
 }
 
-C2Error C2Buffer::unregisterOnDestroyNotify(OnDestroyNotify onDestroyNotify, void *arg) {
+C2Status C2Buffer::unregisterOnDestroyNotify(OnDestroyNotify onDestroyNotify, void *arg) {
     return mImpl->unregisterOnDestroyNotify(onDestroyNotify, arg);
 }
 
@@ -732,7 +732,7 @@
     return mImpl->infos();
 }
 
-C2Error C2Buffer::setInfo(const std::shared_ptr<C2Info> &info) {
+C2Status C2Buffer::setInfo(const std::shared_ptr<C2Info> &info) {
     return mImpl->setInfo(info);
 }
 
diff --git a/media/libstagefright/codec2/vndk/C2Store.cpp b/media/libstagefright/codec2/vndk/C2Store.cpp
index f21a3f0..42bdf0e 100644
--- a/media/libstagefright/codec2/vndk/C2Store.cpp
+++ b/media/libstagefright/codec2/vndk/C2Store.cpp
@@ -35,7 +35,7 @@
     C2PlatformAllocatorStore(
         /* ionmapper */
     );
-    virtual status_t createAllocator(ID id, std::shared_ptr<C2Allocator> *const allocator);
+    virtual C2Status createAllocator(ID id, std::shared_ptr<C2Allocator> *const allocator);
 
 private:
     // returns a shared-singleton ion allocator
@@ -48,7 +48,7 @@
 C2PlatformAllocatorStore::C2PlatformAllocatorStore() {
 }
 
-status_t C2PlatformAllocatorStore::createAllocator(
+C2Status C2PlatformAllocatorStore::createAllocator(
         ID id, std::shared_ptr<C2Allocator> *const allocator) {
     allocator->reset();
     switch (id) {
diff --git a/media/libstagefright/codec2/vndk/include/C2AllocatorGralloc.h b/media/libstagefright/codec2/vndk/include/C2AllocatorGralloc.h
index 94f74c8..9bfd987 100644
--- a/media/libstagefright/codec2/vndk/include/C2AllocatorGralloc.h
+++ b/media/libstagefright/codec2/vndk/include/C2AllocatorGralloc.h
@@ -30,17 +30,17 @@
     typedef std::function<int (C2MemoryUsage, size_t,
                       /* => */ size_t*, unsigned*, unsigned*)> usage_mapper_fn;
 
-    virtual C2Error allocateGraphicBuffer(
+    virtual C2Status allocateGraphicBuffer(
             uint32_t width, uint32_t height, uint32_t format, C2MemoryUsage usage,
             std::shared_ptr<C2GraphicAllocation> *allocation) override;
 
-    virtual C2Error recreateGraphicBuffer(
+    virtual C2Status recreateGraphicBuffer(
             const C2Handle *handle,
             std::shared_ptr<C2GraphicAllocation> *allocation) override;
 
     C2AllocatorGralloc();
 
-    C2Error status() const;
+    C2Status status() const;
 
     virtual ~C2AllocatorGralloc();
 
diff --git a/media/libstagefright/codec2/vndk/include/C2AllocatorIon.h b/media/libstagefright/codec2/vndk/include/C2AllocatorIon.h
index a453a7d..00c33fe 100644
--- a/media/libstagefright/codec2/vndk/include/C2AllocatorIon.h
+++ b/media/libstagefright/codec2/vndk/include/C2AllocatorIon.h
@@ -29,22 +29,22 @@
     typedef std::function<int (C2MemoryUsage, size_t,
                       /* => */ size_t*, unsigned*, unsigned*)> usage_mapper_fn;
 
-    virtual C2Error allocateLinearBuffer(
+    virtual C2Status allocateLinearBuffer(
             uint32_t capacity, C2MemoryUsage usage,
             std::shared_ptr<C2LinearAllocation> *allocation) override;
 
-    virtual C2Error recreateLinearBuffer(
+    virtual C2Status recreateLinearBuffer(
             const C2Handle *handle,
             std::shared_ptr<C2LinearAllocation> *allocation) override;
 
     C2AllocatorIon();
 
-    C2Error status() const { return mInit; }
+    C2Status status() const { return mInit; }
 
     virtual ~C2AllocatorIon();
 
 private:
-    C2Error mInit;
+    C2Status mInit;
     int mIonFd;
     usage_mapper_fn mUsageMapper;
 };
diff --git a/media/libstagefright/codec2/vndk/include/C2BufferPriv.h b/media/libstagefright/codec2/vndk/include/C2BufferPriv.h
index 6a8f94e..f1e8acb 100644
--- a/media/libstagefright/codec2/vndk/include/C2BufferPriv.h
+++ b/media/libstagefright/codec2/vndk/include/C2BufferPriv.h
@@ -29,7 +29,7 @@
 
     virtual ~C2DefaultBlockAllocator() = default;
 
-    virtual C2Error allocateLinearBlock(
+    virtual C2Status allocateLinearBlock(
             uint32_t capacity,
             C2MemoryUsage usage,
             std::shared_ptr<C2LinearBlock> *block /* nonnull */) override;
@@ -45,7 +45,7 @@
 
     virtual ~C2DefaultGraphicBlockAllocator() = default;
 
-    virtual C2Error allocateGraphicBlock(
+    virtual C2Status allocateGraphicBlock(
             uint32_t width,
             uint32_t height,
             uint32_t format,
diff --git a/media/libstagefright/codec2/vndk/include/C2ErrnoUtils.h b/media/libstagefright/codec2/vndk/include/C2ErrnoUtils.h
index f834cdb..adeb42e 100644
--- a/media/libstagefright/codec2/vndk/include/C2ErrnoUtils.h
+++ b/media/libstagefright/codec2/vndk/include/C2ErrnoUtils.h
@@ -23,32 +23,32 @@
 namespace android {
 
 // standard ERRNO mappings
-template<int N> constexpr C2Error _c2_errno2error_impl();
-template<> constexpr C2Error _c2_errno2error_impl<0>()       { return C2_OK; }
-template<> constexpr C2Error _c2_errno2error_impl<EINVAL>()  { return C2_BAD_VALUE; }
-template<> constexpr C2Error _c2_errno2error_impl<EACCES>()  { return C2_NO_PERMISSION; }
-template<> constexpr C2Error _c2_errno2error_impl<EPERM>()   { return C2_NO_PERMISSION; }
-template<> constexpr C2Error _c2_errno2error_impl<ENOMEM>()  { return C2_NO_MEMORY; }
+template<int N> constexpr C2Status _c2_errno2status_impl();
+template<> constexpr C2Status _c2_errno2status_impl<0>()       { return C2_OK; }
+template<> constexpr C2Status _c2_errno2status_impl<EINVAL>()  { return C2_BAD_VALUE; }
+template<> constexpr C2Status _c2_errno2status_impl<EACCES>()  { return C2_NO_PERMISSION; }
+template<> constexpr C2Status _c2_errno2status_impl<EPERM>()   { return C2_NO_PERMISSION; }
+template<> constexpr C2Status _c2_errno2status_impl<ENOMEM>()  { return C2_NO_MEMORY; }
 
-// map standard errno-s to the equivalent C2Error
+// map standard errno-s to the equivalent C2Status
 template<int... N> struct _c2_map_errno_impl;
 template<int E, int ... N> struct _c2_map_errno_impl<E, N...> {
-    static C2Error map(int result) {
+    static C2Status map(int result) {
         if (result == E) {
-            return _c2_errno2error_impl<E>();
+            return _c2_errno2status_impl <E>();
         } else {
             return _c2_map_errno_impl<N...>::map(result);
         }
     }
 };
 template<> struct _c2_map_errno_impl<> {
-    static C2Error map(int result) {
+    static C2Status map(int result) {
         return result == 0 ? C2_OK : C2_CORRUPTED;
     }
 };
 
 template<int... N>
-C2Error c2_map_errno(int result) {
+C2Status c2_map_errno(int result) {
     return _c2_map_errno_impl<N...>::map(result);
 }
 
diff --git a/media/libstagefright/codecs/avcdec/C2SoftAvcDec.cpp b/media/libstagefright/codecs/avcdec/C2SoftAvcDec.cpp
index 5f55e1e..f94768a 100644
--- a/media/libstagefright/codecs/avcdec/C2SoftAvcDec.cpp
+++ b/media/libstagefright/codecs/avcdec/C2SoftAvcDec.cpp
@@ -94,11 +94,15 @@
     bool validateField(
             const C2FieldSupportedValues &supportedValues, const T &value) {
         switch (supportedValues.type) {
+        case C2FieldSupportedValues::EMPTY:
+            {
+                return false;
+            }
         case C2FieldSupportedValues::RANGE:
             {
                 // TODO: handle step, nom, denom
-                return Getter<T>::get(supportedValues.range.min) < value
-                        && value < Getter<T>::get(supportedValues.range.max);
+                return Getter<T>::get(supportedValues.range.min) <= value
+                        && value <= Getter<T>::get(supportedValues.range.max);
             }
         case C2FieldSupportedValues::VALUES:
             {
@@ -153,7 +157,7 @@
         const C2FieldSupportedValues &supportedValues = mSupportedValues.at(field).supported;
         if (!validateField(supportedValues, param->mValue)) {
             return std::unique_ptr<C2SettingResult>(
-                    new C2SettingResult {field, C2SettingResult::BAD_VALUE, nullptr, {}});
+                    new C2SettingResult {C2SettingResult::BAD_VALUE, {field, nullptr}, {}});
         }
         return nullptr;
     }
@@ -171,13 +175,13 @@
         const C2FieldSupportedValues &supportedWidth = mSupportedValues.at(field).supported;
         if (!validateField(supportedWidth, param->mWidth)) {
             return std::unique_ptr<C2SettingResult>(
-                    new C2SettingResult {field, C2SettingResult::BAD_VALUE, nullptr, {}});
+                    new C2SettingResult {C2SettingResult::BAD_VALUE, {field, nullptr}, {}});
         }
         field = C2ParamField(param, &T::mHeight);
         const C2FieldSupportedValues &supportedHeight = mSupportedValues.at(field).supported;
         if (!validateField(supportedHeight, param->mHeight)) {
             return std::unique_ptr<C2SettingResult>(
-                    new C2SettingResult {field, C2SettingResult::BAD_VALUE, nullptr, {}});
+                    new C2SettingResult {C2SettingResult::BAD_VALUE, {field, nullptr}, {}});
         }
         return nullptr;
     }
@@ -191,7 +195,7 @@
         T* param = (T*)c2param;
         if (strncmp(param->m.mValue, mExpected, param->flexCount()) != 0) {
             return std::unique_ptr<C2SettingResult>(
-                    new C2SettingResult {C2ParamField(param, &T::m), C2SettingResult::BAD_VALUE, nullptr, {}});
+                    new C2SettingResult {C2SettingResult::BAD_VALUE, {C2ParamField(param, &T::m), nullptr}, {}});
         }
         return nullptr;
     }
@@ -428,7 +432,7 @@
     return mId;
 }
 
-status_t C2SoftAvcDecIntf::query_nb(
+C2Status C2SoftAvcDecIntf::query_nb(
         const std::vector<C2Param* const> & stackParams,
         const std::vector<C2Param::Index> & heapParamIndices,
         std::vector<std::unique_ptr<C2Param>>* const heapParams) const {
@@ -461,10 +465,10 @@
     return C2_OK;
 }
 
-status_t C2SoftAvcDecIntf::config_nb(
+C2Status C2SoftAvcDecIntf::config_nb(
         const std::vector<C2Param* const> &params,
         std::vector<std::unique_ptr<C2SettingResult>>* const failures) {
-    status_t err = C2_OK;
+    C2Status err = C2_OK;
     for (C2Param *param : params) {
         uint32_t index = restoreIndex(param);
         if (mParams.count(index) == 0) {
@@ -485,20 +489,20 @@
     return err;
 }
 
-status_t C2SoftAvcDecIntf::commit_sm(
+C2Status C2SoftAvcDecIntf::commit_sm(
         const std::vector<C2Param* const> &params,
         std::vector<std::unique_ptr<C2SettingResult>>* const failures) {
     // TODO
     return config_nb(params, failures);
 }
 
-status_t C2SoftAvcDecIntf::createTunnel_sm(node_id targetComponent) {
+C2Status C2SoftAvcDecIntf::createTunnel_sm(node_id targetComponent) {
     // Tunneling is not supported
     (void) targetComponent;
     return C2_UNSUPPORTED;
 }
 
-status_t C2SoftAvcDecIntf::releaseTunnel_sm(node_id targetComponent) {
+C2Status C2SoftAvcDecIntf::releaseTunnel_sm(node_id targetComponent) {
     // Tunneling is not supported
     (void) targetComponent;
     return C2_UNSUPPORTED;
@@ -508,22 +512,25 @@
     return mParamReflector;
 }
 
-status_t C2SoftAvcDecIntf::getSupportedParams(
+C2Status C2SoftAvcDecIntf::getSupportedParams(
         std::vector<std::shared_ptr<C2ParamDescriptor>> * const params) const {
     params->insert(params->begin(), mParamDescs.begin(), mParamDescs.end());
     return C2_OK;
 }
 
-status_t C2SoftAvcDecIntf::getSupportedValues(
-        const std::vector<const C2ParamField> &fields,
-        std::vector<C2FieldSupportedValues>* const values) const {
-    for (const auto &field : fields) {
-        if (mSupportedValues.count(field) == 0) {
-            return BAD_VALUE;
+C2Status C2SoftAvcDecIntf::getSupportedValues(
+        std::vector<C2FieldSupportedValuesQuery> &fields) const {
+    C2Status res = C2_OK;
+    for (C2FieldSupportedValuesQuery &query : fields) {
+        if (mSupportedValues.count(query.field) == 0) {
+            query.status = C2_BAD_INDEX;
+            res = C2_BAD_INDEX;
+        } else {
+            query.status = C2_OK;
+            query.values = mSupportedValues.at(query.field).supported;
         }
-        values->push_back(mSupportedValues.at(field).supported);
     }
-    return C2_OK;
+    return res;
 }
 
 void C2SoftAvcDecIntf::updateSupportedValues() {
@@ -644,7 +651,7 @@
     CHECK_EQ(deInitDecoder(), (status_t)OK);
 }
 
-status_t C2SoftAvcDec::queue_nb(
+C2Status C2SoftAvcDec::queue_nb(
         std::list<std::unique_ptr<C2Work>>* const items) {
     if (!mThread->isRunning()) {
         return C2_CORRUPTED;
@@ -659,13 +666,13 @@
     return C2_OK;
 }
 
-status_t C2SoftAvcDec::announce_nb(const std::vector<C2WorkOutline> &items) {
+C2Status C2SoftAvcDec::announce_nb(const std::vector<C2WorkOutline> &items) {
     // Tunneling is not supported
     (void) items;
     return C2_UNSUPPORTED;
 }
 
-status_t C2SoftAvcDec::flush_sm(
+C2Status C2SoftAvcDec::flush_sm(
         bool flushThrough, std::list<std::unique_ptr<C2Work>>* const flushedWork) {
     // Tunneling is not supported
     (void) flushThrough;
@@ -691,7 +698,7 @@
     return C2_OK;
 }
 
-status_t C2SoftAvcDec::drain_nb(bool drainThrough) {
+C2Status C2SoftAvcDec::drain_nb(bool drainThrough) {
     // Tunneling is not supported
     (void) drainThrough;
 
@@ -707,14 +714,14 @@
     return C2_OK;
 }
 
-status_t C2SoftAvcDec::start() {
+C2Status C2SoftAvcDec::start() {
     if (!mThread->isRunning()) {
         mThread->start(shared_from_this());
     }
     return C2_OK;
 }
 
-status_t C2SoftAvcDec::stop() {
+C2Status C2SoftAvcDec::stop() {
     ALOGV("stop");
     std::chrono::system_clock::time_point now = std::chrono::system_clock::now();
     std::chrono::system_clock::time_point deadline = now + std::chrono::milliseconds(500);
diff --git a/media/libstagefright/codecs/avcdec/C2SoftAvcDec.h b/media/libstagefright/codecs/avcdec/C2SoftAvcDec.h
index 6a83d1d..cc33083 100644
--- a/media/libstagefright/codecs/avcdec/C2SoftAvcDec.h
+++ b/media/libstagefright/codecs/avcdec/C2SoftAvcDec.h
@@ -85,24 +85,23 @@
     // From C2ComponentInterface
     virtual C2String getName() const override;
     virtual node_id getId() const override;
-    virtual status_t query_nb(
+    virtual C2Status query_nb(
             const std::vector<C2Param* const> &stackParams,
             const std::vector<C2Param::Index> &heapParamIndices,
             std::vector<std::unique_ptr<C2Param>>* const heapParams) const override;
-    virtual status_t config_nb(
+    virtual C2Status config_nb(
             const std::vector<C2Param* const> &params,
             std::vector<std::unique_ptr<C2SettingResult>>* const failures) override;
-    virtual status_t commit_sm(
+    virtual C2Status commit_sm(
             const std::vector<C2Param* const> &params,
             std::vector<std::unique_ptr<C2SettingResult>>* const failures) override;
-    virtual status_t createTunnel_sm(node_id targetComponent) override;
-    virtual status_t releaseTunnel_sm(node_id targetComponent) override;
+    virtual C2Status createTunnel_sm(node_id targetComponent) override;
+    virtual C2Status releaseTunnel_sm(node_id targetComponent) override;
     virtual std::shared_ptr<C2ParamReflector> getParamReflector() const override;
-    virtual status_t getSupportedParams(
+    virtual C2Status getSupportedParams(
             std::vector<std::shared_ptr<C2ParamDescriptor>> * const params) const override;
-    virtual status_t getSupportedValues(
-            const std::vector<const C2ParamField> &fields,
-            std::vector<C2FieldSupportedValues>* const values) const override;
+    virtual C2Status getSupportedValues(
+            std::vector<C2FieldSupportedValuesQuery> &fields) const override;
 
 private:
     class ParamReflector;
@@ -150,13 +149,13 @@
     virtual ~C2SoftAvcDec();
 
     // From C2Component
-    virtual status_t queue_nb(std::list<std::unique_ptr<C2Work>>* const items) override;
-    virtual status_t announce_nb(const std::vector<C2WorkOutline> &items) override;
-    virtual status_t flush_sm(
+    virtual C2Status queue_nb(std::list<std::unique_ptr<C2Work>>* const items) override;
+    virtual C2Status announce_nb(const std::vector<C2WorkOutline> &items) override;
+    virtual C2Status flush_sm(
             bool flushThrough, std::list<std::unique_ptr<C2Work>>* const flushedWork) override;
-    virtual status_t drain_nb(bool drainThrough) override;
-    virtual status_t start() override;
-    virtual status_t stop() override;
+    virtual C2Status drain_nb(bool drainThrough) override;
+    virtual C2Status start() override;
+    virtual C2Status stop() override;
     virtual void reset() override;
     virtual void release() override;
     virtual std::shared_ptr<C2ComponentInterface> intf() override;
@@ -228,9 +227,9 @@
     bool mChangingResolution;
     bool mFlushNeeded;
     bool mSignalledError;
-    int32_t mWidth;
-    int32_t mHeight;
-    int32_t mStride;
+    uint32_t mWidth;
+    uint32_t mHeight;
+    uint32_t mStride;
     size_t mInputOffset;
 
     void processQueue();
diff --git a/services/mediaanalytics/MediaAnalyticsService.cpp b/services/mediaanalytics/MediaAnalyticsService.cpp
index f08be50..83992aa 100644
--- a/services/mediaanalytics/MediaAnalyticsService.cpp
+++ b/services/mediaanalytics/MediaAnalyticsService.cpp
@@ -318,6 +318,7 @@
                 saveItem(mFinalized, oitem, 0);
             }
             // new record could itself be marked finalized...
+            id = item->getSessionID();
             if (finalizing) {
                 summarize(item);
                 saveItem(mFinalized, item, 0);
@@ -325,16 +326,15 @@
             } else {
                 saveItem(mOpen, item, 1);
             }
-            id = item->getSessionID();
         } else {
             // combine the records, send it to finalized if appropriate
             oitem->merge(item);
+            id = oitem->getSessionID();
             if (finalizing) {
                 summarize(oitem);
                 saveItem(mFinalized, oitem, 0);
                 mItemsFinalized++;
             }
-            id = oitem->getSessionID();
 
             // we're responsible for disposing of the dead record
             delete item;
@@ -614,17 +614,28 @@
 // caller should hold mLock
 void MediaAnalyticsService::saveItem(List<MediaAnalyticsItem *> *l, MediaAnalyticsItem * item, int front) {
 
-    // adding at back of queue (fifo order)
     if (front)  {
+        // for non-finalized stuff, since we expect to reference it again soon,
+        // make it quicker to find (nearer the front of our list)
         l->push_front(item);
     } else {
+        // for finalized records, which we want to dump 'in sequence order'
         l->push_back(item);
     }
 
+    // our reclaim process is for oldest-first queues
+    if (front) {
+        return;
+    }
+
+
     // keep removing old records the front until we're in-bounds (count)
     if (mMaxRecords > 0) {
         while (l->size() > (size_t) mMaxRecords) {
             MediaAnalyticsItem * oitem = *(l->begin());
+            if (oitem == item) {
+                break;
+            }
             l->erase(l->begin());
             delete oitem;
             mItemsDiscarded++;
@@ -638,6 +649,9 @@
         while (l->size() > 0) {
             MediaAnalyticsItem * oitem = *(l->begin());
             nsecs_t when = oitem->getTimestamp();
+            if (oitem == item) {
+                break;
+            }
             // careful about timejumps too
             if ((now > when) && (now-when) <= mMaxRecordAgeNs) {
                 // this (and the rest) are recent enough to keep