Merge "Allow clearing effect hal buffers"
diff --git a/camera/include/camera/camera2/CaptureRequest.h b/camera/include/camera/camera2/CaptureRequest.h
index 0180183..e39dfcf 100644
--- a/camera/include/camera/camera2/CaptureRequest.h
+++ b/camera/include/camera/camera2/CaptureRequest.h
@@ -43,6 +43,7 @@
     CameraMetadata          mMetadata;
     Vector<sp<Surface> >    mSurfaceList;
     bool                    mIsReprocess;
+    void*                   mContext; // arbitrary user context from NDK apps, null for java apps
 
     /**
      * Keep impl up-to-date with CaptureRequest.java in frameworks/base
diff --git a/camera/ndk/NdkCaptureRequest.cpp b/camera/ndk/NdkCaptureRequest.cpp
index 5b4c180..ac1856b 100644
--- a/camera/ndk/NdkCaptureRequest.cpp
+++ b/camera/ndk/NdkCaptureRequest.cpp
@@ -142,3 +142,40 @@
     delete request;
     return;
 }
+
+EXPORT
+camera_status_t ACaptureRequest_setUserContext(
+        ACaptureRequest* request, void* context) {
+    if (request == nullptr) {
+        ALOGE("%s: invalid argument! request is NULL", __FUNCTION__);
+        return ACAMERA_ERROR_INVALID_PARAMETER;
+    }
+    return request->setContext(context);
+}
+
+EXPORT
+camera_status_t ACaptureRequest_getUserContext(
+        const ACaptureRequest* request, /*out*/void** context) {
+    if (request == nullptr || context == nullptr) {
+        ALOGE("%s: invalid argument! request %p, context %p",
+                __FUNCTION__, request, context);
+        return ACAMERA_ERROR_INVALID_PARAMETER;
+    }
+    return request->getContext(context);
+}
+
+EXPORT
+ACaptureRequest* ACaptureRequest_copy(const ACaptureRequest* src) {
+    ATRACE_CALL();
+    if (src == nullptr) {
+        ALOGE("%s: src is null!", __FUNCTION__);
+        return nullptr;
+    }
+
+    ACaptureRequest* pRequest = new ACaptureRequest();
+    pRequest->settings = new ACameraMetadata(*(src->settings));
+    pRequest->targets  = new ACameraOutputTargets();
+    *(pRequest->targets)  = *(src->targets);
+    pRequest->context = src->context;
+    return pRequest;
+}
diff --git a/camera/ndk/impl/ACameraDevice.cpp b/camera/ndk/impl/ACameraDevice.cpp
index 9ce0ac8..45fa28e 100644
--- a/camera/ndk/impl/ACameraDevice.cpp
+++ b/camera/ndk/impl/ACameraDevice.cpp
@@ -372,6 +372,7 @@
     sp<CaptureRequest> req(new CaptureRequest());
     req->mMetadata = request->settings->getInternalData();
     req->mIsReprocess = false; // NDK does not support reprocessing yet
+    req->mContext = request->context;
 
     for (auto outputTarget : request->targets->mOutputs) {
         ANativeWindow* anw = outputTarget.mWindow;
@@ -398,6 +399,7 @@
         ACameraOutputTarget outputTarget(anw);
         pRequest->targets->mOutputs.insert(outputTarget);
     }
+    pRequest->context = req->mContext;
     return pRequest;
 }
 
diff --git a/camera/ndk/impl/ACaptureRequest.h b/camera/ndk/impl/ACaptureRequest.h
index e5b453e..06b2cc3 100644
--- a/camera/ndk/impl/ACaptureRequest.h
+++ b/camera/ndk/impl/ACaptureRequest.h
@@ -45,8 +45,19 @@
 };
 
 struct ACaptureRequest {
+    camera_status_t setContext(void* ctx) {
+        context = ctx;
+        return ACAMERA_OK;
+    }
+
+    camera_status_t getContext(void** ctx) const {
+        *ctx = context;
+        return ACAMERA_OK;
+    }
+
     ACameraMetadata*      settings;
     ACameraOutputTargets* targets;
+    void*                 context;
 };
 
 #endif // _ACAPTURE_REQUEST_H
diff --git a/camera/ndk/include/camera/NdkCaptureRequest.h b/camera/ndk/include/camera/NdkCaptureRequest.h
index c62ba2c..4961ce3 100644
--- a/camera/ndk/include/camera/NdkCaptureRequest.h
+++ b/camera/ndk/include/camera/NdkCaptureRequest.h
@@ -305,6 +305,58 @@
 
 #endif /* __ANDROID_API__ >= 24 */
 
+#if __ANDROID_API__ >= 28
+
+/**
+ * Associate an arbitrary user context pointer to the {@link ACaptureRequest}
+ *
+ * This method is useful for user to identify the capture request in capture session callbacks.
+ * The context is NULL for newly created request.
+ * {@link ACameraOutputTarget_free} will not free the context. Also calling this method twice
+ * will not cause the previous context be freed.
+ * Also note that calling this method after the request has been sent to capture session will not
+ * change the context pointer in the capture callbacks.
+ *
+ * @param request the {@link ACaptureRequest} of interest.
+ * @param context the user context pointer to be associated with this capture request.
+ *
+ * @return <ul>
+ *         <li>{@link ACAMERA_OK} if the method call succeeds.</li>
+ *         <li>{@link ACAMERA_ERROR_INVALID_PARAMETER} if request is NULL.</li></ul>
+ */
+camera_status_t ACaptureRequest_setUserContext(
+        ACaptureRequest* request, void* context);
+
+/**
+ * Get the user context pointer of the {@link ACaptureRequest}
+ *
+ * This method is useful for user to identify the capture request in capture session callbacks.
+ * The context is NULL for newly created request.
+ *
+ * @param request the {@link ACaptureRequest} of interest.
+ * @param context the user context pointer of this capture request.
+ *
+ * @return <ul>
+ *         <li>{@link ACAMERA_OK} if the method call succeeds.</li>
+ *         <li>{@link ACAMERA_ERROR_INVALID_PARAMETER} if request is NULL.</li></ul>
+ */
+camera_status_t ACaptureRequest_getUserContext(
+        const ACaptureRequest* request, /*out*/void** context);
+
+/**
+ * Create a copy of input {@link ACaptureRequest}.
+ *
+ * <p>The returned ACaptureRequest must be freed by the application by {@link ACaptureRequest_free}
+ * after application is done using it.</p>
+ *
+ * @param src the input {@link ACaptureRequest} to be copied.
+ *
+ * @return a valid ACaptureRequest pointer or NULL if the input request cannot be copied.
+ */
+ACaptureRequest* ACaptureRequest_copy(const ACaptureRequest* src);
+
+#endif /* __ANDROID_API__ >= 28 */
+
 __END_DECLS
 
 #endif /* _NDK_CAPTURE_REQUEST_H */
diff --git a/camera/ndk/libcamera2ndk.map.txt b/camera/ndk/libcamera2ndk.map.txt
index 0a8a6e9..58d239b 100644
--- a/camera/ndk/libcamera2ndk.map.txt
+++ b/camera/ndk/libcamera2ndk.map.txt
@@ -26,9 +26,11 @@
     ACameraOutputTarget_create;
     ACameraOutputTarget_free;
     ACaptureRequest_addTarget;
+    ACaptureRequest_copy;
     ACaptureRequest_free;
     ACaptureRequest_getAllTags;
     ACaptureRequest_getConstEntry;
+    ACaptureRequest_getUserContext;
     ACaptureRequest_removeTarget;
     ACaptureRequest_setEntry_double;
     ACaptureRequest_setEntry_float;
@@ -36,6 +38,7 @@
     ACaptureRequest_setEntry_i64;
     ACaptureRequest_setEntry_rational;
     ACaptureRequest_setEntry_u8;
+    ACaptureRequest_setUserContext;
     ACaptureSessionOutputContainer_add;
     ACaptureSessionOutputContainer_create;
     ACaptureSessionOutputContainer_free;
diff --git a/media/libaudioclient/AudioRecord.cpp b/media/libaudioclient/AudioRecord.cpp
index 26a320c..2432cac 100644
--- a/media/libaudioclient/AudioRecord.cpp
+++ b/media/libaudioclient/AudioRecord.cpp
@@ -89,7 +89,8 @@
         audio_input_flags_t flags,
         uid_t uid,
         pid_t pid,
-        const audio_attributes_t* pAttributes)
+        const audio_attributes_t* pAttributes,
+        audio_port_handle_t selectedDeviceId)
     : mActive(false),
       mStatus(NO_INIT),
       mOpPackageName(opPackageName),
@@ -97,12 +98,11 @@
       mPreviousPriority(ANDROID_PRIORITY_NORMAL),
       mPreviousSchedulingGroup(SP_DEFAULT),
       mProxy(NULL),
-      mSelectedDeviceId(AUDIO_PORT_HANDLE_NONE),
       mPortId(AUDIO_PORT_HANDLE_NONE)
 {
     mStatus = set(inputSource, sampleRate, format, channelMask, frameCount, cbf, user,
             notificationFrames, false /*threadCanCallJava*/, sessionId, transferType, flags,
-            uid, pid, pAttributes);
+            uid, pid, pAttributes, selectedDeviceId);
 }
 
 AudioRecord::~AudioRecord()
@@ -148,7 +148,8 @@
         audio_input_flags_t flags,
         uid_t uid,
         pid_t pid,
-        const audio_attributes_t* pAttributes)
+        const audio_attributes_t* pAttributes,
+        audio_port_handle_t selectedDeviceId)
 {
     ALOGV("set(): inputSource %d, sampleRate %u, format %#x, channelMask %#x, frameCount %zu, "
           "notificationFrames %u, sessionId %d, transferType %d, flags %#x, opPackageName %s "
@@ -156,6 +157,8 @@
           inputSource, sampleRate, format, channelMask, frameCount, notificationFrames,
           sessionId, transferType, flags, String8(mOpPackageName).string(), uid, pid);
 
+    mSelectedDeviceId = selectedDeviceId;
+
     switch (transferType) {
     case TRANSFER_DEFAULT:
         if (cbf == NULL || threadCanCallJava) {
@@ -489,6 +492,7 @@
                 mAudioRecord->stop();
             }
             android_atomic_or(CBLK_INVALID, &mCblk->mFlags);
+            mProxy->interrupt();
         }
     }
     return NO_ERROR;
diff --git a/media/libaudioclient/AudioTrack.cpp b/media/libaudioclient/AudioTrack.cpp
index 36961d6..30f97ac 100644
--- a/media/libaudioclient/AudioTrack.cpp
+++ b/media/libaudioclient/AudioTrack.cpp
@@ -2651,23 +2651,28 @@
 
 status_t AudioTrack::dump(int fd, const Vector<String16>& args __unused) const
 {
-
-    const size_t SIZE = 256;
-    char buffer[SIZE];
     String8 result;
 
     result.append(" AudioTrack::dump\n");
-    snprintf(buffer, 255, "  stream type(%d), left - right volume(%f, %f)\n", mStreamType,
-            mVolume[AUDIO_INTERLEAVE_LEFT], mVolume[AUDIO_INTERLEAVE_RIGHT]);
-    result.append(buffer);
-    snprintf(buffer, 255, "  format(%d), channel count(%d), frame count(%zu)\n", mFormat,
-            mChannelCount, mFrameCount);
-    result.append(buffer);
-    snprintf(buffer, 255, "  sample rate(%u), speed(%f), status(%d)\n",
-            mSampleRate, mPlaybackRate.mSpeed, mStatus);
-    result.append(buffer);
-    snprintf(buffer, 255, "  state(%d), latency (%d)\n", mState, mLatency);
-    result.append(buffer);
+    result.appendFormat("  status(%d), state(%d), session Id(%d), flags(%x)\n",
+                        mStatus, mState, mSessionId, mFlags);
+    result.appendFormat("  stream type(%d), left - right volume(%f, %f)\n",
+                        (mStreamType == AUDIO_STREAM_DEFAULT) ?
+                                audio_attributes_to_stream_type(&mAttributes) : mStreamType,
+                        mVolume[AUDIO_INTERLEAVE_LEFT], mVolume[AUDIO_INTERLEAVE_RIGHT]);
+    result.appendFormat("  format(%x), channel mask(%x), channel count(%u)\n",
+                  mFormat, mChannelMask, mChannelCount);
+    result.appendFormat("  sample rate(%u), original sample rate(%u), speed(%f)\n",
+                  mSampleRate, mOriginalSampleRate, mPlaybackRate.mSpeed);
+    result.appendFormat("  frame count(%zu), req. frame count(%zu)\n",
+                  mFrameCount, mReqFrameCount);
+    result.appendFormat("  notif. frame count(%u), req. notif. frame count(%u),"
+            " req. notif. per buff(%u)\n",
+             mNotificationFramesAct, mNotificationFramesReq, mNotificationsPerBufferReq);
+    result.appendFormat("  latency (%d), selected device Id(%d), routed device Id(%d)\n",
+                        mLatency, mSelectedDeviceId, mRoutedDeviceId);
+    result.appendFormat("  output(%d) AF latency (%u) AF frame count(%zu) AF SampleRate(%u)\n",
+                        mOutput, mAfLatency, mAfFrameCount, mAfSampleRate);
     ::write(fd, result.string(), result.size());
     return NO_ERROR;
 }
diff --git a/media/libaudioclient/include/media/AudioRecord.h b/media/libaudioclient/include/media/AudioRecord.h
index c6ad1b5..51596a2 100644
--- a/media/libaudioclient/include/media/AudioRecord.h
+++ b/media/libaudioclient/include/media/AudioRecord.h
@@ -185,7 +185,8 @@
                                     audio_input_flags_t flags = AUDIO_INPUT_FLAG_NONE,
                                     uid_t uid = AUDIO_UID_INVALID,
                                     pid_t pid = -1,
-                                    const audio_attributes_t* pAttributes = NULL);
+                                    const audio_attributes_t* pAttributes = NULL,
+                                    audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE);
 
     /* Terminates the AudioRecord and unregisters it from AudioFlinger.
      * Also destroys all resources associated with the AudioRecord.
@@ -223,7 +224,8 @@
                             audio_input_flags_t flags = AUDIO_INPUT_FLAG_NONE,
                             uid_t uid = AUDIO_UID_INVALID,
                             pid_t pid = -1,
-                            const audio_attributes_t* pAttributes = NULL);
+                            const audio_attributes_t* pAttributes = NULL,
+                            audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE);
 
     /* Result of constructing the AudioRecord. This must be checked for successful initialization
      * before using any AudioRecord API (except for set()), because using
diff --git a/media/libmedia/IMediaRecorder.cpp b/media/libmedia/IMediaRecorder.cpp
index 5282352..72f5f58 100644
--- a/media/libmedia/IMediaRecorder.cpp
+++ b/media/libmedia/IMediaRecorder.cpp
@@ -61,6 +61,9 @@
     PAUSE,
     RESUME,
     GET_METRICS,
+    SET_INPUT_DEVICE,
+    GET_ROUTED_DEVICE_ID,
+    ENABLE_AUDIO_DEVICE_CALLBACK,
 
 };
 
@@ -337,6 +340,57 @@
         remote()->transact(RELEASE, data, &reply);
         return reply.readInt32();
     }
+
+    status_t setInputDevice(audio_port_handle_t deviceId)
+    {
+        ALOGV("setInputDevice");
+        Parcel data, reply;
+        data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor());
+        data.writeInt32(deviceId);
+
+        status_t status = remote()->transact(SET_INPUT_DEVICE, data, &reply);
+        if (status != OK) {
+            ALOGE("setInputDevice binder call failed: %d", status);
+            return status;
+        }
+        return reply.readInt32();;
+    }
+
+    audio_port_handle_t getRoutedDeviceId(audio_port_handle_t *deviceId)
+    {
+        ALOGV("getRoutedDeviceId");
+        Parcel data, reply;
+        data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor());
+
+        status_t status = remote()->transact(GET_ROUTED_DEVICE_ID, data, &reply);
+        if (status != OK) {
+            ALOGE("getRoutedDeviceid binder call failed: %d", status);
+            *deviceId = AUDIO_PORT_HANDLE_NONE;
+            return status;
+        }
+
+        status = reply.readInt32();
+        if (status != NO_ERROR) {
+            *deviceId = AUDIO_PORT_HANDLE_NONE;
+        } else {
+            *deviceId = reply.readInt32();
+        }
+        return status;
+    }
+
+    status_t enableAudioDeviceCallback(bool enabled)
+    {
+        ALOGV("enableAudioDeviceCallback");
+        Parcel data, reply;
+        data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor());
+        data.writeBool(enabled);
+        status_t status = remote()->transact(ENABLE_AUDIO_DEVICE_CALLBACK, data, &reply);
+        if (status != OK) {
+            ALOGE("enableAudioDeviceCallback binder call failed: %d, %d", enabled, status);
+            return status;
+        }
+        return reply.readInt32();
+    }
 };
 
 IMPLEMENT_META_INTERFACE(MediaRecorder, "android.media.IMediaRecorder");
@@ -543,6 +597,41 @@
             }
             return NO_ERROR;
         } break;
+        case SET_INPUT_DEVICE: {
+            ALOGV("SET_INPUT_DEVICE");
+            CHECK_INTERFACE(IMediaRecorder, data, reply);
+            audio_port_handle_t deviceId;
+            status_t status = data.readInt32(&deviceId);
+            if (status == NO_ERROR) {
+                reply->writeInt32(setInputDevice(deviceId));
+            } else {
+                reply->writeInt32(BAD_VALUE);
+            }
+            return NO_ERROR;
+        } break;
+        case GET_ROUTED_DEVICE_ID: {
+            ALOGV("GET_ROUTED_DEVICE_ID");
+            CHECK_INTERFACE(IMediaRecorder, data, reply);
+            audio_port_handle_t deviceId;
+            status_t status = getRoutedDeviceId(&deviceId);
+            reply->writeInt32(status);
+            if (status == NO_ERROR) {
+                reply->writeInt32(deviceId);
+            }
+            return NO_ERROR;
+        } break;
+        case ENABLE_AUDIO_DEVICE_CALLBACK: {
+            ALOGV("ENABLE_AUDIO_DEVICE_CALLBACK");
+            CHECK_INTERFACE(IMediaRecorder, data, reply);
+            bool enabled;
+            status_t status = data.readBool(&enabled);
+            if (status == NO_ERROR) {
+                reply->writeInt32(enableAudioDeviceCallback(enabled));
+            } else {
+                reply->writeInt32(BAD_VALUE);
+            }
+            return NO_ERROR;
+        }
         default:
             return BBinder::onTransact(code, data, reply, flags);
     }
diff --git a/media/libmedia/include/media/IMediaRecorder.h b/media/libmedia/include/media/IMediaRecorder.h
index 9d0341a..3cef329 100644
--- a/media/libmedia/include/media/IMediaRecorder.h
+++ b/media/libmedia/include/media/IMediaRecorder.h
@@ -19,6 +19,7 @@
 #define ANDROID_IMEDIARECORDER_H
 
 #include <binder/IInterface.h>
+#include <system/audio.h>
 
 namespace android {
 
@@ -64,6 +65,10 @@
     virtual status_t release() = 0;
     virtual status_t setInputSurface(const sp<PersistentSurface>& surface) = 0;
     virtual sp<IGraphicBufferProducer> querySurfaceMediaSource() = 0;
+
+    virtual status_t setInputDevice(audio_port_handle_t deviceId) = 0;
+    virtual status_t getRoutedDeviceId(audio_port_handle_t *deviceId) = 0;
+    virtual status_t enableAudioDeviceCallback(bool enabled) = 0;
 };
 
 // ----------------------------------------------------------------------------
diff --git a/media/libmedia/include/media/MediaRecorderBase.h b/media/libmedia/include/media/MediaRecorderBase.h
index 40dd9f9..748153c 100644
--- a/media/libmedia/include/media/MediaRecorderBase.h
+++ b/media/libmedia/include/media/MediaRecorderBase.h
@@ -18,6 +18,7 @@
 
 #define MEDIA_RECORDER_BASE_H_
 
+#include <media/AudioSystem.h>
 #include <media/mediarecorder.h>
 
 #include <system/audio.h>
@@ -62,6 +63,10 @@
     virtual status_t dump(int fd, const Vector<String16>& args) const = 0;
     virtual status_t setInputSurface(const sp<PersistentSurface>& surface) = 0;
     virtual sp<IGraphicBufferProducer> querySurfaceMediaSource() const = 0;
+    virtual status_t setInputDevice(audio_port_handle_t deviceId) = 0;
+    virtual status_t getRoutedDeviceId(audio_port_handle_t* deviceId) = 0;
+    virtual void setAudioDeviceCallback(const sp<AudioSystem::AudioDeviceCallback>& callback) = 0;
+    virtual status_t enableAudioDeviceCallback(bool enabled) = 0;
 
 
 protected:
diff --git a/media/libmedia/include/media/mediarecorder.h b/media/libmedia/include/media/mediarecorder.h
index b9717ea..5f2a6fe 100644
--- a/media/libmedia/include/media/mediarecorder.h
+++ b/media/libmedia/include/media/mediarecorder.h
@@ -141,6 +141,8 @@
     MEDIA_RECORDER_TRACK_EVENT_ERROR              = 100,
     MEDIA_RECORDER_TRACK_EVENT_INFO               = 101,
     MEDIA_RECORDER_TRACK_EVENT_LIST_END           = 1000,
+
+    MEDIA_RECORDER_AUDIO_ROUTING_CHANGED          = 10000,
 };
 
 /*
@@ -253,6 +255,9 @@
     status_t    setInputSurface(const sp<PersistentSurface>& surface);
     sp<IGraphicBufferProducer>     querySurfaceMediaSourceFromMediaServer();
     status_t    getMetrics(Parcel *reply);
+    status_t    setInputDevice(audio_port_handle_t deviceId);
+    status_t    getRoutedDeviceId(audio_port_handle_t *deviceId);
+    status_t    enableAudioDeviceCallback(bool enabled);
 
 private:
     void                    doCleanUp();
diff --git a/media/libmedia/mediarecorder.cpp b/media/libmedia/mediarecorder.cpp
index 4405930..aab845b 100644
--- a/media/libmedia/mediarecorder.cpp
+++ b/media/libmedia/mediarecorder.cpp
@@ -792,4 +792,41 @@
     notify(MEDIA_RECORDER_EVENT_ERROR, MEDIA_ERROR_SERVER_DIED, 0);
 }
 
+status_t MediaRecorder::setInputDevice(audio_port_handle_t deviceId)
+{
+    ALOGV("setInputDevice");
+
+    if (mMediaRecorder == NULL) {
+        ALOGE("media recorder is not initialized yet");
+        return INVALID_OPERATION;
+    }
+    return mMediaRecorder->setInputDevice(deviceId);
+}
+
+status_t MediaRecorder::getRoutedDeviceId(audio_port_handle_t* deviceId)
+{
+    ALOGV("getRoutedDeviceId");
+
+    if (mMediaRecorder == NULL) {
+        ALOGE("media recorder is not initialized yet");
+        return INVALID_OPERATION;
+    }
+    status_t status = mMediaRecorder->getRoutedDeviceId(deviceId);
+    if (status != NO_ERROR) {
+        *deviceId = AUDIO_PORT_HANDLE_NONE;
+    }
+    return status;
+}
+
+status_t MediaRecorder::enableAudioDeviceCallback(bool enabled)
+{
+    ALOGV("enableAudioDeviceCallback");
+
+    if (mMediaRecorder == NULL) {
+        ALOGE("media recorder is not initialized yet");
+        return INVALID_OPERATION;
+    }
+    return mMediaRecorder->enableAudioDeviceCallback(enabled);
+}
+
 } // namespace android
diff --git a/media/libmediaplayerservice/MediaRecorderClient.cpp b/media/libmediaplayerservice/MediaRecorderClient.cpp
index a423fee..dcd393b 100644
--- a/media/libmediaplayerservice/MediaRecorderClient.cpp
+++ b/media/libmediaplayerservice/MediaRecorderClient.cpp
@@ -411,6 +411,25 @@
     }
 }
 
+MediaRecorderClient::AudioDeviceUpdatedNotifier::AudioDeviceUpdatedNotifier(
+        const sp<IMediaRecorderClient>& listener) {
+    mListener = listener;
+}
+
+MediaRecorderClient::AudioDeviceUpdatedNotifier::~AudioDeviceUpdatedNotifier() {
+}
+
+void MediaRecorderClient::AudioDeviceUpdatedNotifier::onAudioDeviceUpdate(
+        audio_io_handle_t audioIo,
+        audio_port_handle_t deviceId) {
+    sp<IMediaRecorderClient> listener = mListener.promote();
+    if (listener != NULL) {
+        listener->notify(MEDIA_RECORDER_AUDIO_ROUTING_CHANGED, audioIo, deviceId);
+    } else {
+        ALOGW("listener for process %d death is gone", MEDIA_RECORDER_AUDIO_ROUTING_CHANGED);
+    }
+}
+
 void MediaRecorderClient::clearDeathNotifiers_l() {
     if (mCameraDeathListener != nullptr) {
         mCameraDeathListener->unlinkToDeath();
@@ -459,6 +478,9 @@
             MediaPlayerService::MEDIACODEC_PROCESS_DEATH);
     omx->linkToDeath(mCodecDeathListener, 0);
 
+    mAudioDeviceUpdatedNotifier = new AudioDeviceUpdatedNotifier(listener);
+    mRecorder->setAudioDeviceCallback(mAudioDeviceUpdatedNotifier);
+
     return OK;
 }
 
@@ -479,4 +501,30 @@
     return OK;
 }
 
+status_t MediaRecorderClient::setInputDevice(audio_port_handle_t deviceId) {
+    ALOGV("setInputDevice(%d)", deviceId);
+    Mutex::Autolock lock(mLock);
+    if (mRecorder != NULL) {
+        return mRecorder->setInputDevice(deviceId);
+    }
+    return NO_INIT;
+}
+
+status_t MediaRecorderClient::getRoutedDeviceId(audio_port_handle_t* deviceId) {
+    ALOGV("getRoutedDeviceId");
+    Mutex::Autolock lock(mLock);
+    if (mRecorder != NULL) {
+        return mRecorder->getRoutedDeviceId(deviceId);
+    }
+    return NO_INIT;
+}
+
+status_t MediaRecorderClient::enableAudioDeviceCallback(bool enabled) {
+    ALOGV("enableDeviceCallback: %d", enabled);
+    Mutex::Autolock lock(mLock);
+    if (mRecorder != NULL) {
+        return mRecorder->enableAudioDeviceCallback(enabled);
+    }
+    return NO_INIT;
+}
 }; // namespace android
diff --git a/media/libmediaplayerservice/MediaRecorderClient.h b/media/libmediaplayerservice/MediaRecorderClient.h
index 711db2c..538b461 100644
--- a/media/libmediaplayerservice/MediaRecorderClient.h
+++ b/media/libmediaplayerservice/MediaRecorderClient.h
@@ -18,6 +18,7 @@
 #ifndef ANDROID_MEDIARECORDERCLIENT_H
 #define ANDROID_MEDIARECORDERCLIENT_H
 
+#include <media/AudioSystem.h>
 #include <media/IMediaRecorder.h>
 
 #include <android/hardware/media/omx/1.0/IOmx.h>
@@ -58,6 +59,18 @@
         wp<IMediaRecorderClient> mListener;
     };
 
+    class AudioDeviceUpdatedNotifier: public AudioSystem::AudioDeviceCallback
+    {
+    public:
+        AudioDeviceUpdatedNotifier(const sp<IMediaRecorderClient>& listener);
+        virtual ~AudioDeviceUpdatedNotifier();
+        virtual void onAudioDeviceUpdate(
+                audio_io_handle_t audioIo,
+                audio_port_handle_t deviceId);
+    private:
+        wp<IMediaRecorderClient> mListener;
+    };
+
     void clearDeathNotifiers_l();
 
 public:
@@ -91,6 +104,9 @@
     virtual     status_t   dump(int fd, const Vector<String16>& args);
     virtual     status_t   setInputSurface(const sp<PersistentSurface>& surface);
     virtual     sp<IGraphicBufferProducer> querySurfaceMediaSource();
+    virtual     status_t   setInputDevice(audio_port_handle_t deviceId);
+    virtual     status_t   getRoutedDeviceId(audio_port_handle_t* deviceId);
+    virtual     status_t   enableAudioDeviceCallback(bool enabled);
 
 private:
     friend class           MediaPlayerService;  // for accessing private constructor
@@ -103,6 +119,7 @@
 
     sp<ServiceDeathNotifier> mCameraDeathListener;
     sp<ServiceDeathNotifier> mCodecDeathListener;
+    sp<AudioDeviceUpdatedNotifier> mAudioDeviceUpdatedNotifier;
 
     pid_t                  mPid;
     Mutex                  mLock;
diff --git a/media/libmediaplayerservice/StagefrightRecorder.cpp b/media/libmediaplayerservice/StagefrightRecorder.cpp
index 89354d6..77eaefe 100644
--- a/media/libmediaplayerservice/StagefrightRecorder.cpp
+++ b/media/libmediaplayerservice/StagefrightRecorder.cpp
@@ -103,7 +103,9 @@
       mOutputFd(-1),
       mAudioSource(AUDIO_SOURCE_CNT),
       mVideoSource(VIDEO_SOURCE_LIST_END),
-      mStarted(false) {
+      mStarted(false),
+      mSelectedDeviceId(AUDIO_PORT_HANDLE_NONE),
+      mDeviceCallbackEnabled(false) {
 
     ALOGV("Constructor");
 
@@ -204,7 +206,7 @@
     return OK;
 }
 
-// The client side of mediaserver asks it to creat a SurfaceMediaSource
+// The client side of mediaserver asks it to create a SurfaceMediaSource
 // and return a interface reference. The client side will use that
 // while encoding GL Frames
 sp<IGraphicBufferProducer> StagefrightRecorder::querySurfaceMediaSource() const {
@@ -1069,7 +1071,8 @@
                 mAudioChannels,
                 mSampleRate,
                 mClientUid,
-                mClientPid);
+                mClientPid,
+                mSelectedDeviceId);
 
     status_t err = audioSource->initCheck();
 
@@ -1120,6 +1123,10 @@
 
     sp<MediaCodecSource> audioEncoder =
             MediaCodecSource::Create(mLooper, format, audioSource);
+    sp<AudioSystem::AudioDeviceCallback> callback = mAudioDeviceCallback.promote();
+    if (mDeviceCallbackEnabled && callback != 0) {
+        audioSource->addAudioDeviceCallback(callback);
+    }
     mAudioSourceNode = audioSource;
 
     if (audioEncoder == NULL) {
@@ -2116,6 +2123,46 @@
     return OK;
 }
 
+status_t StagefrightRecorder::setInputDevice(audio_port_handle_t deviceId) {
+    ALOGV("setInputDevice");
+
+    if (mSelectedDeviceId != deviceId) {
+        mSelectedDeviceId = deviceId;
+        if (mAudioSourceNode != 0) {
+            return mAudioSourceNode->setInputDevice(deviceId);
+        }
+    }
+    return NO_ERROR;
+}
+
+status_t StagefrightRecorder::getRoutedDeviceId(audio_port_handle_t* deviceId) {
+    ALOGV("getRoutedDeviceId");
+
+    if (mAudioSourceNode != 0) {
+        status_t status = mAudioSourceNode->getRoutedDeviceId(deviceId);
+        return status;
+    }
+    return NO_INIT;
+}
+
+void StagefrightRecorder::setAudioDeviceCallback(
+        const sp<AudioSystem::AudioDeviceCallback>& callback) {
+    mAudioDeviceCallback = callback;
+}
+
+status_t StagefrightRecorder::enableAudioDeviceCallback(bool enabled) {
+    mDeviceCallbackEnabled = enabled;
+    sp<AudioSystem::AudioDeviceCallback> callback = mAudioDeviceCallback.promote();
+    if (mAudioSourceNode != 0 && callback != 0) {
+        if (enabled) {
+            return mAudioSourceNode->addAudioDeviceCallback(callback);
+        } else {
+            return mAudioSourceNode->removeAudioDeviceCallback(callback);
+        }
+    }
+    return NO_ERROR;
+}
+
 status_t StagefrightRecorder::dump(
         int fd, const Vector<String16>& args) const {
     ALOGV("dump");
diff --git a/media/libmediaplayerservice/StagefrightRecorder.h b/media/libmediaplayerservice/StagefrightRecorder.h
index 5111c8e..ec7e8ed 100644
--- a/media/libmediaplayerservice/StagefrightRecorder.h
+++ b/media/libmediaplayerservice/StagefrightRecorder.h
@@ -72,6 +72,10 @@
     virtual status_t dump(int fd, const Vector<String16> &args) const;
     // Querying a SurfaceMediaSourcer
     virtual sp<IGraphicBufferProducer> querySurfaceMediaSource() const;
+    virtual status_t setInputDevice(audio_port_handle_t deviceId);
+    virtual status_t getRoutedDeviceId(audio_port_handle_t* deviceId);
+    virtual void setAudioDeviceCallback(const sp<AudioSystem::AudioDeviceCallback>& callback);
+    virtual status_t enableAudioDeviceCallback(bool enabled);
 
 private:
     mutable Mutex mLock;
@@ -144,6 +148,10 @@
     sp<IGraphicBufferProducer> mGraphicBufferProducer;
     sp<ALooper> mLooper;
 
+    audio_port_handle_t mSelectedDeviceId;
+    bool mDeviceCallbackEnabled;
+    wp<AudioSystem::AudioDeviceCallback> mAudioDeviceCallback;
+
     static const int kMaxHighSpeedFps = 1000;
 
     status_t prepareInternal();
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
index 6c4b823..d1e5d45 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
@@ -1311,6 +1311,7 @@
 
             mResetting = true;
             stopPlaybackTimer("kWhatReset");
+            stopRebufferingTimer(true);
 
             mDeferredActions.push_back(
                     new FlushDecoderAction(
@@ -1604,6 +1605,37 @@
     }
 }
 
+void NuPlayer::startRebufferingTimer() {
+    Mutex::Autolock autoLock(mPlayingTimeLock);
+    if (mLastStartedRebufferingTimeNs == 0) {
+        mLastStartedRebufferingTimeNs = systemTime();
+        ALOGV("startRebufferingTimer() time %20" PRId64 "",  mLastStartedRebufferingTimeNs);
+    }
+}
+
+void NuPlayer::stopRebufferingTimer(bool exitingPlayback) {
+    Mutex::Autolock autoLock(mPlayingTimeLock);
+
+    ALOGV("stopRebufferTimer()  time %20" PRId64 " (exiting %d)", mLastStartedRebufferingTimeNs, exitingPlayback);
+
+    if (mLastStartedRebufferingTimeNs != 0) {
+        sp<NuPlayerDriver> driver = mDriver.promote();
+        if (driver != NULL) {
+            int64_t now = systemTime();
+            int64_t rebuffered = now - mLastStartedRebufferingTimeNs;
+            ALOGV("stopRebufferingTimer()  log  %20" PRId64 "", rebuffered);
+
+            if (rebuffered > 0) {
+                driver->notifyMoreRebufferingTimeUs((rebuffered+500)/1000);
+                if (exitingPlayback) {
+                    driver->notifyRebufferingWhenExit(true);
+                }
+            }
+        }
+        mLastStartedRebufferingTimeNs = 0;
+    }
+}
+
 void NuPlayer::onPause() {
 
     stopPlaybackTimer("onPause");
@@ -2250,6 +2282,7 @@
     CHECK(mVideoDecoder == NULL);
 
     stopPlaybackTimer("performReset");
+    stopRebufferingTimer(true);
 
     cancelPollDuration();
 
@@ -2503,6 +2536,7 @@
             if (mStarted) {
                 ALOGI("buffer low, pausing...");
 
+                startRebufferingTimer();
                 mPausedForBuffering = true;
                 onPause();
             }
@@ -2516,6 +2550,7 @@
             if (mStarted) {
                 ALOGI("buffer ready, resuming...");
 
+                stopRebufferingTimer(false);
                 mPausedForBuffering = false;
 
                 // do not resume yet if client didn't unpause
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.h b/media/libmediaplayerservice/nuplayer/NuPlayer.h
index 492b8d4..fda69e8 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.h
@@ -183,6 +183,10 @@
     void stopPlaybackTimer(const char *where);
     void startPlaybackTimer(const char *where);
 
+    int64_t mLastStartedRebufferingTimeNs;
+    void startRebufferingTimer();
+    void stopRebufferingTimer(bool exitingPlayback);
+
     int64_t mPreviousSeekTimeUs;
 
     List<sp<Action> > mDeferredActions;
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
index bd54df0..ebf57c6 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
@@ -56,6 +56,10 @@
 static const char *kPlayerError = "android.media.mediaplayer.err";
 static const char *kPlayerErrorCode = "android.media.mediaplayer.errcode";
 static const char *kPlayerDataSourceType = "android.media.mediaplayer.dataSource";
+//
+static const char *kPlayerRebuffering = "android.media.mediaplayer.rebufferingMs";
+static const char *kPlayerRebufferingCount = "android.media.mediaplayer.rebuffers";
+static const char *kPlayerRebufferingAtExit = "android.media.mediaplayer.rebufferExit";
 
 
 NuPlayerDriver::NuPlayerDriver(pid_t pid)
@@ -67,6 +71,9 @@
       mPositionUs(-1),
       mSeekInProgress(false),
       mPlayingTimeUs(0),
+      mRebufferingTimeUs(0),
+      mRebufferingEvents(0),
+      mRebufferingAtExit(false),
       mLooper(new ALooper),
       mMediaClock(new MediaClock),
       mPlayer(new NuPlayer(pid, mMediaClock)),
@@ -582,6 +589,12 @@
 
     mAnalyticsItem->setInt64(kPlayerPlaying, (mPlayingTimeUs+500)/1000 );
 
+    if (mRebufferingEvents != 0) {
+        mAnalyticsItem->setInt64(kPlayerRebuffering, (mRebufferingTimeUs+500)/1000 );
+        mAnalyticsItem->setInt32(kPlayerRebufferingCount, mRebufferingEvents);
+        mAnalyticsItem->setInt32(kPlayerRebufferingAtExit, mRebufferingAtExit);
+    }
+
     mAnalyticsItem->setCString(kPlayerDataSourceType, mPlayer->getDataSourceType());
 }
 
@@ -661,6 +674,9 @@
     mPositionUs = -1;
     mLooping = false;
     mPlayingTimeUs = 0;
+    mRebufferingTimeUs = 0;
+    mRebufferingEvents = 0;
+    mRebufferingAtExit = false;
 
     return OK;
 }
@@ -811,6 +827,17 @@
     mPlayingTimeUs += playingUs;
 }
 
+void NuPlayerDriver::notifyMoreRebufferingTimeUs(int64_t rebufferingUs) {
+    Mutex::Autolock autoLock(mLock);
+    mRebufferingTimeUs += rebufferingUs;
+    mRebufferingEvents++;
+}
+
+void NuPlayerDriver::notifyRebufferingWhenExit(bool status) {
+    Mutex::Autolock autoLock(mLock);
+    mRebufferingAtExit = status;
+}
+
 void NuPlayerDriver::notifySeekComplete() {
     ALOGV("notifySeekComplete(%p)", this);
     Mutex::Autolock autoLock(mLock);
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h
index 6ca6344..13b46c3 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h
@@ -84,6 +84,8 @@
     void notifySetSurfaceComplete();
     void notifyDuration(int64_t durationUs);
     void notifyMorePlayingTimeUs(int64_t timeUs);
+    void notifyMoreRebufferingTimeUs(int64_t timeUs);
+    void notifyRebufferingWhenExit(bool status);
     void notifySeekComplete();
     void notifySeekComplete_l();
     void notifyListener(int msg, int ext1 = 0, int ext2 = 0, const Parcel *in = NULL);
@@ -126,6 +128,9 @@
     int64_t mPositionUs;
     bool mSeekInProgress;
     int64_t mPlayingTimeUs;
+    int64_t mRebufferingTimeUs;
+    int32_t mRebufferingEvents;
+    bool mRebufferingAtExit;
     // <<<
 
     sp<ALooper> mLooper;
diff --git a/media/libstagefright/AudioSource.cpp b/media/libstagefright/AudioSource.cpp
index f2b1f10..b8da980 100644
--- a/media/libstagefright/AudioSource.cpp
+++ b/media/libstagefright/AudioSource.cpp
@@ -52,7 +52,7 @@
 AudioSource::AudioSource(
         audio_source_t inputSource, const String16 &opPackageName,
         uint32_t sampleRate, uint32_t channelCount, uint32_t outSampleRate,
-        uid_t uid, pid_t pid)
+        uid_t uid, pid_t pid, audio_port_handle_t selectedDeviceId)
     : mStarted(false),
       mSampleRate(sampleRate),
       mOutSampleRate(outSampleRate > 0 ? outSampleRate : sampleRate),
@@ -101,7 +101,9 @@
                     AudioRecord::TRANSFER_DEFAULT,
                     AUDIO_INPUT_FLAG_NONE,
                     uid,
-                    pid);
+                    pid,
+                    NULL /*pAttributes*/,
+                    selectedDeviceId);
         mInitCheck = mRecord->initCheck();
         if (mInitCheck != OK) {
             mRecord.clear();
@@ -465,4 +467,35 @@
     return value;
 }
 
+status_t AudioSource::setInputDevice(audio_port_handle_t deviceId) {
+    if (mRecord != 0) {
+        return mRecord->setInputDevice(deviceId);
+    }
+    return NO_INIT;
+}
+
+status_t AudioSource::getRoutedDeviceId(audio_port_handle_t* deviceId) {
+    if (mRecord != 0) {
+        *deviceId = mRecord->getRoutedDeviceId();
+        return NO_ERROR;
+    }
+    return NO_INIT;
+}
+
+status_t AudioSource::addAudioDeviceCallback(
+        const sp<AudioSystem::AudioDeviceCallback>& callback) {
+    if (mRecord != 0) {
+        return mRecord->addAudioDeviceCallback(callback);
+    }
+    return NO_INIT;
+}
+
+status_t AudioSource::removeAudioDeviceCallback(
+        const sp<AudioSystem::AudioDeviceCallback>& callback) {
+    if (mRecord != 0) {
+        return mRecord->removeAudioDeviceCallback(callback);
+    }
+    return NO_INIT;
+}
+
 }  // namespace android
diff --git a/media/libstagefright/codec2/include/C2.h b/media/libstagefright/codec2/include/C2.h
index bd563ff..01d1341 100644
--- a/media/libstagefright/codec2/include/C2.h
+++ b/media/libstagefright/codec2/include/C2.h
@@ -66,7 +66,7 @@
  * mitigate binary breaks by adhering to the following conventions:
  *
  * - at most one vtable with placeholder virtual methods
- * - all optional/placeholder virtual methods returning a C2Status, with C2_OMITTED not requiring
+ * - all optional/placeholder virtual methods returning a c2_status_t, with C2_OMITTED not requiring
  *   any update to input/output arguments.
  * - limiting symbol export of inline methods
  * - use of pimpl (or shared-pimpl)
@@ -106,9 +106,9 @@
 typedef const char *C2StringLiteral;
 
 /**
- * C2Status: status codes used.
+ * c2_status_t: status codes used.
  */
-enum C2Status : int32_t {
+enum c2_status_t : int32_t {
 
 /*
  * Use android status constants if available. Otherwise, define the android status constants as
diff --git a/media/libstagefright/codec2/include/C2Buffer.h b/media/libstagefright/codec2/include/C2Buffer.h
index 22e4360..d978e42 100644
--- a/media/libstagefright/codec2/include/C2Buffer.h
+++ b/media/libstagefright/codec2/include/C2Buffer.h
@@ -91,7 +91,7 @@
      * \retval C2_REFUSED       no permission to wait for the fence (unexpected - system)
      * \retval C2_CORRUPTED     some unknown error prevented waiting for the fence (unexpected)
      */
-    C2Status wait(nsecs_t timeoutNs);
+    c2_status_t 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_REFUSED       no permission to signal the fence (unexpected - system)
      * \retval C2_CORRUPTED     some unknown error prevented signaling the fence(s) (unexpected)
      */
-    C2Status fire();
+    c2_status_t fire();
 
     /**
      * Trigger this event from the merging of the supplied fences. This means that it will be
@@ -172,7 +172,7 @@
      * \retval C2_REFUSED       no permission to merge the fence (unexpected - system)
      * \retval C2_CORRUPTED     some unknown error prevented merging the fence(s) (unexpected)
      */
-    C2Status merge(std::vector<C2Fence> fences);
+    c2_status_t merge(std::vector<C2Fence> fences);
 
     /**
      * Abandons the event and any associated fence(s).
@@ -186,7 +186,7 @@
      * \retval C2_REFUSED       no permission to abandon the fence (unexpected - system)
      * \retval C2_CORRUPTED     some unknown error prevented signaling the fence(s) (unexpected)
      */
-    C2Status abandon();
+    c2_status_t abandon();
 
 private:
     class Impl;
@@ -200,12 +200,12 @@
  * Interface for objects that encapsulate an updatable status value.
  */
 struct _C2InnateStatus {
-    inline C2Status status() const { return mStatus; }
+    inline c2_status_t status() const { return mStatus; }
 
 protected:
-    _C2InnateStatus(C2Status status) : mStatus(status) { }
+    _C2InnateStatus(c2_status_t status) : mStatus(status) { }
 
-    C2Status mStatus; // this status is updatable by the object
+    c2_status_t mStatus; // this status is updatable by the object
 };
 
 /// @}
@@ -230,10 +230,10 @@
     }
 
 protected:
-    C2Acquirable(C2Status error, C2Fence fence, T t) : C2Fence(fence), mInitialError(error), mT(t) { }
+    C2Acquirable(c2_status_t error, C2Fence fence, T t) : C2Fence(fence), mInitialError(error), mT(t) { }
 
 private:
-    C2Status mInitialError;
+    c2_status_t mInitialError;
     T mT; // TODO: move instead of copy
 };
 
@@ -449,11 +449,11 @@
     /**
      * \return error during the creation/mapping of this view.
      */
-    C2Status error() const;
+    c2_status_t error() const;
 
 protected:
     C2ReadView(const _C2LinearCapacityAspect *parent, const uint8_t *data);
-    explicit C2ReadView(C2Status error);
+    explicit C2ReadView(c2_status_t error);
 
 private:
     class Impl;
@@ -482,11 +482,11 @@
     /**
      * \return error during the creation/mapping of this view.
      */
-    C2Status error() const;
+    c2_status_t error() const;
 
 protected:
     C2WriteView(const _C2LinearRangeAspect *parent, uint8_t *base);
-    explicit C2WriteView(C2Status error);
+    explicit C2WriteView(c2_status_t 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)
      */
-    C2Status reserve(size_t size, C2Fence *fence /* nullable */);
+    c2_status_t 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)
      */
-    C2Status abandon(size_t size);
+    c2_status_t 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)
      */
-    C2Status share(size_t size, C2Fence fence, std::list<C2ConstLinearBlock> &blocks);
+    c2_status_t 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.
      */
-    C2Status error() const;
+    c2_status_t 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)
      */
-    C2Status commit(size_t size, C2Fence fence);
+    c2_status_t 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.
      */
-    C2Status error() const;
+    c2_status_t error() const;
 
 protected:
     C2GraphicView(
             const _C2PlanarCapacityAspect *parent,
             uint8_t *const *data,
             const C2PlaneLayout& layout);
-    explicit C2GraphicView(C2Status error);
+    explicit C2GraphicView(c2_status_t 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)
      */
-    C2Status registerOnDestroyNotify(OnDestroyNotify onDestroyNotify, void *arg = nullptr);
+    c2_status_t 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)
      */
-    C2Status unregisterOnDestroyNotify(OnDestroyNotify onDestroyNotify, void *arg = nullptr);
+    c2_status_t 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).
      */
-    C2Status setInfo(const std::shared_ptr<C2Info> &info);
+    c2_status_t 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 C2Status map(
+    virtual c2_status_t 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_REFUSED   no permission to unmap the portion (unexpected - system)
      */
-    virtual C2Status unmap(void *addr, size_t size, int *fenceFd /* nullable */) = 0;
+    virtual c2_status_t 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 C2Status map(
+    virtual c2_status_t 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_REFUSED   no permission to unmap the section (unexpected - system)
      */
-    virtual C2Status unmap(C2Fence *fenceFd /* nullable */) = 0;
+    virtual c2_status_t unmap(C2Fence *fenceFd /* nullable */) = 0;
 
     /**
      * Returns true if this is a valid allocation.
@@ -1544,8 +1544,10 @@
 
     /**
      * Information about an allocator.
+     *
+     * Allocators don't have a query API so all queriable information is stored here.
      */
-    struct Info {
+    struct Traits {
         C2String name;              ///< allocator name
         id_t id;                    ///< allocator ID
         type_t supportedTypes;      ///< supported allocation types
@@ -1574,13 +1576,15 @@
     virtual id_t getId() const = 0;
 
     /**
-     * Returns the allocator information.
+     * Returns the allocator traits.
      *
      * This method MUST be "non-blocking" and return within 1ms.
      *
+     * Allocators don't have a full-fledged query API, only this method.
+     *
      * \return allocator information
      */
-    virtual std::shared_ptr<const Info> getInfo() const = 0;
+    virtual std::shared_ptr<const Traits> getTraits() const = 0;
 
     /**
      * Allocates a 1D allocation of given |capacity| and |usage|. If successful, the allocation is
@@ -1604,7 +1608,7 @@
      * \retval C2_OMITTED   this allocator does not support 1D allocations
      * \retval C2_CORRUPTED some unknown, unrecoverable error occured during allocation (unexpected)
      */
-    virtual C2Status newLinearAllocation(
+    virtual c2_status_t newLinearAllocation(
             uint32_t capacity __unused, C2MemoryUsage usage __unused,
             std::shared_ptr<C2LinearAllocation> *allocation /* nonnull */) {
         *allocation = nullptr;
@@ -1627,7 +1631,7 @@
      * \retval C2_OMITTED   this allocator does not support 1D allocations
      * \retval C2_CORRUPTED some unknown, unrecoverable error occured during allocation (unexpected)
      */
-    virtual C2Status priorLinearAllocation(
+    virtual c2_status_t priorLinearAllocation(
             const C2Handle *handle __unused,
             std::shared_ptr<C2LinearAllocation> *allocation /* nonnull */) {
         *allocation = nullptr;
@@ -1660,7 +1664,7 @@
      * \retval C2_OMITTED   this allocator does not support 2D allocations
      * \retval C2_CORRUPTED some unknown, unrecoverable error occured during allocation (unexpected)
      */
-    virtual C2Status newGraphicAllocation(
+    virtual c2_status_t newGraphicAllocation(
             uint32_t width __unused, uint32_t height __unused, uint32_t format __unused,
             C2MemoryUsage usage __unused,
             std::shared_ptr<C2GraphicAllocation> *allocation /* nonnull */) {
@@ -1684,7 +1688,7 @@
      * \retval C2_OMITTED   this allocator does not support 2D allocations
      * \retval C2_CORRUPTED some unknown, unrecoverable error occured during recreation (unexpected)
      */
-    virtual C2Status priorGraphicAllocation(
+    virtual c2_status_t priorGraphicAllocation(
             const C2Handle *handle __unused,
             std::shared_ptr<C2GraphicAllocation> *allocation /* nonnull */) {
         *allocation = nullptr;
@@ -1764,7 +1768,7 @@
      * \retval C2_OMITTED   this pool does not support linear blocks
      * \retval C2_CORRUPTED some unknown, unrecoverable error occured during operation (unexpected)
      */
-    virtual C2Status fetchLinearBlock(
+    virtual c2_status_t fetchLinearBlock(
             uint32_t capacity __unused, C2MemoryUsage usage __unused,
             std::shared_ptr<C2LinearBlock> *block /* nonnull */) {
         *block = nullptr;
@@ -1792,7 +1796,7 @@
      * \retval C2_OMITTED   this pool does not support circular blocks
      * \retval C2_CORRUPTED some unknown, unrecoverable error occured during operation (unexpected)
      */
-    virtual C2Status fetchCircularBlock(
+    virtual c2_status_t fetchCircularBlock(
             uint32_t capacity __unused, C2MemoryUsage usage __unused,
             std::shared_ptr<C2CircularBlock> *block /* nonnull */) {
         *block = nullptr;
@@ -1823,7 +1827,7 @@
      * \retval C2_OMITTED   this pool does not support 2D blocks
      * \retval C2_CORRUPTED some unknown, unrecoverable error occured during operation (unexpected)
      */
-    virtual C2Status fetchGraphicBlock(
+    virtual c2_status_t fetchGraphicBlock(
             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 c88de62..2dbf7ea 100644
--- a/media/libstagefright/codec2/include/C2Component.h
+++ b/media/libstagefright/codec2/include/C2Component.h
@@ -36,25 +36,6 @@
 
 class C2Component;
 
-class C2ComponentListener {
-public:
-    virtual void onWorkDone(std::weak_ptr<C2Component> component,
-                            std::vector<std::unique_ptr<C2Work>> workItems) = 0;
-
-    virtual void onTripped(std::weak_ptr<C2Component> component,
-                           std::vector<std::shared_ptr<C2SettingResult>> settingResult) = 0;
-
-    virtual void onError(std::weak_ptr<C2Component> component,
-                         uint32_t errorCode) = 0;
-
-    // virtual void onTunnelReleased(<from>, <to>) = 0;
-
-    // virtual void onComponentReleased(<id>) = 0;
-
-protected:
-    virtual ~C2ComponentListener() = default;
-};
-
 struct C2FieldSupportedValuesQuery {
     enum Type : uint32_t {
         POSSIBLE, ///< query all possible values regardless of other settings
@@ -63,7 +44,7 @@
 
     const C2ParamField field;
     const Type type;
-    C2Status status;
+    c2_status_t status;
     C2FieldSupportedValues values;
 
     C2FieldSupportedValuesQuery(const C2ParamField &field_, Type type_)
@@ -118,7 +99,7 @@
      *
      * \return a unique node ID for this component or component interface instance.
      */
-    virtual node_id getId() const = 0;
+    virtual c2_node_id_t getId() const = 0;
 
     /**
      * Queries a set of parameters from the component or interface object.
@@ -154,7 +135,7 @@
      * \retval C2_CORRUPTED some unknown error prevented the querying of the parameters
      *                      (unexpected)
      */
-    virtual C2Status query_nb(
+    virtual c2_status_t query_nb(
         const std::vector<C2Param* const> &stackParams,
         const std::vector<C2Param::Index> &heapParamIndices,
         std::vector<std::unique_ptr<C2Param>>* const heapParams) const = 0;
@@ -191,7 +172,7 @@
      * \retval C2_CORRUPTED some unknown error prevented the update of the parameters
      *                      (unexpected)
      */
-    virtual C2Status config_nb(
+    virtual c2_status_t config_nb(
             const std::vector<C2Param* const> &params,
             std::vector<std::unique_ptr<C2SettingResult>>* const failures) = 0;
 
@@ -230,7 +211,7 @@
      * \retval C2_CORRUPTED some unknown error prevented the update of the parameters
      *                      (unexpected)
      */
-    virtual C2Status commit_sm(
+    virtual c2_status_t commit_sm(
             const std::vector<C2Param* const> &params,
             std::vector<std::unique_ptr<C2SettingResult>>* const failures) = 0;
 
@@ -256,7 +237,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 C2Status createTunnel_sm(node_id targetComponent) = 0;
+    virtual c2_status_t createTunnel_sm(c2_node_id_t targetComponent) = 0;
 
     /**
      * Releases a tunnel from this component to the target component.
@@ -277,38 +258,41 @@
      * \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 C2Status releaseTunnel_sm(node_id targetComponent) = 0;
-
+    virtual c2_status_t releaseTunnel_sm(c2_node_id_t targetComponent) = 0;
 
     // REFLECTION MECHANISM (USED FOR EXTENSION)
     // =============================================================================================
 
     /**
-     * Returns the parameter reflector.
-     *
-     * This is used to describe parameter fields.
-     *
-     * \return a shared parameter reflector object.
-     */
-    virtual std::shared_ptr<C2ParamReflector> getParamReflector() const = 0;
-
-    /**
      * Returns the set of supported parameters.
      *
+     * This method MUST be "non-blocking" and return within 1ms.
+     *
      * \param[out] params a vector of supported parameters will be appended to this vector.
      *
      * \retval C2_OK        the operation completed successfully.
      * \retval C2_NO_MEMORY not enough memory to complete this method.
      */
-    virtual C2Status getSupportedParams(
+    virtual c2_status_t querySupportedParams_nb(
             std::vector<std::shared_ptr<C2ParamDescriptor>> * const params) const = 0;
 
     /**
+     * Retrieves the supported values for the queried fields.
      *
-     * \todo should this take a list considering that setting some fields may further limit other
-     * fields in the same list?
+     * Client SHALL set the parameter-field specifier and the type of supported values query (e.g.
+     * currently supported values, or potential supported values) in fields.
+     * Upon return the component SHALL fill in the supported values for the fields listed as well
+     * as a status for each field. Component shall process all fields queried even if some queries
+     * fail.
+     *
+     * This method MUST be "non-blocking" and return within 1ms.
+     *
+     * \param[in out] fields a vector of fields descriptor structures.
+     *
+     * \retval C2_OK        the operation completed successfully.
+     * \retval C2_BAD_INDEX at least one field was not recognized as a component field
      */
-    virtual C2Status getSupportedValues(
+    virtual c2_status_t querySupportedValues_nb(
             std::vector<C2FieldSupportedValuesQuery> &fields) const = 0;
 
     virtual ~C2ComponentInterface() = default;
@@ -316,6 +300,75 @@
 
 class C2Component {
 public:
+    class Listener {
+    public:
+        virtual void onWorkDone_nb(std::weak_ptr<C2Component> component,
+                                std::vector<std::unique_ptr<C2Work>> workItems) = 0;
+
+        virtual void onTripped_nb(std::weak_ptr<C2Component> component,
+                               std::vector<std::shared_ptr<C2SettingResult>> settingResult) = 0;
+
+        virtual void onError_nb(std::weak_ptr<C2Component> component,
+                             uint32_t errorCode) = 0;
+
+        // virtual void onTunnelReleased(<from>, <to>) = 0;
+
+        // virtual void onComponentReleased(<id>) = 0;
+
+    protected:
+        virtual ~Listener() = default;
+    };
+
+    /**
+     * Sets the listener for this component
+     *
+     * This method MUST be supported in all states. The listener can only be set to non-null value
+     * in non-running state (that does not include tripped or error). It can be set to nullptr in
+     * any state. Components only use the listener in running state.
+     *
+     * If listener is nullptr, the component SHALL guarantee that no more listener callbacks are
+     * done to the original listener once this method returns. (Any pending listener callbacks will
+     * need to be completed during this call - hence this call may be temporarily blocking.)
+     *
+     * This method may be momentarily blocking, but must return within 5ms.
+     *
+     * Component SHALL handle listener notifications from the same thread (the thread used is
+     * at the component's discretion.)
+     *
+     * \note This could also be accomplished by passing a weak_ptr to a component-specific listener
+     * here and requiring the client to always promote the weak_ptr before any callback. This would
+     * put the burden on the client to clear the listener - wait for its deletion - at which point
+     * it is guaranteed that no more listener callbacks will occur.
+     *
+     * \todo TBD is this needed? or move it to createComponent()
+     *
+     * \param listener the component listener object
+     *
+     * \retval C2_BAD_STATE attempting to change the listener in the running state (user error)
+     * \retval C2_OK        listener was updated successfully.
+     */
+    virtual c2_status_t setListener_sm(const std::shared_ptr<Listener> &listener) = 0;
+
+    /**
+     * Information about a component.
+     */
+    struct Traits {
+    // public:
+    // TBD
+    #if 0
+        C2String name;             ///< name of the component
+        C2DomainKind domain;       ///< component domain (e.g. audio or video)
+        C2ComponentKind type;      ///< component type (e.g. encoder, decoder or filter)
+        C2StringLiteral mediaType; ///< media type supported by the component
+
+        /**
+         * name alias(es) for backward compatibility.
+         * \note Multiple components can have the same alias as long as their media-type differs.
+         */
+        std::vector<C2StringLiteral> aliases; ///< name aliases for backward compatibility
+    #endif
+    };
+
     // METHODS AVAILABLE WHEN RUNNING
     // =============================================================================================
 
@@ -336,7 +389,7 @@
      * \retval C2_NO_MEMORY not enough memory to queue the work
      * \retval C2_CORRUPTED some unknown error prevented queuing the work (unexpected)
      */
-    virtual C2Status queue_nb(std::list<std::unique_ptr<C2Work>>* const items) = 0;
+    virtual c2_status_t 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
@@ -354,8 +407,17 @@
      * \retval C2_CORRUPTED some unknown error prevented recording the announcement (unexpected)
      *
      * \todo Can this be rolled into queue_nb?
+     * \todo Expose next work item for each component to detect stalls
      */
-    virtual C2Status announce_nb(const std::vector<C2WorkOutline> &items) = 0;
+    virtual c2_status_t announce_nb(const std::vector<C2WorkOutline> &items) = 0;
+
+    enum flush_mode_t : uint32_t {
+        /// flush work from this component only
+        FLUSH_COMPONENT,
+        /// flush work from this component and all components connected downstream from it via
+        /// tunneling
+        FLUSH_CHAIN,
+    };
 
     /**
      * Discards and abandons any pending work for the component, and optionally any component
@@ -379,22 +441,33 @@
      *
      * Work that could not be abandoned or discarded immediately SHALL be marked to be
      * discarded at the earliest opportunity, and SHALL be returned via the onWorkDone() callback.
+     * This shall be completed within 500ms.
      *
-     * \param flushThrough    flush work from this component and all components connected downstream
-     *                      from it via tunneling.
+     * \param mode flush mode
      *
-     * \retval C2_OK        the work announcement has been successfully recorded
+     * \retval C2_OK        the component has been successfully flushed
      * \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 C2Status flush_sm(bool flushThrough, std::list<std::unique_ptr<C2Work>>* const flushedWork) = 0;
+    virtual c2_status_t flush_sm(flush_mode_t mode, std::list<std::unique_ptr<C2Work>>* const flushedWork) = 0;
+
+    enum drain_mode_t : uint32_t {
+        /// drain component only
+        DRAIN_COMPONENT,
+        /// marks the last work item with a persistent "end-of-stream" marker that will drain
+        /// downstream components
+        /// \todo this may confuse work-ordering downstream
+        DRAIN_CHAIN,
+        /**
+         * \todo define this; we could place EOS to all upstream components, just this component, or
+         *       all upstream and downstream component.
+         * \todo should EOS carry over to downstream components?
+         */
+    };
 
     /**
-     * Drains the component, and optionally downstream components
-     *
-     * \todo define this; we could place EOS to all upstream components, just this component, or
-     *       all upstream and downstream component.
-     * \todo should EOS carry over to downstream components?
+     * Drains the component, and optionally downstream components. This is a signalling method;
+     * as such it does not wait for any work completion.
      *
      * Marks last work item as "end-of-stream", so component is notified not to wait for further
      * work before it processes work already queued. This method is called to set the end-of-stream
@@ -407,16 +480,13 @@
      *
      * Work that is completed SHALL be returned via the onWorkDone() callback.
      *
-     * \param drainThrough    marks the last work item with a persistent "end-of-stream" marker that
-     *                      will drain downstream components.
+     * \param mode drain mode
      *
-     * \todo this may confuse work-ordering downstream; could be an mode enum
-     *
-     * \retval C2_OK        the work announcement has been successfully recorded
+     * \retval C2_OK        the drain request has been successfully recorded
      * \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 C2Status drain_nb(bool drainThrough) = 0;
+    virtual c2_status_t drain_nb(drain_mode_t mode) = 0;
 
     // STATE CHANGE METHODS
     // =============================================================================================
@@ -430,14 +500,12 @@
      * there are no immediate guarantees. Though there are guarantees for responsiveness immediately
      * after start returns.
      *
-     * \todo Could we just start a ComponentInterface to get a Component?
-     *
-     * \retval C2_OK        the work announcement has been successfully recorded
+     * \retval C2_OK        the component has started successfully
      * \retval C2_NO_MEMORY not enough memory to start the component
      * \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 C2Status start() = 0;
+    virtual c2_status_t start() = 0;
 
     /**
      * Stops the component.
@@ -454,14 +522,14 @@
      * 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 C2Status stop() = 0;
+    virtual c2_status_t stop() = 0;
 
     /**
      * Resets the component.
      *
-     * This method MUST be supported in running (including tripped) state.
+     * This method MUST be supported in all (including tripped) state.
      *
-     * This method MUST be supported during any other call (\todo or just blocking ones?)
+     * This method MUST be supported during any other blocking call.
      *
      * This method MUST return withing 500ms.
      *
@@ -473,22 +541,24 @@
      * This brings settings back to their default - "guaranteeing" no tripped space.
      *
      * \todo reclaim support - it seems that since ownership is passed, this will allow reclaiming stuff.
+     *
+     * \retval C2_OK        the component has been reset
+     * \retval C2_TIMED_OUT the component could not be reset within the time limit (unexpected)
+     * \retval C2_CORRUPTED some unknown error prevented resetting the component (unexpected)
      */
     virtual void reset() = 0;
 
     /**
      * Releases the component.
      *
-     * This method MUST be supported in any state. (\todo Or shall we force reset() first to bring
-     * to a known state?)
+     * This method MUST be supported in stopped state.
      *
-     * This method MUST return withing 500ms.
+     * This method MUST return withing 500ms. Upon return all references shall be abandoned.
      *
-     * \todo should this return completed work, since client will just free it? Also, if it unblocks
-     * a stop, where should completed work be returned?
-     *
-     * TODO: does it matter if this call has a short time limit? Yes, as upon return all references
-     * shall be abandoned.
+     * \retval C2_OK        the component has been released
+     * \retval C2_BAD_STATE the component is running
+     * \retval C2_TIMED_OUT the component could not be released within the time limit (unexpected)
+     * \retval C2_CORRUPTED some unknown error prevented releasing the component (unexpected)
      */
     virtual void release() = 0;
 
@@ -515,6 +585,8 @@
     /**
      * \return a vector of supported parameter indices parsed by this info parser.
      *
+     * This method MUST be "non-blocking" and return within 1ms.
+     *
      * \todo sticky vs. non-sticky params? this may be communicated by param-reflector.
      */
     virtual const std::vector<C2Param::Index> getParsedParams() const = 0;
@@ -528,18 +600,13 @@
      * \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 C2Status reset() { return C2_OK; }
+    virtual c2_status_t reset() { return C2_OK; }
 
-    virtual C2Status parseFrame(C2BufferPack &frame);
+    virtual c2_status_t parseFrame(C2BufferPack &frame);
 
     virtual ~C2FrameInfoParser() = default;
 };
 
-struct C2ComponentInfo {
-    // TBD
-
-};
-
 class C2AllocatorStore {
 public:
     typedef C2Allocator::id_t id_t;
@@ -564,16 +631,18 @@
     /**
      * Returns the set of allocators supported by this allocator store.
      *
-     * This method SHALL return within 1ms.
+     * This method MUST be "non-blocking" and return within 1ms.
      *
      * \retval vector of allocator information (as shared pointers)
      * \retval an empty vector if there was not enough memory to allocate the whole vector.
      */
-    virtual std::vector<std::shared_ptr<const C2Allocator::Info>> listAllocators() const = 0;
+    virtual std::vector<std::shared_ptr<const C2Allocator::Traits>> listAllocators_nb() const = 0;
 
     /**
      * Retrieves/creates a shared allocator object.
      *
+     * This method MUST be return within 5ms.
+     *
      * The allocator is created on first use, and the same allocator is returned on subsequent
      * concurrent uses in the same process. The allocator is freed when it is no longer referenced.
      *
@@ -589,7 +658,7 @@
      * \retval C2_NOT_FOUND no such allocator
      * \retval C2_NO_MEMORY not enough memory to create the allocator
      */
-    virtual C2Status getAllocator(id_t id, std::shared_ptr<C2Allocator>* const allocator) = 0;
+    virtual c2_status_t fetchAllocator(id_t id, std::shared_ptr<C2Allocator>* const allocator) = 0;
 
     virtual ~C2AllocatorStore() = default;
 };
@@ -597,6 +666,21 @@
 class C2ComponentStore {
 public:
     /**
+     * Returns the name of this component or component interface object.
+     * This is a unique name for this component or component interface 'class'; however, multiple
+     * instances of this component SHALL have the same name.
+     *
+     * This method MUST be supported in any state. This call does not change the state nor the
+     * internal states of the component.
+     *
+     * This method MUST be "non-blocking" and return within 1ms.
+     *
+     * \return the name of this component or component interface object.
+     * \retval an empty string if there was not enough memory to allocate the actual name.
+     */
+    virtual C2String getName() const = 0;
+
+    /**
      * Creates a component.
      *
      * This method SHALL return within 100ms.
@@ -612,7 +696,8 @@
      * \retval C2_NOT_FOUND no such component
      * \retval C2_NO_MEMORY not enough memory to create the component
      */
-    virtual C2Status createComponent(C2String name, std::shared_ptr<C2Component>* const component);
+    virtual c2_status_t createComponent(
+            C2String name, std::shared_ptr<C2Component>* const component) = 0;
 
     /**
      * Creates a component interface.
@@ -633,26 +718,27 @@
      *
      * \todo Do we need an interface, or could this just be a component that is never started?
      */
-    virtual C2Status createInterface(C2String name, std::shared_ptr<C2ComponentInterface>* const interface);
+    virtual c2_status_t createInterface(
+            C2String name, std::shared_ptr<C2ComponentInterface>* const interface) = 0;
 
     /**
      * Returns the list of components supported by this component store.
      *
-     * This method SHALL return within 1ms.
+     * This method may be momentarily blocking, but MUST return within 5ms.
      *
      * \retval vector of component information.
      */
-    virtual std::vector<std::unique_ptr<const C2ComponentInfo>> getComponents();
+    virtual std::vector<std::shared_ptr<const C2Component::Traits>> listComponents_sm() const = 0;
 
     // -------------------------------------- UTILITY METHODS --------------------------------------
 
     // on-demand buffer layout conversion (swizzling)
-    virtual C2Status copyBuffer(std::shared_ptr<C2GraphicBuffer> src, std::shared_ptr<C2GraphicBuffer> dst);
+    //
+    virtual c2_status_t copyBuffer(
+            std::shared_ptr<C2GraphicBuffer> src, std::shared_ptr<C2GraphicBuffer> dst) = 0;
 
-    // C2Status selectPreferredColor(formats<A>, formats<B>);
-
-    // GLOBAL SETTINGS
-    // system-wide stride & slice-height (???)
+    // -------------------------------------- CONFIGURATION API -----------------------------------
+    // e.g. for global settings (system-wide stride, etc.)
 
     /**
      * Queries a set of system-wide parameters.
@@ -683,7 +769,7 @@
      * \retval C2_CORRUPTED some unknown error prevented the querying of the parameters
      *                      (unexpected)
      */
-    virtual C2Status query_sm(
+    virtual c2_status_t query_sm(
         const std::vector<C2Param* const> &stackParams,
         const std::vector<C2Param::Index> &heapParamIndices,
         std::vector<std::unique_ptr<C2Param>>* const heapParams) const = 0;
@@ -701,15 +787,15 @@
      * \note Parameter tuning DOES depend on the order of the tuning parameters. E.g. some parameter
      * update may allow some subsequent parameter update.
      *
-     * This method MUST be "non-blocking" and return within 1ms.
+     * This method may be momentarily blocking, but MUST return within 5ms.
      *
-     * \param params          a list of parameter updates. These will be updated to the actual
+     * \param params        a list of parameter updates. These will be updated to the actual
      *                      parameter values after the updates (this is because tuning is performed
      *                      at best effort).
      *                      \todo params that could not be updated are not marked here, so are
      *                      confusing - are they "existing" values or intended to be configured
      *                      values?
-     * \param failures        a list of parameter failures
+     * \param failures      a list of parameter failures
      *
      * \retval C2_OK        all parameters could be updated successfully
      * \retval C2_BAD_INDEX all supported parameters could be updated successfully, but some
@@ -722,9 +808,95 @@
      * \retval C2_CORRUPTED some unknown error prevented the update of the parameters
      *                      (unexpected)
      */
-    virtual C2Status config_nb(
+    virtual c2_status_t config_sm(
             const std::vector<C2Param* const> &params,
-            std::list<std::unique_ptr<C2SettingResult>>* const failures) = 0;
+            std::vector<std::unique_ptr<C2SettingResult>>* const failures) = 0;
+
+    /**
+     * Atomically sets a set of system-wide parameters.
+     *
+     * \note There are no settable system-wide parameters defined thus far, but may be added in the
+     * future.
+     *
+     * The component store SHALL update all supported configuration at best effort(TBD)
+     * (unless configured otherwise) and skip unsupported ones. If any errors are encountered
+     * (other than unsupported parameters), the configuration SHALL be aborted as if it did not
+     * happen.
+     *
+     * \note Parameter tuning DOES depend on the order of the tuning parameters. E.g. some parameter
+     * update may allow some subsequent parameter update.
+     *
+     * This method may be momentarily blocking, but MUST return within 5ms.
+     *
+     * \param params[in,out] a list of parameter updates. These will be updated to the actual
+     *                       parameter values after the updates (this is because tuning is performed
+     *                       at best effort).
+     *                       \todo params that could not be updated are not marked here, so are
+     *                       confusing - are they "existing" values or intended to be configured
+     *                       values?
+     * \param failures[out]  a list of parameter failures
+     *
+     * \retval C2_OK        all parameters could be updated successfully
+     * \retval C2_BAD_INDEX all supported parameters could be updated successfully, but some
+     *                      parameters were not supported
+     * \retval C2_BAD_VALUE some supported parameters could not be updated successfully because
+     *                      they contained unsupported values. These are returned in |failures|.
+     * \retval C2_NO_MEMORY some supported parameters could not be updated successfully because
+     *                      they contained unsupported values, but could not allocate a failure
+     *                      object for them.
+     * \retval C2_CORRUPTED some unknown error prevented the update of the parameters
+     *                      (unexpected)
+     */
+    virtual c2_status_t commit_sm(
+            const std::vector<C2Param* const> &params,
+            std::vector<std::unique_ptr<C2SettingResult>>* const failures) = 0;
+
+    // REFLECTION MECHANISM (USED FOR EXTENSION)
+    // =============================================================================================
+
+    /**
+     * Returns the parameter reflector.
+     *
+     * This is used to describe parameter fields. This is shared for all components created by
+     * this component store.
+     *
+     * This method MUST be "non-blocking" and return within 1ms.
+     *
+     * \return a shared parameter reflector object.
+     */
+    virtual std::shared_ptr<C2ParamReflector> getParamReflector() const = 0;
+
+    /**
+     * Returns the set of supported parameters.
+     *
+     * This method MUST be "non-blocking" and return within 1ms.
+     *
+     * \param[out] params a vector of supported parameters will be appended to this vector.
+     *
+     * \retval C2_OK        the operation completed successfully.
+     * \retval C2_NO_MEMORY not enough memory to complete this method.
+     */
+    virtual c2_status_t querySupportedParams_nb(
+            std::vector<std::shared_ptr<C2ParamDescriptor>> * const params) const = 0;
+
+    /**
+     * Retrieves the supported values for the queried fields.
+     *
+     * Client SHALL set the parameter-field specifier and the type of supported values query (e.g.
+     * currently supported values, or potential supported values) in fields.
+     * Upon return the store SHALL fill in the supported values for the fields listed as well
+     * as a status for each field. Store shall process all fields queried even if some queries
+     * fail.
+     *
+     * This method MUST be "non-blocking" and return within 1ms.
+     *
+     * \param[in out] fields a vector of fields descriptor structures.
+     *
+     * \retval C2_OK        the operation completed successfully.
+     * \retval C2_BAD_INDEX at least one field was not recognized as a component store field
+     */
+    virtual c2_status_t querySupportedValues_nb(
+            std::vector<C2FieldSupportedValuesQuery> &fields) const = 0;
 
     virtual ~C2ComponentStore() = default;
 };
diff --git a/media/libstagefright/codec2/include/C2Work.h b/media/libstagefright/codec2/include/C2Work.h
index 52c00d5..105cf81 100644
--- a/media/libstagefright/codec2/include/C2Work.h
+++ b/media/libstagefright/codec2/include/C2Work.h
@@ -75,14 +75,9 @@
 //  WORK
 // ================================================================================================
 
-// node_id-s
-typedef uint32_t node_id;
-
-enum flags_t : uint32_t {
-    BUFFERFLAG_CODEC_CONFIG  = (1 << 0),
-    BUFFERFLAG_DROP_FRAME    = (1 << 1),
-    BUFFERFLAG_END_OF_STREAM = (1 << 2),
-};
+// c2_node_id_t-s
+typedef uint32_t c2_node_id_t;
+typedef c2_node_id_t c2_node_id_t;
 
 enum {
     kParamIndexWorkOrdinal,
@@ -101,6 +96,12 @@
 
 struct C2BufferPack {
 //public:
+    enum flags_t : uint32_t {
+        FLAG_CODEC_CONFIG  = (1 << 0),
+        FLAG_DROP_FRAME    = (1 << 1),
+        FLAG_END_OF_STREAM = (1 << 2),
+    };
+
     flags_t  flags;
     C2WorkOrdinalStruct ordinal;
     std::vector<std::shared_ptr<C2Buffer>> buffers;
@@ -113,7 +114,7 @@
 struct C2Worklet {
 //public:
     // IN
-    node_id component;
+    c2_node_id_t component;
 
     std::list<std::unique_ptr<C2Param>> tunings; //< tunings to be applied before processing this
                                                  // worklet
@@ -165,13 +166,13 @@
     std::list<std::unique_ptr<C2Worklet>> worklets;
 
     uint32_t worklets_processed;
-    C2Status result;
+    c2_status_t result;
 };
 
 struct C2WorkOutline {
 //public:
     C2WorkOrdinalStruct ordinal;
-    std::list<node_id> chain;
+    std::list<c2_node_id_t> chain;
 };
 
 /// @}
diff --git a/media/libstagefright/codec2/tests/C2ComponentInterface_test.cpp b/media/libstagefright/codec2/tests/C2ComponentInterface_test.cpp
index b725d76..0613b5a 100644
--- a/media/libstagefright/codec2/tests/C2ComponentInterface_test.cpp
+++ b/media/libstagefright/codec2/tests/C2ComponentInterface_test.cpp
@@ -72,7 +72,7 @@
 
     // If a parameter is writable this is called.
     // Test one filed |writableField| for given writable parameter |param|.
-    // |validValues| contains all values obtained from getSupportedValues() for |writableField|.
+    // |validValues| contains all values obtained from querySupportedValues() for |writableField|.
     // The test checks validity for config() with each value, and make sure values are config-ed
     // by query() them out. |invalidValues| contains some values which are not in |validValues|.
     // The test expects C2_BAD_VALUE while config() with these values,
@@ -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 C2Status (e.g. C2_OK).
-    template <typename T> C2Status queryOnStack(T *const p);
+    // The return value is c2_status_t (e.g. C2_OK).
+    template <typename T> c2_status_t queryOnStack(T *const p);
 
     template <typename T>
-    C2Status queryOnHeap(const T &p,
+    c2_status_t 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>
-    C2Status
+    c2_status_t
     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, C2Status *stConfig);
+    template <typename T> void configWritableParamValidValue(const T &newParam, c2_status_t *stConfig);
 
     // Test if config works correctly in the case an invalid value |newParam| is tried to write
     // to an writable parameter.
@@ -194,13 +194,13 @@
         }                                               \
     } while (false)
 
-template <typename T> C2Status C2CompIntfTest::queryOnStack(T *const p) {
+template <typename T> c2_status_t C2CompIntfTest::queryOnStack(T *const p) {
     std::vector<C2Param *const> stackParams{p};
     return mIntf->query_nb(stackParams, {}, nullptr);
 }
 
 template <typename T>
-C2Status C2CompIntfTest::queryOnHeap(
+c2_status_t 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>
-C2Status C2CompIntfTest::config(
+c2_status_t 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, C2Status *configResult) {
+void C2CompIntfTest::configWritableParamValidValue(const T &newParam, c2_status_t *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.
-    C2Status stConfig = mIntf->config_nb(params, &failures);
+    c2_status_t stConfig = mIntf->config_nb(params, &failures);
     if (stConfig == C2_OK) {
         EXPECT_EQ(0u, failures.size());
     } else {
@@ -481,7 +481,7 @@
         TParam *const param, TRealField *const writableField,
         const std::vector<TField> &validValues,
         const std::vector<TField> &invalidValues) {
-    C2Status stConfig;
+    c2_status_t stConfig;
 
     // Get the parameter's value in the beginning in order to reset the value at the end.
     TRACED_FAILURE(getValue(param));
@@ -555,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.
-    C2Status stStack = config(param.get(), &failures);
+    c2_status_t stStack = config(param.get(), &failures);
     if (stStack == C2_BAD_VALUE) {
         // Read-only
         std::unique_ptr<T> newParam = makeParam<T>();
@@ -594,7 +594,7 @@
                     C2ParamField(param.get(), &field_type_name_::field_name_)) \
         };                                                              \
         ASSERT_EQ(C2_OK,                                                \
-                  mIntf->getSupportedValues(validValueInfos));          \
+                  mIntf->querySupportedValues_nb(validValueInfos));     \
         ASSERT_EQ(1u, validValueInfos.size());                          \
         std::vector<decltype(param->field_name_)> validValues;          \
         std::vector<decltype(param->field_name_)> invalidValues;        \
@@ -640,7 +640,7 @@
     setComponent(intf);
 
     std::vector<std::shared_ptr<C2ParamDescriptor>> supportedParams;
-    ASSERT_EQ(C2_OK, mIntf->getSupportedParams(&supportedParams));
+    ASSERT_EQ(C2_OK, mIntf->querySupportedParams_nb(&supportedParams));
 
     EACH_TEST_SELF(C2ComponentLatencyInfo, TEST_U32_WRITABLE_FIELD);
     EACH_TEST_SELF(C2ComponentTemporalInfo, TEST_U32_WRITABLE_FIELD);
diff --git a/media/libstagefright/codec2/tests/C2Param_test.cpp b/media/libstagefright/codec2/tests/C2Param_test.cpp
index 97c5f91..a688d2c 100644
--- a/media/libstagefright/codec2/tests/C2Param_test.cpp
+++ b/media/libstagefright/codec2/tests/C2Param_test.cpp
@@ -2393,41 +2393,41 @@
 
 class MyComponentInstance : public C2ComponentInterface {
 public:
-    virtual C2String getName() const {
+    virtual C2String getName() const override {
         /// \todo this seems too specific
         return "sample.interface";
     };
 
-    virtual node_id getId() const {
+    virtual c2_node_id_t getId() const override {
         /// \todo how are these shared?
         return 0;
     }
 
-    virtual C2Status commit_sm(
+    virtual c2_status_t commit_sm(
             const std::vector<C2Param* const> &params,
-            std::vector<std::unique_ptr<C2SettingResult>>* const failures) {
+            std::vector<std::unique_ptr<C2SettingResult>>* const failures) override {
         (void)params;
         (void)failures;
         return C2_OMITTED;
     }
 
-    virtual C2Status config_nb(
+    virtual c2_status_t config_nb(
             const std::vector<C2Param* const> &params,
-            std::vector<std::unique_ptr<C2SettingResult>>* const failures) {
+            std::vector<std::unique_ptr<C2SettingResult>>* const failures) override {
         (void)params;
         (void)failures;
         return C2_OMITTED;
     }
 
-    virtual C2Status createTunnel_sm(node_id targetComponent) {
+    virtual c2_status_t createTunnel_sm(c2_node_id_t targetComponent) override {
         (void)targetComponent;
         return C2_OMITTED;
     }
 
-    virtual C2Status query_nb(
+    virtual c2_status_t query_nb(
             const std::vector<C2Param* const> &stackParams,
             const std::vector<C2Param::Index> &heapParamIndices,
-            std::vector<std::unique_ptr<C2Param>>* const heapParams) const {
+            std::vector<std::unique_ptr<C2Param>>* const heapParams) const override {
         for (C2Param* const param : stackParams) {
             if (!*param) { // param is already invalid - remember it
                 continue;
@@ -2466,7 +2466,7 @@
         mMyParams.insert({mDomainInfo.type(), mDomainInfo});
     }
 
-    virtual C2Status releaseTunnel_sm(node_id targetComponent) {
+    virtual c2_status_t releaseTunnel_sm(c2_node_id_t targetComponent) override {
         (void)targetComponent;
         return C2_OMITTED;
     }
@@ -2477,7 +2477,7 @@
     public:
         MyParamReflector(const MyComponentInstance *i) : instance(i) { }
 
-        virtual std::unique_ptr<C2StructDescriptor> describe(C2Param::BaseIndex paramIndex) {
+        virtual std::unique_ptr<C2StructDescriptor> describe(C2Param::BaseIndex paramIndex) override {
             switch (paramIndex.coreIndex()) {
             case decltype(instance->mDomainInfo)::coreIndex:
             default:
@@ -2490,8 +2490,8 @@
         }
     };
 
-    virtual C2Status getSupportedValues(
-            std::vector<C2FieldSupportedValuesQuery> &fields) const {
+    virtual c2_status_t querySupportedValues_nb(
+            std::vector<C2FieldSupportedValuesQuery> &fields) const override {
         for (C2FieldSupportedValuesQuery &query : fields) {
             if (query.field == C2ParamField(&mDomainInfo, &C2ComponentDomainInfo::mValue)) {
                 query.values = C2FieldSupportedValues(
@@ -2508,22 +2508,20 @@
         return C2_OK;
     }
 
-    virtual std::shared_ptr<C2ParamReflector> getParamReflector() const {
+    std::shared_ptr<C2ParamReflector> getParamReflector() const {
         return std::shared_ptr<C2ParamReflector>(new MyParamReflector(this));
     }
 
-    virtual C2Status getSupportedParams(std::vector<std::shared_ptr<C2ParamDescriptor>> * const params) const {
+    virtual c2_status_t querySupportedParams_nb(
+            std::vector<std::shared_ptr<C2ParamDescriptor>> * const params) const override {
         params->push_back(std::make_shared<C2ParamDescriptor>(
                 true /* required */, "_domain", &mDomainInfo));
-        return C2_OK;
-    }
-
-    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;
     }
 
+    virtual ~MyComponentInstance() override = default;
 };
 
 template<typename E, bool S=std::is_enum<E>::value>
@@ -2700,10 +2698,11 @@
 
 TEST_F(C2ParamTest, ReflectorTest) {
     C2ComponentDomainInfo domainInfo;
-    std::shared_ptr<C2ComponentInterface> comp(new MyComponentInstance);
+    std::shared_ptr<MyComponentInstance> myComp(new MyComponentInstance);
+    std::shared_ptr<C2ComponentInterface> comp = myComp;
 
     std::unique_ptr<C2StructDescriptor> desc{
-        comp->getParamReflector()->describe(C2ComponentDomainInfo::indexFlags)};
+        myComp->getParamReflector()->describe(C2ComponentDomainInfo::indexFlags)};
     dumpStruct(*desc);
 
     std::vector<C2FieldSupportedValuesQuery> query = {
@@ -2714,7 +2713,7 @@
         C2FieldSupportedValuesQuery::Current(C2ParamField(&domainInfo, &C2ComponentDomainInfo::mValue)),
     };
 
-    EXPECT_EQ(C2_OK, comp->getSupportedValues(query));
+    EXPECT_EQ(C2_OK, comp->querySupportedValues_nb(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 3d23c23..1bcf070 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) {
-        C2Status err = mLinearAllocator->newLinearAllocation(
+        c2_status_t err = mLinearAllocator->newLinearAllocation(
                 capacity,
                 { C2MemoryUsage::kSoftwareRead, C2MemoryUsage::kSoftwareWrite },
                 &mLinearAllocation);
@@ -50,7 +50,7 @@
 
     void mapLinear(size_t offset, size_t size, uint8_t **addr) {
         ASSERT_TRUE(mLinearAllocation);
-        C2Status err = mLinearAllocation->map(
+        c2_status_t err = mLinearAllocation->map(
                 offset,
                 size,
                 { C2MemoryUsage::kSoftwareRead, C2MemoryUsage::kSoftwareWrite },
@@ -82,7 +82,7 @@
     }
 
     void allocateGraphic(uint32_t width, uint32_t height) {
-        C2Status err = mGraphicAllocator->newGraphicAllocation(
+        c2_status_t err = mGraphicAllocator->newGraphicAllocation(
                 width,
                 height,
                 HAL_PIXEL_FORMAT_YCBCR_420_888,
@@ -96,7 +96,7 @@
 
     void mapGraphic(C2Rect rect, C2PlaneLayout *layout, uint8_t **addr) {
         ASSERT_TRUE(mGraphicAllocation);
-        C2Status err = mGraphicAllocation->map(
+        c2_status_t 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 3e2242b..da8372c 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 C2Status maperr2error(Error maperr) {
+static c2_status_t maperr2error(Error maperr) {
     switch (maperr) {
         case Error::NONE:           return C2_OK;
         case Error::BAD_DESCRIPTOR: return C2_BAD_VALUE;
@@ -52,12 +52,12 @@
 
 class C2AllocationGralloc : public C2GraphicAllocation {
 public:
-    virtual ~C2AllocationGralloc();
+    virtual ~C2AllocationGralloc() override;
 
-    virtual C2Status map(
+    virtual c2_status_t map(
             C2Rect rect, C2MemoryUsage usage, int *fenceFd,
             C2PlaneLayout *layout /* nonnull */, uint8_t **addr /* nonnull */) override;
-    virtual C2Status unmap(C2Fence *fenceFd /* nullable */) override;
+    virtual c2_status_t 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;
-    C2Status status() const;
+    c2_status_t status() const;
 
 private:
     const IMapper::BufferDescriptorInfo mInfo;
@@ -100,7 +100,7 @@
     mMapper->freeBuffer(const_cast<native_handle_t *>(mBuffer));
 }
 
-C2Status C2AllocationGralloc::map(
+c2_status_t C2AllocationGralloc::map(
         C2Rect rect, C2MemoryUsage usage, int *fenceFd,
         C2PlaneLayout *layout /* nonnull */, uint8_t **addr /* nonnull */) {
     // TODO
@@ -114,7 +114,7 @@
         return C2_BAD_VALUE;
     }
 
-    C2Status err = C2_OK;
+    c2_status_t err = C2_OK;
     if (!mBuffer) {
         mMapper->importBuffer(
                 mHandle, [&err, this](const auto &maperr, const auto &buffer) {
@@ -202,9 +202,9 @@
     return C2_OK;
 }
 
-C2Status C2AllocationGralloc::unmap(C2Fence *fenceFd /* nullable */) {
+c2_status_t C2AllocationGralloc::unmap(C2Fence *fenceFd /* nullable */) {
     // TODO: fence
-    C2Status err = C2_OK;
+    c2_status_t err = C2_OK;
     mMapper->unlock(
             const_cast<native_handle_t *>(mBuffer),
             [&err, &fenceFd](const auto &maperr, const auto &releaseFence) {
@@ -235,18 +235,18 @@
 
     C2String getName() const;
 
-    C2Status newGraphicAllocation(
+    c2_status_t newGraphicAllocation(
             uint32_t width, uint32_t height, uint32_t format, const C2MemoryUsage &usage,
             std::shared_ptr<C2GraphicAllocation> *allocation);
 
-    C2Status priorGraphicAllocation(
+    c2_status_t priorGraphicAllocation(
             const C2Handle *handle,
             std::shared_ptr<C2GraphicAllocation> *allocation);
 
-    C2Status status() const { return mInit; }
+    c2_status_t status() const { return mInit; }
 
 private:
-    C2Status mInit;
+    c2_status_t mInit;
     sp<IAllocator> mAllocator;
     sp<IMapper> mMapper;
 };
@@ -268,7 +268,7 @@
     return "android.allocator.gralloc";
 }
 
-C2Status C2AllocatorGralloc::Impl::newGraphicAllocation(
+c2_status_t C2AllocatorGralloc::Impl::newGraphicAllocation(
         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|
@@ -281,7 +281,7 @@
         (PixelFormat)format,
         BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN,
     };
-    C2Status err = C2_OK;
+    c2_status_t err = C2_OK;
     BufferDescriptor desc;
     mMapper->createDescriptor(
             info, [&err, &desc](const auto &maperr, const auto &descriptor) {
@@ -319,7 +319,7 @@
     return C2_OK;
 }
 
-C2Status C2AllocatorGralloc::Impl::priorGraphicAllocation(
+c2_status_t C2AllocatorGralloc::Impl::priorGraphicAllocation(
         const C2Handle *handle,
         std::shared_ptr<C2GraphicAllocation> *allocation) {
     (void) handle;
@@ -341,19 +341,19 @@
     return mImpl->getName();
 }
 
-C2Status C2AllocatorGralloc::newGraphicAllocation(
+c2_status_t C2AllocatorGralloc::newGraphicAllocation(
         uint32_t width, uint32_t height, uint32_t format, C2MemoryUsage usage,
         std::shared_ptr<C2GraphicAllocation> *allocation) {
     return mImpl->newGraphicAllocation(width, height, format, usage, allocation);
 }
 
-C2Status C2AllocatorGralloc::priorGraphicAllocation(
+c2_status_t C2AllocatorGralloc::priorGraphicAllocation(
         const C2Handle *handle,
         std::shared_ptr<C2GraphicAllocation> *allocation) {
     return mImpl->priorGraphicAllocation(handle, allocation);
 }
 
-C2Status C2AllocatorGralloc::status() const {
+c2_status_t C2AllocatorGralloc::status() const {
     return mImpl->status();
 }
 
diff --git a/media/libstagefright/codec2/vndk/C2AllocatorIon.cpp b/media/libstagefright/codec2/vndk/C2AllocatorIon.cpp
index 09df502..acd69af 100644
--- a/media/libstagefright/codec2/vndk/C2AllocatorIon.cpp
+++ b/media/libstagefright/codec2/vndk/C2AllocatorIon.cpp
@@ -82,20 +82,20 @@
 /* ======================================= ION ALLOCATION ====================================== */
 class C2AllocationIon : public C2LinearAllocation {
 public:
-    virtual C2Status map(
+    virtual c2_status_t map(
         size_t offset, size_t size, C2MemoryUsage usage, int *fence,
-        void **addr /* nonnull */);
-    virtual C2Status unmap(void *addr, size_t size, int *fenceFd);
-    virtual bool isValid() const;
-    virtual ~C2AllocationIon();
-    virtual const C2Handle *handle() const;
-    virtual bool equals(const std::shared_ptr<C2LinearAllocation> &other) const;
+        void **addr /* nonnull */) override;
+    virtual c2_status_t unmap(void *addr, size_t size, int *fenceFd) override;
+    virtual bool isValid() const override;
+    virtual ~C2AllocationIon() override;
+    virtual const C2Handle *handle() const override;
+    virtual bool equals(const std::shared_ptr<C2LinearAllocation> &other) const override;
 
     // internal methods
     C2AllocationIon(int ionFd, size_t size, size_t align, unsigned heapMask, unsigned flags);
     C2AllocationIon(int ionFd, size_t size, int shareFd);
     int dup() const;
-    C2Status status() const;
+    c2_status_t status() const;
 
 protected:
     class Impl;
@@ -142,7 +142,7 @@
         (void)mCapacity; // TODO
     }
 
-    C2Status map(size_t offset, size_t size, C2MemoryUsage usage, int *fenceFd, void **addr) {
+    c2_status_t 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;
@@ -159,7 +159,7 @@
         size_t mapOffset = offset - alignmentBytes;
         size_t mapSize = size + alignmentBytes;
 
-        C2Status err = C2_OK;
+        c2_status_t err = C2_OK;
         if (mMapFd == -1) {
             int ret = ion_map(mHandle.ionFd(), mHandle.buffer(), mapSize, prot,
                               flags, mapOffset, (unsigned char**)&mMapAddr, &mMapFd);
@@ -186,7 +186,7 @@
         return err;
     }
 
-    C2Status unmap(void *addr, size_t size, int *fenceFd) {
+    c2_status_t unmap(void *addr, size_t size, int *fenceFd) {
         if (addr != (uint8_t *)mMapAddr + mMapAlignmentBytes ||
                 size + mMapAlignmentBytes != mMapSize) {
             return C2_BAD_VALUE;
@@ -210,7 +210,7 @@
         (void)ion_free(mHandle.ionFd(), mHandle.buffer());
     }
 
-    C2Status status() const {
+    c2_status_t status() const {
         return mInit;
     }
 
@@ -227,7 +227,7 @@
     }
 
 private:
-    C2Status mInit;
+    c2_status_t mInit;
     C2HandleIon mHandle;
     int mMapFd; // only one for now
     void *mMapAddr;
@@ -236,12 +236,12 @@
     size_t mCapacity;
 };
 
-C2Status C2AllocationIon::map(
+c2_status_t C2AllocationIon::map(
     size_t offset, size_t size, C2MemoryUsage usage, int *fenceFd, void **addr) {
     return mImpl->map(offset, size, usage, fenceFd, addr);
 }
 
-C2Status C2AllocationIon::unmap(void *addr, size_t size, int *fenceFd) {
+c2_status_t C2AllocationIon::unmap(void *addr, size_t size, int *fenceFd) {
     return mImpl->unmap(addr, size, fenceFd);
 }
 
@@ -249,7 +249,7 @@
     return mImpl->status() == C2_OK;
 }
 
-C2Status C2AllocationIon::status() const {
+c2_status_t C2AllocationIon::status() const {
     return mImpl->status();
 }
 
@@ -302,7 +302,7 @@
     return "android.allocator.ion";
 }
 
-C2Status C2AllocatorIon::newLinearAllocation(
+c2_status_t C2AllocatorIon::newLinearAllocation(
         uint32_t capacity, C2MemoryUsage usage, std::shared_ptr<C2LinearAllocation> *allocation) {
     if (allocation == nullptr) {
         return C2_BAD_VALUE;
@@ -329,14 +329,14 @@
 
     std::shared_ptr<C2AllocationIon> alloc
         = std::make_shared<C2AllocationIon>(mIonFd, capacity, align, heapMask, flags);
-    C2Status ret = alloc->status();
+    c2_status_t ret = alloc->status();
     if (ret == C2_OK) {
         *allocation = alloc;
     }
     return ret;
 }
 
-C2Status C2AllocatorIon::priorLinearAllocation(
+c2_status_t C2AllocatorIon::priorLinearAllocation(
         const C2Handle *handle, std::shared_ptr<C2LinearAllocation> *allocation) {
     *allocation = nullptr;
     if (mInit != C2_OK) {
@@ -351,7 +351,7 @@
     const C2HandleIon *h = static_cast<const C2HandleIon*>(handle);
     std::shared_ptr<C2AllocationIon> alloc
         = std::make_shared<C2AllocationIon>(mIonFd, 0 /* capacity */, h->buffer());
-    C2Status ret = alloc->status();
+    c2_status_t 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 02e2dd9..d9bde7a 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(C2Status error)
+    explicit Impl(c2_status_t error)
         : mData(nullptr), mError(error) {}
 
     const uint8_t *data() const {
         return mData;
     }
 
-    C2Status error() const {
+    c2_status_t error() const {
         return mError;
     }
 
 private:
     const uint8_t *mData;
-    C2Status mError;
+    c2_status_t mError;
 };
 
 C2ReadView::C2ReadView(const _C2LinearCapacityAspect *parent, const uint8_t *data)
     : _C2LinearCapacityAspect(parent), mImpl(std::make_shared<Impl>(data)) {}
 
-C2ReadView::C2ReadView(C2Status error)
+C2ReadView::C2ReadView(c2_status_t error)
     : _C2LinearCapacityAspect(0u), mImpl(std::make_shared<Impl>(error)) {}
 
 const uint8_t *C2ReadView::data() const {
@@ -167,7 +167,7 @@
     return C2ReadView(&newCapacity, data() + offset);
 }
 
-C2Status C2ReadView::error() const {
+c2_status_t C2ReadView::error() const {
     return mImpl->error();
 }
 
@@ -176,33 +176,33 @@
     explicit Impl(uint8_t *base)
         : mBase(base), mError(C2_OK) {}
 
-    explicit Impl(C2Status error)
+    explicit Impl(c2_status_t error)
         : mBase(nullptr), mError(error) {}
 
     uint8_t *base() const {
         return mBase;
     }
 
-    C2Status error() const {
+    c2_status_t error() const {
         return mError;
     }
 
 private:
     uint8_t *mBase;
-    C2Status mError;
+    c2_status_t mError;
 };
 
 C2WriteView::C2WriteView(const _C2LinearRangeAspect *parent, uint8_t *base)
     : _C2EditableLinearRange(parent), mImpl(std::make_shared<Impl>(base)) {}
 
-C2WriteView::C2WriteView(C2Status error)
+C2WriteView::C2WriteView(c2_status_t error)
     : _C2EditableLinearRange(nullptr), mImpl(std::make_shared<Impl>(error)) {}
 
 uint8_t *C2WriteView::base() { return mImpl->base(); }
 
 uint8_t *C2WriteView::data() { return mImpl->base() + offset(); }
 
-C2Status C2WriteView::error() const { return mImpl->error(); }
+c2_status_t C2WriteView::error() const { return mImpl->error(); }
 
 class C2ConstLinearBlock::Impl {
 public:
@@ -212,7 +212,7 @@
     ~Impl() {
         if (mBase != nullptr) {
             // TODO: fence
-            C2Status err = mAllocation->unmap(mBase, mSize, nullptr);
+            c2_status_t err = mAllocation->unmap(mBase, mSize, nullptr);
             if (err != C2_OK) {
                 // TODO: Log?
             }
@@ -238,13 +238,13 @@
 
     const uint8_t *base() const { return mBase; }
 
-    C2Status error() const { return mError; }
+    c2_status_t error() const { return mError; }
 
 private:
     std::shared_ptr<C2LinearAllocation> mAllocation;
     uint8_t *mBase;
     size_t mSize;
-    C2Status mError;
+    c2_status_t mError;
 };
 
 C2ConstLinearBlock::C2ConstLinearBlock(std::shared_ptr<C2LinearAllocation> alloc)
@@ -277,7 +277,7 @@
     ~Impl() {
         if (mBase != nullptr) {
             // TODO: fence
-            C2Status err = mAllocation->unmap(mBase, mSize, nullptr);
+            c2_status_t err = mAllocation->unmap(mBase, mSize, nullptr);
             if (err != C2_OK) {
                 // TODO: Log?
             }
@@ -309,7 +309,7 @@
 
     uint8_t *base() const { return mBase; }
 
-    C2Status error() const { return mError; }
+    c2_status_t error() const { return mError; }
 
     C2Fence fence() const { return mFence; }
 
@@ -317,7 +317,7 @@
     std::shared_ptr<C2LinearAllocation> mAllocation;
     uint8_t *mBase;
     size_t mSize;
-    C2Status mError;
+    c2_status_t mError;
     C2Fence mFence;
 };
 
@@ -349,14 +349,14 @@
         const std::shared_ptr<C2Allocator> &allocator)
   : mAllocator(allocator) {}
 
-C2Status C2BasicLinearBlockPool::fetchLinearBlock(
+c2_status_t C2BasicLinearBlockPool::fetchLinearBlock(
         uint32_t capacity,
         C2MemoryUsage usage,
         std::shared_ptr<C2LinearBlock> *block /* nonnull */) {
     block->reset();
 
     std::shared_ptr<C2LinearAllocation> alloc;
-    C2Status err = mAllocator->newLinearAllocation(capacity, usage, &alloc);
+    c2_status_t err = mAllocator->newLinearAllocation(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(C2Status error) : mData(nullptr), mError(error) {}
+    explicit Impl(c2_status_t error) : mData(nullptr), mError(error) {}
 
     uint8_t *const *data() const { return mData; }
     const C2PlaneLayout &layout() const { return mLayout; }
-    C2Status error() const { return mError; }
+    c2_status_t error() const { return mError; }
 
 private:
     uint8_t *const *mData;
     C2PlaneLayout mLayout;
-    C2Status mError;
+    c2_status_t mError;
 };
 
 C2GraphicView::C2GraphicView(
@@ -410,7 +410,7 @@
         const C2PlaneLayout& layout)
     : _C2PlanarSection(parent), mImpl(new Impl(data, layout)) {}
 
-C2GraphicView::C2GraphicView(C2Status error)
+C2GraphicView::C2GraphicView(c2_status_t error)
     : _C2PlanarSection(nullptr), mImpl(new Impl(error)) {}
 
 const uint8_t *const *C2GraphicView::data() const {
@@ -437,7 +437,7 @@
     return view;
 }
 
-C2Status C2GraphicView::error() const {
+c2_status_t C2GraphicView::error() const {
     return mImpl->error();
 }
 
@@ -453,12 +453,12 @@
         }
     }
 
-    C2Status map(C2Rect rect) {
+    c2_status_t map(C2Rect rect) {
         if (mData[0] != nullptr) {
             // Already mapped.
             return C2_OK;
         }
-        C2Status err = mAllocation->map(
+        c2_status_t 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 {
-    C2Status err = mImpl->map(crop());
+    c2_status_t err = mImpl->map(crop());
     if (err != C2_OK) {
         C2DefaultGraphicView view(err);
         return C2AcquirableConstGraphicView(err, mFence, view);
@@ -518,13 +518,13 @@
         }
     }
 
-    C2Status map(C2Rect rect) {
+    c2_status_t map(C2Rect rect) {
         if (mData[0] != nullptr) {
             // Already mapped.
             return C2_OK;
         }
         uint8_t *data[C2PlaneLayout::MAX_NUM_PLANES];
-        C2Status err = mAllocation->map(
+        c2_status_t err = mAllocation->map(
                 rect,
                 { C2MemoryUsage::kSoftwareRead, C2MemoryUsage::kSoftwareWrite },
                 nullptr,
@@ -560,7 +560,7 @@
     : C2Block2D(alloc), mImpl(new Impl(alloc)) {}
 
 C2Acquirable<C2GraphicView> C2GraphicBlock::map() {
-    C2Status err = mImpl->map(crop());
+    c2_status_t 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) {}
 
-C2Status C2BasicGraphicBlockPool::fetchGraphicBlock(
+c2_status_t C2BasicGraphicBlockPool::fetchGraphicBlock(
         uint32_t width,
         uint32_t height,
         uint32_t format,
@@ -588,7 +588,7 @@
     block->reset();
 
     std::shared_ptr<C2GraphicAllocation> alloc;
-    C2Status err = mAllocator->newGraphicAllocation(width, height, format, usage, &alloc);
+    c2_status_t err = mAllocator->newGraphicAllocation(width, height, format, usage, &alloc);
     if (err != C2_OK) {
         return err;
     }
@@ -650,7 +650,7 @@
 
     const C2BufferData &data() const { return mData; }
 
-    C2Status registerOnDestroyNotify(OnDestroyNotify onDestroyNotify, void *arg) {
+    c2_status_t 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;
     }
 
-    C2Status unregisterOnDestroyNotify(OnDestroyNotify onDestroyNotify, void *arg) {
+    c2_status_t 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;
     }
 
-    C2Status setInfo(const std::shared_ptr<C2Info> &info) {
+    c2_status_t 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(); }
 
-C2Status C2Buffer::registerOnDestroyNotify(OnDestroyNotify onDestroyNotify, void *arg) {
+c2_status_t C2Buffer::registerOnDestroyNotify(OnDestroyNotify onDestroyNotify, void *arg) {
     return mImpl->registerOnDestroyNotify(onDestroyNotify, arg);
 }
 
-C2Status C2Buffer::unregisterOnDestroyNotify(OnDestroyNotify onDestroyNotify, void *arg) {
+c2_status_t C2Buffer::unregisterOnDestroyNotify(OnDestroyNotify onDestroyNotify, void *arg) {
     return mImpl->unregisterOnDestroyNotify(onDestroyNotify, arg);
 }
 
@@ -732,7 +732,7 @@
     return mImpl->infos();
 }
 
-C2Status C2Buffer::setInfo(const std::shared_ptr<C2Info> &info) {
+c2_status_t 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 f8ddfef..73ffaea 100644
--- a/media/libstagefright/codec2/vndk/C2Store.cpp
+++ b/media/libstagefright/codec2/vndk/C2Store.cpp
@@ -37,40 +37,40 @@
         /* ionmapper */
     );
 
-    virtual C2Status getAllocator(id_t id, std::shared_ptr<C2Allocator> *const allocator);
+    virtual c2_status_t fetchAllocator(id_t id, std::shared_ptr<C2Allocator> *const allocator) override;
 
-    virtual std::vector<std::shared_ptr<const C2Allocator::Info>> listAllocators() const {
-        return std::vector<std::shared_ptr<const C2Allocator::Info>>(); /// \todo
+    virtual std::vector<std::shared_ptr<const C2Allocator::Traits>> listAllocators_nb() const override {
+        return std::vector<std::shared_ptr<const C2Allocator::Traits>>(); /// \todo
     }
 
-    virtual C2String getName() const {
+    virtual C2String getName() const override {
         return "android.allocator-store";
     }
 
 private:
     // returns a shared-singleton ion allocator
-    std::shared_ptr<C2Allocator> getIonAllocator();
+    std::shared_ptr<C2Allocator> fetchIonAllocator();
 
     // returns a shared-singleton gralloc allocator
-    std::shared_ptr<C2Allocator> getGrallocAllocator();
+    std::shared_ptr<C2Allocator> fetchGrallocAllocator();
 };
 
 C2PlatformAllocatorStore::C2PlatformAllocatorStore() {
 }
 
-C2Status C2PlatformAllocatorStore::getAllocator(
+c2_status_t C2PlatformAllocatorStore::fetchAllocator(
         id_t id, std::shared_ptr<C2Allocator> *const allocator) {
     allocator->reset();
     switch (id) {
     // TODO: should we implement a generic registry for all, and use that?
     case C2PlatformAllocatorStore::ION:
     case C2AllocatorStore::DEFAULT_LINEAR:
-        *allocator = getIonAllocator();
+        *allocator = fetchIonAllocator();
         break;
 
     case C2PlatformAllocatorStore::GRALLOC:
     case C2AllocatorStore::DEFAULT_GRAPHIC:
-        *allocator = getGrallocAllocator();
+        *allocator = fetchGrallocAllocator();
         break;
 
     default:
@@ -82,7 +82,7 @@
     return C2_OK;
 }
 
-std::shared_ptr<C2Allocator> C2PlatformAllocatorStore::getIonAllocator() {
+std::shared_ptr<C2Allocator> C2PlatformAllocatorStore::fetchIonAllocator() {
     static std::mutex mutex;
     static std::weak_ptr<C2Allocator> ionAllocator;
     std::lock_guard<std::mutex> lock(mutex);
@@ -94,7 +94,7 @@
     return allocator;
 }
 
-std::shared_ptr<C2Allocator> C2PlatformAllocatorStore::getGrallocAllocator() {
+std::shared_ptr<C2Allocator> C2PlatformAllocatorStore::fetchGrallocAllocator() {
     static std::mutex mutex;
     static std::weak_ptr<C2Allocator> grallocAllocator;
     std::lock_guard<std::mutex> lock(mutex);
@@ -110,7 +110,7 @@
     return std::make_shared<C2PlatformAllocatorStore>();
 }
 
-C2Status GetCodec2BlockPool(
+c2_status_t GetCodec2BlockPool(
         C2BlockPool::local_id_t id, std::shared_ptr<const C2Component> component,
         std::shared_ptr<C2BlockPool> *pool) {
     pool->reset();
@@ -120,17 +120,17 @@
     // TODO support pre-registered block pools
     std::shared_ptr<C2AllocatorStore> allocatorStore = GetCodec2PlatformAllocatorStore();
     std::shared_ptr<C2Allocator> allocator;
-    C2Status res = C2_NOT_FOUND;
+    c2_status_t res = C2_NOT_FOUND;
 
     switch (id) {
     case C2BlockPool::BASIC_LINEAR:
-        res = allocatorStore->getAllocator(C2AllocatorStore::DEFAULT_LINEAR, &allocator);
+        res = allocatorStore->fetchAllocator(C2AllocatorStore::DEFAULT_LINEAR, &allocator);
         if (res == OK) {
             *pool = std::make_shared<C2BasicLinearBlockPool>(allocator);
         }
         break;
     case C2BlockPool::BASIC_GRAPHIC:
-        res = allocatorStore->getAllocator(C2AllocatorStore::DEFAULT_GRAPHIC, &allocator);
+        res = allocatorStore->fetchAllocator(C2AllocatorStore::DEFAULT_GRAPHIC, &allocator);
         if (res == OK) {
             *pool = std::make_shared<C2BasicGraphicBlockPool>(allocator);
         }
diff --git a/media/libstagefright/codec2/vndk/include/C2AllocatorGralloc.h b/media/libstagefright/codec2/vndk/include/C2AllocatorGralloc.h
index 78d41c4..374b0ed 100644
--- a/media/libstagefright/codec2/vndk/include/C2AllocatorGralloc.h
+++ b/media/libstagefright/codec2/vndk/include/C2AllocatorGralloc.h
@@ -34,23 +34,23 @@
 
     virtual C2String getName() const override;
 
-    virtual std::shared_ptr<const Info> getInfo() const override {
+    virtual std::shared_ptr<const Traits> getTraits() const override {
         return nullptr; // \todo
     }
 
-    virtual C2Status newGraphicAllocation(
+    virtual c2_status_t newGraphicAllocation(
             uint32_t width, uint32_t height, uint32_t format, C2MemoryUsage usage,
             std::shared_ptr<C2GraphicAllocation> *allocation) override;
 
-    virtual C2Status priorGraphicAllocation(
+    virtual c2_status_t priorGraphicAllocation(
             const C2Handle *handle,
             std::shared_ptr<C2GraphicAllocation> *allocation) override;
 
     C2AllocatorGralloc();
 
-    C2Status status() const;
+    c2_status_t status() const;
 
-    virtual ~C2AllocatorGralloc();
+    virtual ~C2AllocatorGralloc() override;
 
 private:
     class Impl;
diff --git a/media/libstagefright/codec2/vndk/include/C2AllocatorIon.h b/media/libstagefright/codec2/vndk/include/C2AllocatorIon.h
index 2fff91f..bb815f9 100644
--- a/media/libstagefright/codec2/vndk/include/C2AllocatorIon.h
+++ b/media/libstagefright/codec2/vndk/include/C2AllocatorIon.h
@@ -33,26 +33,26 @@
 
     virtual C2String getName() const override;
 
-    virtual std::shared_ptr<const Info> getInfo() const override {
+    virtual std::shared_ptr<const Traits> getTraits() const override {
         return nullptr; // \todo
     }
 
-    virtual C2Status newLinearAllocation(
+    virtual c2_status_t newLinearAllocation(
             uint32_t capacity, C2MemoryUsage usage,
             std::shared_ptr<C2LinearAllocation> *allocation) override;
 
-    virtual C2Status priorLinearAllocation(
+    virtual c2_status_t priorLinearAllocation(
             const C2Handle *handle,
             std::shared_ptr<C2LinearAllocation> *allocation) override;
 
     C2AllocatorIon();
 
-    C2Status status() const { return mInit; }
+    virtual c2_status_t status() const { return mInit; }
 
-    virtual ~C2AllocatorIon();
+    virtual ~C2AllocatorIon() override;
 
 private:
-    C2Status mInit;
+    c2_status_t 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 56b0123..875a8c2 100644
--- a/media/libstagefright/codec2/vndk/include/C2BufferPriv.h
+++ b/media/libstagefright/codec2/vndk/include/C2BufferPriv.h
@@ -27,7 +27,7 @@
 public:
     explicit C2BasicLinearBlockPool(const std::shared_ptr<C2Allocator> &allocator);
 
-    virtual ~C2BasicLinearBlockPool() = default;
+    virtual ~C2BasicLinearBlockPool() override = default;
 
     virtual C2Allocator::id_t getAllocatorId() const override {
         return mAllocator->getId();
@@ -37,7 +37,7 @@
         return BASIC_LINEAR;
     }
 
-    virtual C2Status fetchLinearBlock(
+    virtual c2_status_t fetchLinearBlock(
             uint32_t capacity,
             C2MemoryUsage usage,
             std::shared_ptr<C2LinearBlock> *block /* nonnull */) override;
@@ -52,7 +52,7 @@
 public:
     explicit C2BasicGraphicBlockPool(const std::shared_ptr<C2Allocator> &allocator);
 
-    virtual ~C2BasicGraphicBlockPool() = default;
+    virtual ~C2BasicGraphicBlockPool() override = default;
 
     virtual C2Allocator::id_t getAllocatorId() const override {
         return mAllocator->getId();
@@ -62,7 +62,7 @@
         return BASIC_GRAPHIC;
     }
 
-    virtual C2Status fetchGraphicBlock(
+    virtual c2_status_t fetchGraphicBlock(
             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 aea3a6f..41132b9 100644
--- a/media/libstagefright/codec2/vndk/include/C2ErrnoUtils.h
+++ b/media/libstagefright/codec2/vndk/include/C2ErrnoUtils.h
@@ -23,17 +23,17 @@
 namespace android {
 
 // standard ERRNO mappings
-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_REFUSED; }
-template<> constexpr C2Status _c2_errno2status_impl<EPERM>()   { return C2_REFUSED; }
-template<> constexpr C2Status _c2_errno2status_impl<ENOMEM>()  { return C2_NO_MEMORY; }
+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 C2Status
+// 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 C2Status map(int result) {
+    static c2_status_t map(int result) {
         if (result == E) {
             return _c2_errno2status_impl <E>();
         } else {
@@ -42,13 +42,13 @@
     }
 };
 template<> struct _c2_map_errno_impl<> {
-    static C2Status map(int result) {
+    static c2_status_t map(int result) {
         return result == 0 ? C2_OK : C2_CORRUPTED;
     }
 };
 
 template<int... N>
-C2Status c2_map_errno(int result) {
+c2_status_t c2_map_errno(int result) {
     return _c2_map_errno_impl<N...>::map(result);
 }
 
diff --git a/media/libstagefright/codec2/vndk/include/C2PlatformSupport.h b/media/libstagefright/codec2/vndk/include/C2PlatformSupport.h
index 40bb548..8e45705 100644
--- a/media/libstagefright/codec2/vndk/include/C2PlatformSupport.h
+++ b/media/libstagefright/codec2/vndk/include/C2PlatformSupport.h
@@ -48,10 +48,63 @@
  * \retval C2_CORRUPTED some unknown, unrecoverable error occured during operation (unexpected,
  *                      this return value is only possible for basic pools)
  */
-C2Status GetCodec2BlockPool(
+c2_status_t GetCodec2BlockPool(
         C2BlockPool::local_id_t id, std::shared_ptr<const C2Component> component,
         std::shared_ptr<C2BlockPool> *pool);
 
+/**
+ * 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:
+    /**
+     * Creates a component.
+     *
+     * This method SHALL return within 100ms.
+     *
+     * \param component shared pointer where the created component is stored. Cleared on
+     *                  failure and updated on success.
+     * \param id        component ID for the created component
+     *
+     * \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(
+            std::shared_ptr<C2Component>* const component, c2_node_id_t id) = 0;
+
+    /**
+     * Creates a component interface.
+     *
+     * This method SHALL return within 100ms.
+     *
+     * \param interface shared pointer where the created interface is stored. Cleared on
+     *                  failure and updated on success.
+     * \param id        component interface ID for the created interface
+     *
+     * \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(
+            std::shared_ptr<C2ComponentInterface>* const interface, c2_node_id_t id) = 0;
+
+    virtual ~C2ComponentFactory() = default;
+};
+
 } // namespace android
 
 #endif // STAGEFRIGHT_CODEC2_PLATFORM_SUPPORT_H_
diff --git a/media/libstagefright/codec2/vndk/include/util/C2ParamUtils.h b/media/libstagefright/codec2/vndk/include/util/C2ParamUtils.h
index 5f09889..5ce6071 100644
--- a/media/libstagefright/codec2/vndk/include/util/C2ParamUtils.h
+++ b/media/libstagefright/codec2/vndk/include/util/C2ParamUtils.h
@@ -222,7 +222,7 @@
     friend class C2ParamTest_ParamUtilsTest_Test;
 
 public:
-    static std::vector<C2String> getEnumValuesFromString(C2StringLiteral value) {
+    static std::vector<C2String> parseEnumValuesFromString(C2StringLiteral value) {
         std::vector<C2String> foundNames;
         size_t pos = 0, len = strlen(value);
         do {
diff --git a/media/libstagefright/codecs/avcdec/C2SoftAvcDec.cpp b/media/libstagefright/codecs/avcdec/C2SoftAvcDec.cpp
index 12eaff5..c74ca6d 100644
--- a/media/libstagefright/codecs/avcdec/C2SoftAvcDec.cpp
+++ b/media/libstagefright/codecs/avcdec/C2SoftAvcDec.cpp
@@ -246,7 +246,7 @@
 //     { OMX_VIDEO_AVCProfileMain,     OMX_VIDEO_AVCLevel52 },
 //     { OMX_VIDEO_AVCProfileHigh,     OMX_VIDEO_AVCLevel52 },
 // };
-C2SoftAvcDecIntf::C2SoftAvcDecIntf(const char *name, node_id id)
+C2SoftAvcDecIntf::C2SoftAvcDecIntf(const char *name, c2_node_id_t id)
     : mName(name),
       mId(id),
       mDomainInfo(C2DomainVideo),
@@ -434,11 +434,11 @@
     return mName;
 }
 
-node_id C2SoftAvcDecIntf::getId() const {
+c2_node_id_t C2SoftAvcDecIntf::getId() const {
     return mId;
 }
 
-C2Status C2SoftAvcDecIntf::query_nb(
+c2_status_t C2SoftAvcDecIntf::query_nb(
         const std::vector<C2Param* const> & stackParams,
         const std::vector<C2Param::Index> & heapParamIndices,
         std::vector<std::unique_ptr<C2Param>>* const heapParams) const {
@@ -473,10 +473,10 @@
     return C2_OK;
 }
 
-C2Status C2SoftAvcDecIntf::config_nb(
+c2_status_t C2SoftAvcDecIntf::config_nb(
         const std::vector<C2Param* const> &params,
         std::vector<std::unique_ptr<C2SettingResult>>* const failures) {
-    C2Status err = C2_OK;
+    c2_status_t err = C2_OK;
     for (C2Param *param : params) {
         uint32_t index = restoreIndex(param);
         if (param->index() == mOutputBlockPools.get()->index()) {
@@ -504,20 +504,20 @@
     return err;
 }
 
-C2Status C2SoftAvcDecIntf::commit_sm(
+c2_status_t C2SoftAvcDecIntf::commit_sm(
         const std::vector<C2Param* const> &params,
         std::vector<std::unique_ptr<C2SettingResult>>* const failures) {
     // TODO
     return config_nb(params, failures);
 }
 
-C2Status C2SoftAvcDecIntf::createTunnel_sm(node_id targetComponent) {
+c2_status_t C2SoftAvcDecIntf::createTunnel_sm(c2_node_id_t targetComponent) {
     // Tunneling is not supported
     (void) targetComponent;
     return C2_OMITTED;
 }
 
-C2Status C2SoftAvcDecIntf::releaseTunnel_sm(node_id targetComponent) {
+c2_status_t C2SoftAvcDecIntf::releaseTunnel_sm(c2_node_id_t targetComponent) {
     // Tunneling is not supported
     (void) targetComponent;
     return C2_OMITTED;
@@ -527,15 +527,15 @@
     return mParamReflector;
 }
 
-C2Status C2SoftAvcDecIntf::getSupportedParams(
+c2_status_t C2SoftAvcDecIntf::querySupportedParams_nb(
         std::vector<std::shared_ptr<C2ParamDescriptor>> * const params) const {
     params->insert(params->begin(), mParamDescs.begin(), mParamDescs.end());
     return C2_OK;
 }
 
-C2Status C2SoftAvcDecIntf::getSupportedValues(
+c2_status_t C2SoftAvcDecIntf::querySupportedValues_nb(
         std::vector<C2FieldSupportedValuesQuery> &fields) const {
-    C2Status res = C2_OK;
+    c2_status_t res = C2_OK;
     for (C2FieldSupportedValuesQuery &query : fields) {
         if (mSupportedValues.count(query.field) == 0) {
             query.status = C2_BAD_INDEX;
@@ -642,10 +642,8 @@
 
 C2SoftAvcDec::C2SoftAvcDec(
         const char *name,
-        node_id id,
-        const std::shared_ptr<C2ComponentListener> &listener)
+        c2_node_id_t id)
     : mIntf(std::make_shared<C2SoftAvcDecIntf>(name, id)),
-      mListener(listener),
       mThread(new QueueProcessThread),
       mCodecCtx(NULL),
       mFlushOutBuffer(NULL),
@@ -666,7 +664,22 @@
     CHECK_EQ(deInitDecoder(), (status_t)OK);
 }
 
-C2Status C2SoftAvcDec::queue_nb(
+c2_status_t C2SoftAvcDec::setListener_sm(
+        const std::shared_ptr<C2Component::Listener> &listener) {
+    std::unique_lock<std::mutex> lock(mListenerLock);
+    // TODO: we really need to lock the running check as well
+    if (listener && mThread->isRunning()) {
+        return C2_BAD_STATE;
+    }
+    mListener = listener;
+    if (mActiveListener && !listener) {
+        // wait until no active listeners are in use
+        mActiveListenerChanged.wait(lock, [this]{ return !mActiveListener; });
+    }
+    return C2_OK;
+}
+
+c2_status_t C2SoftAvcDec::queue_nb(
         std::list<std::unique_ptr<C2Work>>* const items) {
     if (!mThread->isRunning()) {
         return C2_CORRUPTED;
@@ -681,16 +694,16 @@
     return C2_OK;
 }
 
-C2Status C2SoftAvcDec::announce_nb(const std::vector<C2WorkOutline> &items) {
+c2_status_t C2SoftAvcDec::announce_nb(const std::vector<C2WorkOutline> &items) {
     // Tunneling is not supported
     (void) items;
     return C2_OMITTED;
 }
 
-C2Status C2SoftAvcDec::flush_sm(
-        bool flushThrough, std::list<std::unique_ptr<C2Work>>* const flushedWork) {
+c2_status_t C2SoftAvcDec::flush_sm(
+        flush_mode_t mode, std::list<std::unique_ptr<C2Work>>* const flushedWork) {
     // Tunneling is not supported
-    (void) flushThrough;
+    (void) mode;
 
     if (!mThread->isRunning()) {
         return C2_CORRUPTED;
@@ -713,9 +726,9 @@
     return C2_OK;
 }
 
-C2Status C2SoftAvcDec::drain_nb(bool drainThrough) {
+c2_status_t C2SoftAvcDec::drain_nb(drain_mode_t mode) {
     // Tunneling is not supported
-    (void) drainThrough;
+    (void) mode;
 
     if (!mThread->isRunning()) {
         return C2_CORRUPTED;
@@ -723,20 +736,20 @@
     std::unique_lock<std::mutex> lock(mQueueLock);
     if (!mQueue.empty()) {
         C2BufferPack &lastInput = mQueue.back()->input;
-        lastInput.flags = (flags_t)(lastInput.flags | BUFFERFLAG_END_OF_STREAM);
+        lastInput.flags = (C2BufferPack::flags_t)(lastInput.flags | C2BufferPack::FLAG_END_OF_STREAM);
         mQueueCond.notify_all();
     }
     return C2_OK;
 }
 
-C2Status C2SoftAvcDec::start() {
+c2_status_t C2SoftAvcDec::start() {
     if (!mThread->isRunning()) {
         mThread->start(shared_from_this());
     }
     return C2_OK;
 }
 
-C2Status C2SoftAvcDec::stop() {
+c2_status_t 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);
@@ -843,7 +856,16 @@
     }
 
     if (!done.empty()) {
-        mListener->onWorkDone(shared_from_this(), std::move(done));
+        std::unique_lock<std::mutex> lock(mListenerLock);
+        mActiveListener = mListener;
+
+        if (mActiveListener) {
+            lock.unlock();
+            mActiveListener->onWorkDone_nb(shared_from_this(), std::move(done));
+            lock.lock();
+            mActiveListener.reset();
+            mActiveListenerChanged.notify_all();
+        }
     }
 }
 
@@ -1206,14 +1228,14 @@
 
         std::vector<std::unique_ptr<C2Work>> done;
         done.emplace_back(std::move(work));
-        mListener->onWorkDone(shared_from_this(), std::move(done));
-        if (!(work->input.flags & BUFFERFLAG_END_OF_STREAM)) {
+        mListener->onWorkDone_nb(shared_from_this(), std::move(done));
+        if (!(work->input.flags & C2BufferPack::FLAG_END_OF_STREAM)) {
             return;
         }
 
         mReceivedEOS = true;
         // TODO: flush
-    } else if (work->input.flags & BUFFERFLAG_END_OF_STREAM) {
+    } else if (work->input.flags & C2BufferPack::FLAG_END_OF_STREAM) {
         mReceivedEOS = true;
     }
 
@@ -1231,7 +1253,7 @@
             mIntf->mOutputBlockPools->flexCount() ?
                     mIntf->mOutputBlockPools->m.mValues[0] : C2BlockPool::BASIC_GRAPHIC;
         if (!mOutputBlockPool || mOutputBlockPool->getLocalId() != poolId) {
-            C2Status err = GetCodec2BlockPool(poolId, shared_from_this(), &mOutputBlockPool);
+            c2_status_t err = GetCodec2BlockPool(poolId, shared_from_this(), &mOutputBlockPool);
             if (err != C2_OK) {
                 // TODO: trip
             }
@@ -1359,7 +1381,7 @@
             done[0]->worklets.front()->output.buffers.emplace_back(
                     std::make_shared<GraphicBuffer>(std::move(mAllocatedBlock)));
             done[0]->worklets.front()->output.ordinal = done[0]->input.ordinal;
-            mListener->onWorkDone(shared_from_this(), std::move(done));
+            mListener->onWorkDone_nb(shared_from_this(), std::move(done));
         } else if (mIsInFlush) {
             ALOGV("flush");
             /* If in flush mode and no output is returned by the codec,
@@ -1440,4 +1462,29 @@
     return C2_OK;
 }
 
+class C2SoftAvcDecFactory : public C2ComponentFactory {
+public:
+    virtual c2_status_t createComponent(
+            std::shared_ptr<C2Component>* const component, c2_node_id_t id) override {
+        *component = std::make_shared<C2SoftAvcDec>("avc", id);
+        return C2_OK;
+    }
+
+    virtual c2_status_t createInterface(
+            std::shared_ptr<C2ComponentInterface>* const interface, c2_node_id_t id) override {
+        *interface = std::make_shared<C2SoftAvcDecIntf>("avc", id);
+        return C2_OK;
+    }
+
+    virtual ~C2SoftAvcDecFactory() override = default;
+};
+
 }  // namespace android
+
+extern "C" ::android::C2ComponentFactory* CreateCodec2Factory() {
+    return new ::android::C2SoftAvcDecFactory();
+}
+
+extern "C" void DestroyCodec2Factory(::android::C2ComponentFactory* factory) {
+    delete factory;
+}
diff --git a/media/libstagefright/codecs/avcdec/C2SoftAvcDec.h b/media/libstagefright/codecs/avcdec/C2SoftAvcDec.h
index 41ccf39..5deaf5d 100644
--- a/media/libstagefright/codecs/avcdec/C2SoftAvcDec.h
+++ b/media/libstagefright/codecs/avcdec/C2SoftAvcDec.h
@@ -79,35 +79,36 @@
         SupportedValuesWithFields(const C2FieldSupportedValues &supported) : supported(supported) {}
     };
 
-    C2SoftAvcDecIntf(const char *name, node_id id);
+    C2SoftAvcDecIntf(const char *name, c2_node_id_t id);
     virtual ~C2SoftAvcDecIntf() = default;
 
     // From C2ComponentInterface
     virtual C2String getName() const override;
-    virtual node_id getId() const override;
-    virtual C2Status query_nb(
+    virtual c2_node_id_t getId() const override;
+    virtual c2_status_t 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 C2Status config_nb(
+    virtual c2_status_t config_nb(
             const std::vector<C2Param* const> &params,
             std::vector<std::unique_ptr<C2SettingResult>>* const failures) override;
-    virtual C2Status commit_sm(
+    virtual c2_status_t commit_sm(
             const std::vector<C2Param* const> &params,
             std::vector<std::unique_ptr<C2SettingResult>>* const failures) 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 C2Status getSupportedParams(
+    virtual c2_status_t createTunnel_sm(c2_node_id_t targetComponent) override;
+    virtual c2_status_t releaseTunnel_sm(c2_node_id_t targetComponent) override;
+    // TODO: move this into some common store class
+    std::shared_ptr<C2ParamReflector> getParamReflector() const;
+    virtual c2_status_t querySupportedParams_nb(
             std::vector<std::shared_ptr<C2ParamDescriptor>> * const params) const override;
-    virtual C2Status getSupportedValues(
+    virtual c2_status_t querySupportedValues_nb(
             std::vector<C2FieldSupportedValuesQuery> &fields) const override;
 
 private:
     class ParamReflector;
 
     const C2String mName;
-    const node_id mId;
+    const c2_node_id_t mId;
 
     C2ComponentDomainInfo mDomainInfo;
     // TODO: config desc
@@ -146,18 +147,18 @@
     : public C2Component,
       public std::enable_shared_from_this<C2SoftAvcDec> {
 public:
-    C2SoftAvcDec(
-            const char *name, node_id id, const std::shared_ptr<C2ComponentListener> &listener);
+    C2SoftAvcDec(const char *name, c2_node_id_t id);
     virtual ~C2SoftAvcDec();
 
     // From C2Component
-    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 C2Status drain_nb(bool drainThrough) override;
-    virtual C2Status start() override;
-    virtual C2Status stop() override;
+    virtual c2_status_t setListener_sm(const std::shared_ptr<Listener> &listener) override;
+    virtual c2_status_t queue_nb(std::list<std::unique_ptr<C2Work>>* const items) override;
+    virtual c2_status_t announce_nb(const std::vector<C2WorkOutline> &items) override;
+    virtual c2_status_t flush_sm(
+            flush_mode_t mode, std::list<std::unique_ptr<C2Work>>* const flushedWork) override;
+    virtual c2_status_t drain_nb(drain_mode_t mode) override;
+    virtual c2_status_t start() override;
+    virtual c2_status_t stop() override;
     virtual void reset() override;
     virtual void release() override;
     virtual std::shared_ptr<C2ComponentInterface> intf() override;
@@ -192,7 +193,11 @@
     using IndexType = decltype(C2WorkOrdinalStruct().frame_index);
 
     const std::shared_ptr<C2SoftAvcDecIntf> mIntf;
-    const std::shared_ptr<C2ComponentListener> mListener;
+    std::shared_ptr<Listener> mListener;
+    std::shared_ptr<Listener> mActiveListener;
+    std::mutex mListenerLock;
+    std::condition_variable mActiveListenerChanged;
+
     std::shared_ptr<C2BlockPool> mOutputBlockPool;
 
     std::mutex mQueueLock;
diff --git a/media/libstagefright/codecs/cmds/codec2.cpp b/media/libstagefright/codecs/cmds/codec2.cpp
index c7e1c82..8e2c4b9 100644
--- a/media/libstagefright/codecs/cmds/codec2.cpp
+++ b/media/libstagefright/codecs/cmds/codec2.cpp
@@ -58,6 +58,9 @@
 #include <C2PlatformSupport.h>
 #include <C2Work.h>
 
+extern "C" ::android::C2ComponentFactory *CreateCodec2Factory();
+extern "C" void DestroyCodec2Factory(::android::C2ComponentFactory *);
+
 #include "../avcdec/C2SoftAvcDec.h"
 
 using namespace android;
@@ -110,22 +113,22 @@
     sp<SurfaceControl> mControl;
 };
 
-class Listener : public C2ComponentListener {
+class Listener : public C2Component::Listener {
 public:
     explicit Listener(SimplePlayer *thiz) : mThis(thiz) {}
     virtual ~Listener() = default;
 
-    virtual void onWorkDone(std::weak_ptr<C2Component> component,
+    virtual void onWorkDone_nb(std::weak_ptr<C2Component> component,
                             std::vector<std::unique_ptr<C2Work>> workItems) override {
         mThis->onWorkDone(component, std::move(workItems));
     }
 
-    virtual void onTripped(std::weak_ptr<C2Component> component,
+    virtual void onTripped_nb(std::weak_ptr<C2Component> component,
                            std::vector<std::shared_ptr<C2SettingResult>> settingResult) override {
         mThis->onTripped(component, settingResult);
     }
 
-    virtual void onError(std::weak_ptr<C2Component> component,
+    virtual void onError_nb(std::weak_ptr<C2Component> component,
                          uint32_t errorCode) override {
         mThis->onError(component, errorCode);
     }
@@ -142,7 +145,7 @@
     CHECK_EQ(mComposerClient->initCheck(), (status_t)OK);
 
     std::shared_ptr<C2AllocatorStore> store = GetCodec2PlatformAllocatorStore();
-    CHECK_EQ(store->getAllocator(C2AllocatorStore::DEFAULT_LINEAR, &mAllocIon), C2_OK);
+    CHECK_EQ(store->fetchAllocator(C2AllocatorStore::DEFAULT_LINEAR, &mAllocIon), C2_OK);
     mLinearPool = std::make_shared<C2BasicLinearBlockPool>(mAllocIon);
 
     mControl = mComposerClient->createSurface(
@@ -208,7 +211,12 @@
         return;
     }
 
-    std::shared_ptr<C2Component> component(std::make_shared<C2SoftAvcDec>("avc", 0, mListener));
+    std::unique_ptr<C2ComponentFactory> factory(CreateCodec2Factory());
+    std::shared_ptr<C2Component> component;
+    (void)factory->createComponent(&component, 0);
+    DestroyCodec2Factory(factory.release());
+
+    (void)component->setListener_sm(mListener);
     std::unique_ptr<C2PortBlockPoolsTuning::output> pools =
         C2PortBlockPoolsTuning::output::alloc_unique({ (uint64_t)C2BlockPool::BASIC_GRAPHIC });
     std::vector<std::unique_ptr<C2SettingResult>> result;
@@ -322,7 +330,7 @@
                 mQueueCondition.wait_for(l, 100ms);
             }
         }
-        work->input.flags = (flags_t)0;
+        work->input.flags = (C2BufferPack::flags_t)0;
         work->input.ordinal.timestamp = timestamp;
         work->input.ordinal.frame_index = numFrames;
 
diff --git a/media/libstagefright/include/media/stagefright/AudioSource.h b/media/libstagefright/include/media/stagefright/AudioSource.h
index 4984f69..9414aab 100644
--- a/media/libstagefright/include/media/stagefright/AudioSource.h
+++ b/media/libstagefright/include/media/stagefright/AudioSource.h
@@ -40,7 +40,8 @@
             uint32_t channels,
             uint32_t outSampleRate = 0,
             uid_t uid = -1,
-            pid_t pid = -1);
+            pid_t pid = -1,
+            audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE);
 
     status_t initCheck() const;
 
@@ -58,6 +59,11 @@
     status_t dataCallback(const AudioRecord::Buffer& buffer);
     virtual void signalBufferReturned(MediaBuffer *buffer);
 
+    status_t setInputDevice(audio_port_handle_t deviceId);
+    status_t getRoutedDeviceId(audio_port_handle_t* deviceId);
+    status_t addAudioDeviceCallback(const sp<AudioSystem::AudioDeviceCallback>& callback);
+    status_t removeAudioDeviceCallback(const sp<AudioSystem::AudioDeviceCallback>& callback);
+
 protected:
     virtual ~AudioSource();
 
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index 80a8dc6..62cbfc1 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -5595,6 +5595,11 @@
             case AUDIO_FORMAT_E_AC3:
             case AUDIO_FORMAT_DTS:
             case AUDIO_FORMAT_DTS_HD:
+                // If ALWAYS, remove all other surround formats here since we will add them later.
+                if (forceUse == AUDIO_POLICY_FORCE_ENCODED_SURROUND_ALWAYS) {
+                    formats.removeAt(formatIndex);
+                    formatIndex--;
+                }
                 supportsOtherSurround = true;
                 break;
             case AUDIO_FORMAT_IEC61937:
@@ -5640,8 +5645,7 @@
         // If ALWAYS, add support for raw surround formats if all are missing.
         // This assumes that if any of these formats are reported by the HAL
         // then the report is valid and should not be modified.
-        if ((forceUse == AUDIO_POLICY_FORCE_ENCODED_SURROUND_ALWAYS)
-                && !supportsOtherSurround) {
+        if (forceUse == AUDIO_POLICY_FORCE_ENCODED_SURROUND_ALWAYS) {
             formats.add(AUDIO_FORMAT_E_AC3);
             formats.add(AUDIO_FORMAT_DTS);
             formats.add(AUDIO_FORMAT_DTS_HD);