Merge "DO NOT MERGE: IOMX: work against metadata buffer spoofing" into klp-dev am: 425cc025a1 am: 9c7f0824be am: 56100a30ba  -s ours am: 563b100957  -s ours am: 4636e7256a am: 44071d00a7 am: f95caa3506  -s ours am: 483c0d4053 am: 43d4b759f5 am: 8c02795ab6
am: db39c9e711  -s ours

Change-Id: I6c93f11a67f94312b36418c33130bc88ce98a677
diff --git a/camera/Android.mk b/camera/Android.mk
index 471cb0d..1a3382f 100644
--- a/camera/Android.mk
+++ b/camera/Android.mk
@@ -18,7 +18,24 @@
 
 LOCAL_PATH := $(CAMERA_CLIENT_LOCAL_PATH)
 
-LOCAL_SRC_FILES:= \
+LOCAL_AIDL_INCLUDES := \
+    frameworks/av/camera/aidl \
+    frameworks/base/core/java \
+    frameworks/native/aidl/gui
+
+# AIDL files for camera interfaces
+# The headers for these interfaces will be available to any modules that
+# include libcamera_client, at the path "aidl/package/path/BnFoo.h"
+
+LOCAL_SRC_FILES := \
+    aidl/android/hardware/ICameraService.aidl \
+    aidl/android/hardware/ICameraServiceListener.aidl \
+    aidl/android/hardware/camera2/ICameraDeviceCallbacks.aidl \
+    aidl/android/hardware/camera2/ICameraDeviceUser.aidl
+
+# Source for camera interface parcelables, and manually-written interfaces
+
+LOCAL_SRC_FILES += \
 	Camera.cpp \
 	CameraMetadata.cpp \
 	CameraParameters.cpp \
@@ -26,15 +43,12 @@
 	CameraParameters2.cpp \
 	ICamera.cpp \
 	ICameraClient.cpp \
-	ICameraService.cpp \
-	ICameraServiceListener.cpp \
 	ICameraServiceProxy.cpp \
 	ICameraRecordingProxy.cpp \
 	ICameraRecordingProxyListener.cpp \
-	camera2/ICameraDeviceUser.cpp \
-	camera2/ICameraDeviceCallbacks.cpp \
 	camera2/CaptureRequest.cpp \
 	camera2/OutputConfiguration.cpp \
+	camera2/SubmitInfo.cpp \
 	CameraBase.cpp \
 	CameraUtils.cpp \
 	VendorTagDescriptor.cpp
@@ -52,6 +66,14 @@
 LOCAL_C_INCLUDES += \
 	system/media/camera/include \
 	system/media/private/camera/include \
+	frameworks/native/include/media/openmax \
+	frameworks/av/include/camera
+
+LOCAL_EXPORT_C_INCLUDE_DIRS := \
+	system/media/camera/include \
+	frameworks/av/include/camera
+
+LOCAL_CFLAGS += -Werror -Wall -Wextra
 
 LOCAL_MODULE:= libcamera_client
 
diff --git a/camera/Camera.cpp b/camera/Camera.cpp
index 9bf3134..bf9904c 100644
--- a/camera/Camera.cpp
+++ b/camera/Camera.cpp
@@ -24,10 +24,10 @@
 #include <binder/IServiceManager.h>
 #include <binder/IMemory.h>
 
-#include <camera/Camera.h>
-#include <camera/ICameraRecordingProxyListener.h>
-#include <camera/ICameraService.h>
-#include <camera/ICamera.h>
+#include <Camera.h>
+#include <ICameraRecordingProxyListener.h>
+#include <android/hardware/ICameraService.h>
+#include <android/hardware/ICamera.h>
 
 #include <gui/IGraphicBufferProducer.h>
 #include <gui/Surface.h>
@@ -40,10 +40,10 @@
 }
 
 CameraTraits<Camera>::TCamConnectService CameraTraits<Camera>::fnConnectService =
-        &ICameraService::connect;
+        &::android::hardware::ICameraService::connect;
 
 // construct a camera client from an existing camera remote
-sp<Camera> Camera::create(const sp<ICamera>& camera)
+sp<Camera> Camera::create(const sp<::android::hardware::ICamera>& camera)
 {
      ALOGV("create");
      if (camera == 0) {
@@ -72,9 +72,9 @@
 }
 
 sp<Camera> Camera::connect(int cameraId, const String16& clientPackageName,
-        int clientUid)
+        int clientUid, int clientPid)
 {
-    return CameraBaseT::connect(cameraId, clientPackageName, clientUid);
+    return CameraBaseT::connect(cameraId, clientPackageName, clientUid, clientPid);
 }
 
 status_t Camera::connectLegacy(int cameraId, int halVersion,
@@ -84,21 +84,51 @@
 {
     ALOGV("%s: connect legacy camera device", __FUNCTION__);
     sp<Camera> c = new Camera(cameraId);
-    sp<ICameraClient> cl = c;
+    sp<::android::hardware::ICameraClient> cl = c;
     status_t status = NO_ERROR;
-    const sp<ICameraService>& cs = CameraBaseT::getCameraService();
+    const sp<::android::hardware::ICameraService>& cs = CameraBaseT::getCameraService();
 
-    if (cs != 0) {
-        status = cs.get()->connectLegacy(cl, cameraId, halVersion, clientPackageName,
-                                        clientUid, /*out*/c->mCamera);
+    binder::Status ret;
+    if (cs != nullptr) {
+        ret = cs.get()->connectLegacy(cl, cameraId, halVersion, clientPackageName,
+                clientUid, /*out*/&(c->mCamera));
     }
-    if (status == OK && c->mCamera != 0) {
+    if (ret.isOk() && c->mCamera != nullptr) {
         IInterface::asBinder(c->mCamera)->linkToDeath(c);
         c->mStatus = NO_ERROR;
         camera = c;
     } else {
-        ALOGW("An error occurred while connecting to camera %d: %d (%s)",
-                cameraId, status, strerror(-status));
+        switch(ret.serviceSpecificErrorCode()) {
+            case hardware::ICameraService::ERROR_DISCONNECTED:
+                status = -ENODEV;
+                break;
+            case hardware::ICameraService::ERROR_CAMERA_IN_USE:
+                status = -EBUSY;
+                break;
+            case hardware::ICameraService::ERROR_INVALID_OPERATION:
+                status = -EINVAL;
+                break;
+            case hardware::ICameraService::ERROR_MAX_CAMERAS_IN_USE:
+                status = -EUSERS;
+                break;
+            case hardware::ICameraService::ERROR_ILLEGAL_ARGUMENT:
+                status = BAD_VALUE;
+                break;
+            case hardware::ICameraService::ERROR_DEPRECATED_HAL:
+                status = -EOPNOTSUPP;
+                break;
+            case hardware::ICameraService::ERROR_DISABLED:
+                status = -EACCES;
+                break;
+            case hardware::ICameraService::ERROR_PERMISSION_DENIED:
+                status = PERMISSION_DENIED;
+                break;
+            default:
+                status = -EINVAL;
+                ALOGW("An error occurred while connecting to camera %d: %s", cameraId,
+                        (cs != nullptr) ? "Service not available" : ret.toString8().string());
+                break;
+        }
         c.clear();
     }
     return status;
@@ -107,21 +137,21 @@
 status_t Camera::reconnect()
 {
     ALOGV("reconnect");
-    sp <ICamera> c = mCamera;
+    sp <::android::hardware::ICamera> c = mCamera;
     if (c == 0) return NO_INIT;
     return c->connect(this);
 }
 
 status_t Camera::lock()
 {
-    sp <ICamera> c = mCamera;
+    sp <::android::hardware::ICamera> c = mCamera;
     if (c == 0) return NO_INIT;
     return c->lock();
 }
 
 status_t Camera::unlock()
 {
-    sp <ICamera> c = mCamera;
+    sp <::android::hardware::ICamera> c = mCamera;
     if (c == 0) return NO_INIT;
     return c->unlock();
 }
@@ -130,35 +160,43 @@
 status_t Camera::setPreviewTarget(const sp<IGraphicBufferProducer>& bufferProducer)
 {
     ALOGV("setPreviewTarget(%p)", bufferProducer.get());
-    sp <ICamera> c = mCamera;
+    sp <::android::hardware::ICamera> c = mCamera;
     if (c == 0) return NO_INIT;
     ALOGD_IF(bufferProducer == 0, "app passed NULL surface");
     return c->setPreviewTarget(bufferProducer);
 }
 
+status_t Camera::setVideoTarget(const sp<IGraphicBufferProducer>& bufferProducer)
+{
+    ALOGV("setVideoTarget(%p)", bufferProducer.get());
+    sp <::android::hardware::ICamera> c = mCamera;
+    if (c == 0) return NO_INIT;
+    ALOGD_IF(bufferProducer == 0, "app passed NULL video surface");
+    return c->setVideoTarget(bufferProducer);
+}
+
 // start preview mode
 status_t Camera::startPreview()
 {
     ALOGV("startPreview");
-    sp <ICamera> c = mCamera;
+    sp <::android::hardware::ICamera> c = mCamera;
     if (c == 0) return NO_INIT;
     return c->startPreview();
 }
 
-status_t Camera::storeMetaDataInBuffers(bool enabled)
+status_t Camera::setVideoBufferMode(int32_t videoBufferMode)
 {
-    ALOGV("storeMetaDataInBuffers: %s",
-            enabled? "true": "false");
-    sp <ICamera> c = mCamera;
+    ALOGV("setVideoBufferMode: %d", videoBufferMode);
+    sp <::android::hardware::ICamera> c = mCamera;
     if (c == 0) return NO_INIT;
-    return c->storeMetaDataInBuffers(enabled);
+    return c->setVideoBufferMode(videoBufferMode);
 }
 
 // start recording mode, must call setPreviewTarget first
 status_t Camera::startRecording()
 {
     ALOGV("startRecording");
-    sp <ICamera> c = mCamera;
+    sp <::android::hardware::ICamera> c = mCamera;
     if (c == 0) return NO_INIT;
     return c->startRecording();
 }
@@ -167,7 +205,7 @@
 void Camera::stopPreview()
 {
     ALOGV("stopPreview");
-    sp <ICamera> c = mCamera;
+    sp <::android::hardware::ICamera> c = mCamera;
     if (c == 0) return;
     c->stopPreview();
 }
@@ -180,7 +218,7 @@
         Mutex::Autolock _l(mLock);
         mRecordingProxyListener.clear();
     }
-    sp <ICamera> c = mCamera;
+    sp <::android::hardware::ICamera> c = mCamera;
     if (c == 0) return;
     c->stopRecording();
 }
@@ -189,16 +227,24 @@
 void Camera::releaseRecordingFrame(const sp<IMemory>& mem)
 {
     ALOGV("releaseRecordingFrame");
-    sp <ICamera> c = mCamera;
+    sp <::android::hardware::ICamera> c = mCamera;
     if (c == 0) return;
     c->releaseRecordingFrame(mem);
 }
 
+void Camera::releaseRecordingFrameHandle(native_handle_t* handle)
+{
+    ALOGV("releaseRecordingFrameHandle");
+    sp <::android::hardware::ICamera> c = mCamera;
+    if (c == 0) return;
+    c->releaseRecordingFrameHandle(handle);
+}
+
 // get preview state
 bool Camera::previewEnabled()
 {
     ALOGV("previewEnabled");
-    sp <ICamera> c = mCamera;
+    sp <::android::hardware::ICamera> c = mCamera;
     if (c == 0) return false;
     return c->previewEnabled();
 }
@@ -207,7 +253,7 @@
 bool Camera::recordingEnabled()
 {
     ALOGV("recordingEnabled");
-    sp <ICamera> c = mCamera;
+    sp <::android::hardware::ICamera> c = mCamera;
     if (c == 0) return false;
     return c->recordingEnabled();
 }
@@ -215,7 +261,7 @@
 status_t Camera::autoFocus()
 {
     ALOGV("autoFocus");
-    sp <ICamera> c = mCamera;
+    sp <::android::hardware::ICamera> c = mCamera;
     if (c == 0) return NO_INIT;
     return c->autoFocus();
 }
@@ -223,7 +269,7 @@
 status_t Camera::cancelAutoFocus()
 {
     ALOGV("cancelAutoFocus");
-    sp <ICamera> c = mCamera;
+    sp <::android::hardware::ICamera> c = mCamera;
     if (c == 0) return NO_INIT;
     return c->cancelAutoFocus();
 }
@@ -232,7 +278,7 @@
 status_t Camera::takePicture(int msgType)
 {
     ALOGV("takePicture: 0x%x", msgType);
-    sp <ICamera> c = mCamera;
+    sp <::android::hardware::ICamera> c = mCamera;
     if (c == 0) return NO_INIT;
     return c->takePicture(msgType);
 }
@@ -241,7 +287,7 @@
 status_t Camera::setParameters(const String8& params)
 {
     ALOGV("setParameters");
-    sp <ICamera> c = mCamera;
+    sp <::android::hardware::ICamera> c = mCamera;
     if (c == 0) return NO_INIT;
     return c->setParameters(params);
 }
@@ -251,7 +297,7 @@
 {
     ALOGV("getParameters");
     String8 params;
-    sp <ICamera> c = mCamera;
+    sp <::android::hardware::ICamera> c = mCamera;
     if (c != 0) params = mCamera->getParameters();
     return params;
 }
@@ -260,7 +306,7 @@
 status_t Camera::sendCommand(int32_t cmd, int32_t arg1, int32_t arg2)
 {
     ALOGV("sendCommand");
-    sp <ICamera> c = mCamera;
+    sp <::android::hardware::ICamera> c = mCamera;
     if (c == 0) return NO_INIT;
     return c->sendCommand(cmd, arg1, arg2);
 }
@@ -280,7 +326,7 @@
 void Camera::setPreviewCallbackFlags(int flag)
 {
     ALOGV("setPreviewCallbackFlags");
-    sp <ICamera> c = mCamera;
+    sp <::android::hardware::ICamera> c = mCamera;
     if (c == 0) return;
     mCamera->setPreviewCallbackFlag(flag);
 }
@@ -288,7 +334,7 @@
 status_t Camera::setPreviewCallbackTarget(
         const sp<IGraphicBufferProducer>& callbackProducer)
 {
-    sp <ICamera> c = mCamera;
+    sp <::android::hardware::ICamera> c = mCamera;
     if (c == 0) return NO_INIT;
     return c->setPreviewCallbackTarget(callbackProducer);
 }
@@ -343,6 +389,35 @@
     }
 }
 
+void Camera::recordingFrameHandleCallbackTimestamp(nsecs_t timestamp, native_handle_t* handle)
+{
+    // If recording proxy listener is registered, forward the frame and return.
+    // The other listener (mListener) is ignored because the receiver needs to
+    // call releaseRecordingFrameHandle.
+    sp<ICameraRecordingProxyListener> proxylistener;
+    {
+        Mutex::Autolock _l(mLock);
+        proxylistener = mRecordingProxyListener;
+    }
+    if (proxylistener != NULL) {
+        proxylistener->recordingFrameHandleCallbackTimestamp(timestamp, handle);
+        return;
+    }
+
+    sp<CameraListener> listener;
+    {
+        Mutex::Autolock _l(mLock);
+        listener = mListener;
+    }
+
+    if (listener != NULL) {
+        listener->postRecordingFrameHandleTimestamp(timestamp, handle);
+    } else {
+        ALOGW("No listener was set. Drop a recording frame.");
+        releaseRecordingFrameHandle(handle);
+    }
+}
+
 sp<ICameraRecordingProxy> Camera::getRecordingProxy() {
     ALOGV("getProxy");
     return new RecordingProxy(this);
@@ -368,6 +443,11 @@
     mCamera->releaseRecordingFrame(mem);
 }
 
+void Camera::RecordingProxy::releaseRecordingFrameHandle(native_handle_t* handle) {
+    ALOGV("RecordingProxy::releaseRecordingFrameHandle");
+    mCamera->releaseRecordingFrameHandle(handle);
+}
+
 Camera::RecordingProxy::RecordingProxy(const sp<Camera>& camera)
 {
     mCamera = camera;
diff --git a/camera/CameraBase.cpp b/camera/CameraBase.cpp
index 5d50aa8..15d7715 100644
--- a/camera/CameraBase.cpp
+++ b/camera/CameraBase.cpp
@@ -21,12 +21,13 @@
 #include <utils/threads.h>
 #include <utils/Mutex.h>
 
+#include <android/hardware/ICameraService.h>
+
 #include <binder/IPCThreadState.h>
 #include <binder/IServiceManager.h>
 #include <binder/IMemory.h>
 
 #include <camera/CameraBase.h>
-#include <camera/ICameraService.h>
 
 // needed to instantiate
 #include <camera/Camera.h>
@@ -35,8 +36,28 @@
 
 namespace android {
 
+namespace hardware {
+
+status_t CameraInfo::writeToParcel(Parcel* parcel) const {
+    status_t res;
+    res = parcel->writeInt32(facing);
+    if (res != OK) return res;
+    res = parcel->writeInt32(orientation);
+    return res;
+}
+
+status_t CameraInfo::readFromParcel(const Parcel* parcel) {
+    status_t res;
+    res = parcel->readInt32(&facing);
+    if (res != OK) return res;
+    res = parcel->readInt32(&orientation);
+    return res;
+}
+
+}
+
 namespace {
-    sp<ICameraService>        gCameraService;
+    sp<::android::hardware::ICameraService> gCameraService;
     const int                 kCameraServicePollDelay = 500000; // 0.5s
     const char*               kCameraServiceName      = "media.camera";
 
@@ -65,7 +86,7 @@
 
 // establish binder interface to camera service
 template <typename TCam, typename TCamTraits>
-const sp<ICameraService>& CameraBase<TCam, TCamTraits>::getCameraService()
+const sp<::android::hardware::ICameraService>& CameraBase<TCam, TCamTraits>::getCameraService()
 {
     Mutex::Autolock _l(gLock);
     if (gCameraService.get() == 0) {
@@ -83,7 +104,7 @@
             gDeathNotifier = new DeathNotifier();
         }
         binder->linkToDeath(gDeathNotifier);
-        gCameraService = interface_cast<ICameraService>(binder);
+        gCameraService = interface_cast<::android::hardware::ICameraService>(binder);
     }
     ALOGE_IF(gCameraService == 0, "no CameraService!?");
     return gCameraService;
@@ -92,24 +113,25 @@
 template <typename TCam, typename TCamTraits>
 sp<TCam> CameraBase<TCam, TCamTraits>::connect(int cameraId,
                                                const String16& clientPackageName,
-                                               int clientUid)
+                                               int clientUid, int clientPid)
 {
     ALOGV("%s: connect", __FUNCTION__);
     sp<TCam> c = new TCam(cameraId);
     sp<TCamCallbacks> cl = c;
-    status_t status = NO_ERROR;
-    const sp<ICameraService>& cs = getCameraService();
+    const sp<::android::hardware::ICameraService>& cs = getCameraService();
 
-    if (cs != 0) {
+    binder::Status ret;
+    if (cs != nullptr) {
         TCamConnectService fnConnectService = TCamTraits::fnConnectService;
-        status = (cs.get()->*fnConnectService)(cl, cameraId, clientPackageName, clientUid,
-                                             /*out*/ c->mCamera);
+        ret = (cs.get()->*fnConnectService)(cl, cameraId, clientPackageName, clientUid,
+                                               clientPid, /*out*/ &c->mCamera);
     }
-    if (status == OK && c->mCamera != 0) {
+    if (ret.isOk() && c->mCamera != nullptr) {
         IInterface::asBinder(c->mCamera)->linkToDeath(c);
         c->mStatus = NO_ERROR;
     } else {
-        ALOGW("An error occurred while connecting to camera: %d", cameraId);
+        ALOGW("An error occurred while connecting to camera %d: %s", cameraId,
+                (cs != nullptr) ? "Service not available" : ret.toString8().string());
         c.clear();
     }
     return c;
@@ -182,38 +204,50 @@
 
 template <typename TCam, typename TCamTraits>
 int CameraBase<TCam, TCamTraits>::getNumberOfCameras() {
-    const sp<ICameraService> cs = getCameraService();
+    const sp<::android::hardware::ICameraService> cs = getCameraService();
 
     if (!cs.get()) {
         // as required by the public Java APIs
         return 0;
     }
-    return cs->getNumberOfCameras();
+    int32_t count;
+    binder::Status res = cs->getNumberOfCameras(
+            ::android::hardware::ICameraService::CAMERA_TYPE_BACKWARD_COMPATIBLE,
+            &count);
+    if (!res.isOk()) {
+        ALOGE("Error reading number of cameras: %s",
+                res.toString8().string());
+        count = 0;
+    }
+    return count;
 }
 
 // this can be in BaseCamera but it should be an instance method
 template <typename TCam, typename TCamTraits>
 status_t CameraBase<TCam, TCamTraits>::getCameraInfo(int cameraId,
-                               struct CameraInfo* cameraInfo) {
-    const sp<ICameraService>& cs = getCameraService();
+        struct hardware::CameraInfo* cameraInfo) {
+    const sp<::android::hardware::ICameraService>& cs = getCameraService();
     if (cs == 0) return UNKNOWN_ERROR;
-    return cs->getCameraInfo(cameraId, cameraInfo);
+    binder::Status res = cs->getCameraInfo(cameraId, cameraInfo);
+    return res.isOk() ? OK : res.serviceSpecificErrorCode();
 }
 
 template <typename TCam, typename TCamTraits>
 status_t CameraBase<TCam, TCamTraits>::addServiceListener(
-                            const sp<ICameraServiceListener>& listener) {
-    const sp<ICameraService>& cs = getCameraService();
+        const sp<::android::hardware::ICameraServiceListener>& listener) {
+    const sp<::android::hardware::ICameraService>& cs = getCameraService();
     if (cs == 0) return UNKNOWN_ERROR;
-    return cs->addListener(listener);
+    binder::Status res = cs->addListener(listener);
+    return res.isOk() ? OK : res.serviceSpecificErrorCode();
 }
 
 template <typename TCam, typename TCamTraits>
 status_t CameraBase<TCam, TCamTraits>::removeServiceListener(
-                            const sp<ICameraServiceListener>& listener) {
-    const sp<ICameraService>& cs = getCameraService();
+        const sp<::android::hardware::ICameraServiceListener>& listener) {
+    const sp<::android::hardware::ICameraService>& cs = getCameraService();
     if (cs == 0) return UNKNOWN_ERROR;
-    return cs->removeListener(listener);
+    binder::Status res = cs->removeListener(listener);
+    return res.isOk() ? OK : res.serviceSpecificErrorCode();
 }
 
 template class CameraBase<Camera>;
diff --git a/camera/CameraMetadata.cpp b/camera/CameraMetadata.cpp
index 46bcc1d..c78fc5d 100644
--- a/camera/CameraMetadata.cpp
+++ b/camera/CameraMetadata.cpp
@@ -79,7 +79,7 @@
     return mBuffer;
 }
 
-status_t CameraMetadata::unlock(const camera_metadata_t *buffer) {
+status_t CameraMetadata::unlock(const camera_metadata_t *buffer) const {
     if (!mLocked) {
         ALOGE("%s: Can't unlock a non-locked CameraMetadata!", __FUNCTION__);
         return INVALID_OPERATION;
@@ -621,7 +621,7 @@
     return res;
 }
 
-status_t CameraMetadata::readFromParcel(Parcel *parcel) {
+status_t CameraMetadata::readFromParcel(const Parcel *parcel) {
 
     ALOGV("%s: parcel = %p", __FUNCTION__, parcel);
 
diff --git a/camera/CameraParameters2.cpp b/camera/CameraParameters2.cpp
index 378afeb..c29233c 100644
--- a/camera/CameraParameters2.cpp
+++ b/camera/CameraParameters2.cpp
@@ -351,7 +351,7 @@
 
 void CameraParameters2::dump() const
 {
-    ALOGD("dump: mMap.size = %d", mMap.size());
+    ALOGD("dump: mMap.size = %zu", mMap.size());
     for (size_t i = 0; i < mMap.size(); i++) {
         String8 k, v;
         k = mMap.keyAt(i);
diff --git a/camera/CameraUtils.cpp b/camera/CameraUtils.cpp
index 04244ac..1676be1 100644
--- a/camera/CameraUtils.cpp
+++ b/camera/CameraUtils.cpp
@@ -18,6 +18,7 @@
 //#define LOG_NDEBUG 0
 
 #include <camera/CameraUtils.h>
+#include <media/hardware/HardwareAPI.h>
 
 #include <system/window.h>
 #include <system/graphics.h>
@@ -121,5 +122,4 @@
     return OK;
 }
 
-
 } /* namespace android */
diff --git a/camera/CaptureResult.cpp b/camera/CaptureResult.cpp
index 4e36160..0a447e7 100644
--- a/camera/CaptureResult.cpp
+++ b/camera/CaptureResult.cpp
@@ -26,7 +26,7 @@
     return requestId >= 0;
 }
 
-status_t CaptureResultExtras::readFromParcel(Parcel *parcel) {
+status_t CaptureResultExtras::readFromParcel(const Parcel *parcel) {
     if (parcel == NULL) {
         ALOGE("%s: Null parcel", __FUNCTION__);
         return BAD_VALUE;
@@ -38,6 +38,7 @@
     parcel->readInt32(&precaptureTriggerId);
     parcel->readInt64(&frameNumber);
     parcel->readInt32(&partialResultCount);
+    parcel->readInt32(&errorStreamId);
 
     return OK;
 }
@@ -54,6 +55,7 @@
     parcel->writeInt32(precaptureTriggerId);
     parcel->writeInt64(frameNumber);
     parcel->writeInt32(partialResultCount);
+    parcel->writeInt32(errorStreamId);
 
     return OK;
 }
diff --git a/camera/ICamera.cpp b/camera/ICamera.cpp
index 9943be6..0680d7c 100644
--- a/camera/ICamera.cpp
+++ b/camera/ICamera.cpp
@@ -21,11 +21,15 @@
 #include <stdint.h>
 #include <sys/types.h>
 #include <binder/Parcel.h>
-#include <camera/ICamera.h>
+#include <camera/CameraUtils.h>
+#include <android/hardware/ICamera.h>
+#include <android/hardware/ICameraClient.h>
 #include <gui/IGraphicBufferProducer.h>
 #include <gui/Surface.h>
+#include <media/hardware/HardwareAPI.h>
 
 namespace android {
+namespace hardware {
 
 enum {
     DISCONNECT = IBinder::FIRST_CALL_TRANSACTION,
@@ -48,7 +52,9 @@
     STOP_RECORDING,
     RECORDING_ENABLED,
     RELEASE_RECORDING_FRAME,
-    STORE_META_DATA_IN_BUFFERS,
+    SET_VIDEO_BUFFER_MODE,
+    SET_VIDEO_BUFFER_TARGET,
+    RELEASE_RECORDING_FRAME_HANDLE,
 };
 
 class BpCamera: public BpInterface<ICamera>
@@ -60,13 +66,14 @@
     }
 
     // disconnect from camera service
-    void disconnect()
+    binder::Status disconnect()
     {
         ALOGV("disconnect");
         Parcel data, reply;
         data.writeInterfaceToken(ICamera::getInterfaceDescriptor());
         remote()->transact(DISCONNECT, data, &reply);
         reply.readExceptionCode();
+        return binder::Status::ok();
     }
 
     // pass the buffered IGraphicBufferProducer to the camera service
@@ -148,16 +155,30 @@
         Parcel data, reply;
         data.writeInterfaceToken(ICamera::getInterfaceDescriptor());
         data.writeStrongBinder(IInterface::asBinder(mem));
+
         remote()->transact(RELEASE_RECORDING_FRAME, data, &reply);
     }
 
-    status_t storeMetaDataInBuffers(bool enabled)
-    {
-        ALOGV("storeMetaDataInBuffers: %s", enabled? "true": "false");
+    void releaseRecordingFrameHandle(native_handle_t *handle) {
+        ALOGV("releaseRecordingFrameHandle");
         Parcel data, reply;
         data.writeInterfaceToken(ICamera::getInterfaceDescriptor());
-        data.writeInt32(enabled);
-        remote()->transact(STORE_META_DATA_IN_BUFFERS, data, &reply);
+        data.writeNativeHandle(handle);
+
+        remote()->transact(RELEASE_RECORDING_FRAME_HANDLE, data, &reply);
+
+        // Close the native handle because camera received a dup copy.
+        native_handle_close(handle);
+        native_handle_delete(handle);
+    }
+
+    status_t setVideoBufferMode(int32_t videoBufferMode)
+    {
+        ALOGV("setVideoBufferMode: %d", videoBufferMode);
+        Parcel data, reply;
+        data.writeInterfaceToken(ICamera::getInterfaceDescriptor());
+        data.writeInt32(videoBufferMode);
+        remote()->transact(SET_VIDEO_BUFFER_MODE, data, &reply);
         return reply.readInt32();
     }
 
@@ -268,6 +289,17 @@
         remote()->transact(UNLOCK, data, &reply);
         return reply.readInt32();
     }
+
+    status_t setVideoTarget(const sp<IGraphicBufferProducer>& bufferProducer)
+    {
+        ALOGV("setVideoTarget");
+        Parcel data, reply;
+        data.writeInterfaceToken(ICamera::getInterfaceDescriptor());
+        sp<IBinder> b(IInterface::asBinder(bufferProducer));
+        data.writeStrongBinder(b);
+        remote()->transact(SET_VIDEO_BUFFER_TARGET, data, &reply);
+        return reply.readInt32();
+    }
 };
 
 IMPLEMENT_META_INTERFACE(Camera, "android.hardware.ICamera");
@@ -339,11 +371,18 @@
             releaseRecordingFrame(mem);
             return NO_ERROR;
         } break;
-        case STORE_META_DATA_IN_BUFFERS: {
-            ALOGV("STORE_META_DATA_IN_BUFFERS");
+        case RELEASE_RECORDING_FRAME_HANDLE: {
+            ALOGV("RELEASE_RECORDING_FRAME_HANDLE");
             CHECK_INTERFACE(ICamera, data, reply);
-            bool enabled = data.readInt32();
-            reply->writeInt32(storeMetaDataInBuffers(enabled));
+            // releaseRecordingFrameHandle will be responsble to close the native handle.
+            releaseRecordingFrameHandle(data.readNativeHandle());
+            return NO_ERROR;
+        } break;
+        case SET_VIDEO_BUFFER_MODE: {
+            ALOGV("SET_VIDEO_BUFFER_MODE");
+            CHECK_INTERFACE(ICamera, data, reply);
+            int32_t mode = data.readInt32();
+            reply->writeInt32(setVideoBufferMode(mode));
             return NO_ERROR;
         } break;
         case PREVIEW_ENABLED: {
@@ -415,6 +454,14 @@
             reply->writeInt32(unlock());
             return NO_ERROR;
         } break;
+        case SET_VIDEO_BUFFER_TARGET: {
+            ALOGV("SET_VIDEO_BUFFER_TARGET");
+            CHECK_INTERFACE(ICamera, data, reply);
+            sp<IGraphicBufferProducer> st =
+                interface_cast<IGraphicBufferProducer>(data.readStrongBinder());
+            reply->writeInt32(setVideoTarget(st));
+            return NO_ERROR;
+        } break;
         default:
             return BBinder::onTransact(code, data, reply, flags);
     }
@@ -422,4 +469,5 @@
 
 // ----------------------------------------------------------------------------
 
-}; // namespace android
+} // namespace hardware
+} // namespace android
diff --git a/camera/ICameraClient.cpp b/camera/ICameraClient.cpp
index 179a341..68cbfb8 100644
--- a/camera/ICameraClient.cpp
+++ b/camera/ICameraClient.cpp
@@ -2,16 +2,16 @@
 **
 ** Copyright 2008, The Android Open Source Project
 **
-** Licensed under the Apache License, Version 2.0 (the "License"); 
-** you may not use this file except in compliance with the License. 
-** You may obtain a copy of the License at 
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
 **
-**     http://www.apache.org/licenses/LICENSE-2.0 
+**     http://www.apache.org/licenses/LICENSE-2.0
 **
-** Unless required by applicable law or agreed to in writing, software 
-** distributed under the License is distributed on an "AS IS" BASIS, 
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
-** See the License for the specific language governing permissions and 
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
 ** limitations under the License.
 */
 
@@ -20,14 +20,18 @@
 #include <utils/Log.h>
 #include <stdint.h>
 #include <sys/types.h>
-#include <camera/ICameraClient.h>
+#include <camera/CameraUtils.h>
+#include <android/hardware/ICameraClient.h>
+#include <media/hardware/HardwareAPI.h>
 
 namespace android {
+namespace hardware {
 
 enum {
     NOTIFY_CALLBACK = IBinder::FIRST_CALL_TRANSACTION,
     DATA_CALLBACK,
     DATA_CALLBACK_TIMESTAMP,
+    RECORDING_FRAME_HANDLE_CALLBACK_TIMESTAMP,
 };
 
 class BpCameraClient: public BpInterface<ICameraClient>
@@ -77,6 +81,16 @@
         data.writeStrongBinder(IInterface::asBinder(imageData));
         remote()->transact(DATA_CALLBACK_TIMESTAMP, data, &reply, IBinder::FLAG_ONEWAY);
     }
+
+    void recordingFrameHandleCallbackTimestamp(nsecs_t timestamp, native_handle_t* handle) {
+        ALOGV("recordingFrameHandleCallbackTimestamp");
+        Parcel data, reply;
+        data.writeInterfaceToken(ICameraClient::getInterfaceDescriptor());
+        data.writeInt64(timestamp);
+        data.writeNativeHandle(handle);
+        remote()->transact(RECORDING_FRAME_HANDLE_CALLBACK_TIMESTAMP, data, &reply,
+                IBinder::FLAG_ONEWAY);
+    }
 };
 
 IMPLEMENT_META_INTERFACE(CameraClient, "android.hardware.ICameraClient");
@@ -121,6 +135,25 @@
             dataCallbackTimestamp(timestamp, msgType, imageData);
             return NO_ERROR;
         } break;
+        case RECORDING_FRAME_HANDLE_CALLBACK_TIMESTAMP: {
+            ALOGV("RECORDING_FRAME_HANDLE_CALLBACK_TIMESTAMP");
+            CHECK_INTERFACE(ICameraClient, data, reply);
+            nsecs_t timestamp;
+            status_t res = data.readInt64(&timestamp);
+            if (res != OK) {
+                ALOGE("%s: Failed to read timestamp: %s (%d)", __FUNCTION__, strerror(-res), res);
+                return BAD_VALUE;
+            }
+            native_handle_t* handle = data.readNativeHandle();
+            if (handle == nullptr) {
+                ALOGE("%s: Received a null native handle", __FUNCTION__);
+                return BAD_VALUE;
+            }
+
+            // The native handle will be freed in BpCamera::releaseRecordingFrameHandle.
+            recordingFrameHandleCallbackTimestamp(timestamp, handle);
+            return NO_ERROR;
+        } break;
         default:
             return BBinder::onTransact(code, data, reply, flags);
     }
@@ -128,5 +161,5 @@
 
 // ----------------------------------------------------------------------------
 
-}; // namespace android
-
+} // namespace hardware
+} // namespace android
diff --git a/camera/ICameraRecordingProxy.cpp b/camera/ICameraRecordingProxy.cpp
index 517b64f..63c4b1d 100644
--- a/camera/ICameraRecordingProxy.cpp
+++ b/camera/ICameraRecordingProxy.cpp
@@ -16,10 +16,12 @@
 
 //#define LOG_NDEBUG 0
 #define LOG_TAG "ICameraRecordingProxy"
+#include <camera/CameraUtils.h>
 #include <camera/ICameraRecordingProxy.h>
 #include <camera/ICameraRecordingProxyListener.h>
 #include <binder/IMemory.h>
 #include <binder/Parcel.h>
+#include <media/hardware/HardwareAPI.h>
 #include <stdint.h>
 #include <utils/Log.h>
 
@@ -29,13 +31,9 @@
     START_RECORDING = IBinder::FIRST_CALL_TRANSACTION,
     STOP_RECORDING,
     RELEASE_RECORDING_FRAME,
+    RELEASE_RECORDING_FRAME_HANDLE,
 };
 
-uint8_t ICameraRecordingProxy::baseObject = 0;
-
-size_t ICameraRecordingProxy::getCommonBaseAddress() {
-    return (size_t)&baseObject;
-}
 
 class BpCameraRecordingProxy: public BpInterface<ICameraRecordingProxy>
 {
@@ -71,6 +69,19 @@
         data.writeStrongBinder(IInterface::asBinder(mem));
         remote()->transact(RELEASE_RECORDING_FRAME, data, &reply);
     }
+
+    void releaseRecordingFrameHandle(native_handle_t *handle) {
+        ALOGV("releaseRecordingFrameHandle");
+        Parcel data, reply;
+        data.writeInterfaceToken(ICameraRecordingProxy::getInterfaceDescriptor());
+        data.writeNativeHandle(handle);
+
+        remote()->transact(RELEASE_RECORDING_FRAME_HANDLE, data, &reply);
+
+        // Close the native handle because camera received a dup copy.
+        native_handle_close(handle);
+        native_handle_delete(handle);
+    }
 };
 
 IMPLEMENT_META_INTERFACE(CameraRecordingProxy, "android.hardware.ICameraRecordingProxy");
@@ -102,7 +113,14 @@
             releaseRecordingFrame(mem);
             return NO_ERROR;
         } break;
+        case RELEASE_RECORDING_FRAME_HANDLE: {
+            ALOGV("RELEASE_RECORDING_FRAME_HANDLE");
+            CHECK_INTERFACE(ICameraRecordingProxy, data, reply);
 
+            // releaseRecordingFrameHandle will be responsble to close the native handle.
+            releaseRecordingFrameHandle(data.readNativeHandle());
+            return NO_ERROR;
+        } break;
         default:
             return BBinder::onTransact(code, data, reply, flags);
     }
@@ -111,3 +129,4 @@
 // ----------------------------------------------------------------------------
 
 }; // namespace android
+
diff --git a/camera/ICameraRecordingProxyListener.cpp b/camera/ICameraRecordingProxyListener.cpp
index cf848fc..fa4dfd8 100644
--- a/camera/ICameraRecordingProxyListener.cpp
+++ b/camera/ICameraRecordingProxyListener.cpp
@@ -16,15 +16,18 @@
 
 //#define LOG_NDEBUG 0
 #define LOG_TAG "ICameraRecordingProxyListener"
+#include <camera/CameraUtils.h>
 #include <camera/ICameraRecordingProxyListener.h>
 #include <binder/IMemory.h>
 #include <binder/Parcel.h>
+#include <media/hardware/HardwareAPI.h>
 #include <utils/Log.h>
 
 namespace android {
 
 enum {
     DATA_CALLBACK_TIMESTAMP = IBinder::FIRST_CALL_TRANSACTION,
+    RECORDING_FRAME_HANDLE_CALLBACK_TIMESTAMP,
 };
 
 class BpCameraRecordingProxyListener: public BpInterface<ICameraRecordingProxyListener>
@@ -45,6 +48,20 @@
         data.writeStrongBinder(IInterface::asBinder(imageData));
         remote()->transact(DATA_CALLBACK_TIMESTAMP, data, &reply, IBinder::FLAG_ONEWAY);
     }
+
+    void recordingFrameHandleCallbackTimestamp(nsecs_t timestamp, native_handle_t* handle) {
+        ALOGV("recordingFrameHandleCallbackTimestamp");
+        Parcel data, reply;
+        data.writeInterfaceToken(ICameraRecordingProxyListener::getInterfaceDescriptor());
+        data.writeInt64(timestamp);
+        data.writeNativeHandle(handle);
+        remote()->transact(RECORDING_FRAME_HANDLE_CALLBACK_TIMESTAMP, data, &reply,
+                IBinder::FLAG_ONEWAY);
+
+        // The native handle is dupped in ICameraClient so we need to free it here.
+        native_handle_close(handle);
+        native_handle_delete(handle);
+    }
 };
 
 IMPLEMENT_META_INTERFACE(CameraRecordingProxyListener, "android.hardware.ICameraRecordingProxyListener");
@@ -64,6 +81,26 @@
             dataCallbackTimestamp(timestamp, msgType, imageData);
             return NO_ERROR;
         } break;
+        case RECORDING_FRAME_HANDLE_CALLBACK_TIMESTAMP: {
+            ALOGV("RECORDING_FRAME_HANDLE_CALLBACK_TIMESTAMP");
+            CHECK_INTERFACE(ICameraRecordingProxyListener, data, reply);
+            nsecs_t timestamp;
+            status_t res = data.readInt64(&timestamp);
+            if (res != OK) {
+                ALOGE("%s: Failed to read timestamp: %s (%d)", __FUNCTION__, strerror(-res), res);
+                return BAD_VALUE;
+            }
+
+            native_handle_t* handle = data.readNativeHandle();
+            if (handle == nullptr) {
+                ALOGE("%s: Received a null native handle", __FUNCTION__);
+                return BAD_VALUE;
+            }
+            // The native handle will be freed in
+            // BpCameraRecordingProxy::releaseRecordingFrameHandle.
+            recordingFrameHandleCallbackTimestamp(timestamp, handle);
+            return NO_ERROR;
+        } break;
         default:
             return BBinder::onTransact(code, data, reply, flags);
     }
diff --git a/camera/ICameraService.cpp b/camera/ICameraService.cpp
deleted file mode 100644
index b359f57..0000000
--- a/camera/ICameraService.cpp
+++ /dev/null
@@ -1,534 +0,0 @@
-/*
-**
-** Copyright 2008, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-#define LOG_TAG "BpCameraService"
-#include <utils/Log.h>
-#include <utils/Errors.h>
-#include <utils/String16.h>
-
-#include <inttypes.h>
-#include <stdint.h>
-#include <sys/types.h>
-
-#include <binder/Parcel.h>
-#include <binder/IPCThreadState.h>
-#include <binder/IServiceManager.h>
-
-#include <camera/ICameraService.h>
-#include <camera/ICameraServiceListener.h>
-#include <camera/ICamera.h>
-#include <camera/ICameraClient.h>
-#include <camera/camera2/ICameraDeviceUser.h>
-#include <camera/camera2/ICameraDeviceCallbacks.h>
-#include <camera/CameraMetadata.h>
-#include <camera/VendorTagDescriptor.h>
-
-namespace android {
-
-namespace {
-
-enum {
-    EX_SECURITY = -1,
-    EX_BAD_PARCELABLE = -2,
-    EX_ILLEGAL_ARGUMENT = -3,
-    EX_NULL_POINTER = -4,
-    EX_ILLEGAL_STATE = -5,
-    EX_HAS_REPLY_HEADER = -128,  // special; see below
-};
-
-static bool readExceptionCode(Parcel& reply) {
-    int32_t exceptionCode = reply.readExceptionCode();
-
-    if (exceptionCode != 0) {
-        const char* errorMsg;
-        switch(exceptionCode) {
-            case EX_SECURITY:
-                errorMsg = "Security";
-                break;
-            case EX_BAD_PARCELABLE:
-                errorMsg = "BadParcelable";
-                break;
-            case EX_NULL_POINTER:
-                errorMsg = "NullPointer";
-                break;
-            case EX_ILLEGAL_STATE:
-                errorMsg = "IllegalState";
-                break;
-            // Binder should be handling this code inside Parcel::readException
-            // but lets have a to-string here anyway just in case.
-            case EX_HAS_REPLY_HEADER:
-                errorMsg = "HasReplyHeader";
-                break;
-            default:
-                errorMsg = "Unknown";
-        }
-
-        ALOGE("Binder transmission error %s (%d)", errorMsg, exceptionCode);
-        return true;
-    }
-
-    return false;
-}
-
-};
-
-class BpCameraService: public BpInterface<ICameraService>
-{
-public:
-    BpCameraService(const sp<IBinder>& impl)
-        : BpInterface<ICameraService>(impl)
-    {
-    }
-
-    // get number of cameras available that support standard camera operations
-    virtual int32_t getNumberOfCameras()
-    {
-        return getNumberOfCameras(CAMERA_TYPE_BACKWARD_COMPATIBLE);
-    }
-
-    // get number of cameras available of a given type
-    virtual int32_t getNumberOfCameras(int type)
-    {
-        Parcel data, reply;
-        data.writeInterfaceToken(ICameraService::getInterfaceDescriptor());
-        data.writeInt32(type);
-        remote()->transact(BnCameraService::GET_NUMBER_OF_CAMERAS, data, &reply);
-
-        if (readExceptionCode(reply)) return 0;
-        return reply.readInt32();
-    }
-
-    // get information about a camera
-    virtual status_t getCameraInfo(int cameraId,
-                                   struct CameraInfo* cameraInfo) {
-        Parcel data, reply;
-        data.writeInterfaceToken(ICameraService::getInterfaceDescriptor());
-        data.writeInt32(cameraId);
-        remote()->transact(BnCameraService::GET_CAMERA_INFO, data, &reply);
-
-        if (readExceptionCode(reply)) return -EPROTO;
-        status_t result = reply.readInt32();
-        if (reply.readInt32() != 0) {
-            cameraInfo->facing = reply.readInt32();
-            cameraInfo->orientation = reply.readInt32();
-        }
-        return result;
-    }
-
-    // get camera characteristics (static metadata)
-    virtual status_t getCameraCharacteristics(int cameraId,
-                                              CameraMetadata* cameraInfo) {
-        Parcel data, reply;
-        data.writeInterfaceToken(ICameraService::getInterfaceDescriptor());
-        data.writeInt32(cameraId);
-        remote()->transact(BnCameraService::GET_CAMERA_CHARACTERISTICS, data, &reply);
-
-        if (readExceptionCode(reply)) return -EPROTO;
-        status_t result = reply.readInt32();
-
-        CameraMetadata out;
-        if (reply.readInt32() != 0) {
-            out.readFromParcel(&reply);
-        }
-
-        if (cameraInfo != NULL) {
-            cameraInfo->swap(out);
-        }
-
-        return result;
-    }
-
-    // Get enumeration and description of vendor tags for camera
-    virtual status_t getCameraVendorTagDescriptor(/*out*/sp<VendorTagDescriptor>& desc) {
-        Parcel data, reply;
-        data.writeInterfaceToken(ICameraService::getInterfaceDescriptor());
-        remote()->transact(BnCameraService::GET_CAMERA_VENDOR_TAG_DESCRIPTOR, data, &reply);
-
-        if (readExceptionCode(reply)) return -EPROTO;
-        status_t result = reply.readInt32();
-
-        if (reply.readInt32() != 0) {
-            sp<VendorTagDescriptor> d;
-            if (VendorTagDescriptor::createFromParcel(&reply, /*out*/d) == OK) {
-                desc = d;
-            }
-        }
-        return result;
-    }
-
-    // connect to camera service (android.hardware.Camera)
-    virtual status_t connect(const sp<ICameraClient>& cameraClient, int cameraId,
-                             const String16 &clientPackageName, int clientUid,
-                             /*out*/
-                             sp<ICamera>& device)
-    {
-        Parcel data, reply;
-        data.writeInterfaceToken(ICameraService::getInterfaceDescriptor());
-        data.writeStrongBinder(IInterface::asBinder(cameraClient));
-        data.writeInt32(cameraId);
-        data.writeString16(clientPackageName);
-        data.writeInt32(clientUid);
-
-        status_t status;
-        status = remote()->transact(BnCameraService::CONNECT, data, &reply);
-        if (status != OK) return status;
-
-        if (readExceptionCode(reply)) return -EPROTO;
-        status = reply.readInt32();
-        if (reply.readInt32() != 0) {
-            device = interface_cast<ICamera>(reply.readStrongBinder());
-        }
-        return status;
-    }
-
-    // connect to camera service (android.hardware.Camera)
-    virtual status_t connectLegacy(const sp<ICameraClient>& cameraClient, int cameraId,
-                             int halVersion,
-                             const String16 &clientPackageName, int clientUid,
-                             /*out*/sp<ICamera>& device)
-    {
-        Parcel data, reply;
-        data.writeInterfaceToken(ICameraService::getInterfaceDescriptor());
-        data.writeStrongBinder(IInterface::asBinder(cameraClient));
-        data.writeInt32(cameraId);
-        data.writeInt32(halVersion);
-        data.writeString16(clientPackageName);
-        data.writeInt32(clientUid);
-
-        status_t status;
-        status = remote()->transact(BnCameraService::CONNECT_LEGACY, data, &reply);
-        if (status != OK) return status;
-
-        if (readExceptionCode(reply)) return -EPROTO;
-        status = reply.readInt32();
-        if (reply.readInt32() != 0) {
-            device = interface_cast<ICamera>(reply.readStrongBinder());
-        }
-        return status;
-    }
-
-    virtual status_t setTorchMode(const String16& cameraId, bool enabled,
-            const sp<IBinder>& clientBinder)
-    {
-        Parcel data, reply;
-        data.writeInterfaceToken(ICameraService::getInterfaceDescriptor());
-        data.writeString16(cameraId);
-        data.writeInt32(enabled ? 1 : 0);
-        data.writeStrongBinder(clientBinder);
-        remote()->transact(BnCameraService::SET_TORCH_MODE, data, &reply);
-
-        if (readExceptionCode(reply)) return -EPROTO;
-        return reply.readInt32();
-    }
-
-    // connect to camera service (android.hardware.camera2.CameraDevice)
-    virtual status_t connectDevice(
-            const sp<ICameraDeviceCallbacks>& cameraCb,
-            int cameraId,
-            const String16& clientPackageName,
-            int clientUid,
-            /*out*/
-            sp<ICameraDeviceUser>& device)
-    {
-        Parcel data, reply;
-        data.writeInterfaceToken(ICameraService::getInterfaceDescriptor());
-        data.writeStrongBinder(IInterface::asBinder(cameraCb));
-        data.writeInt32(cameraId);
-        data.writeString16(clientPackageName);
-        data.writeInt32(clientUid);
-
-        status_t status;
-        status = remote()->transact(BnCameraService::CONNECT_DEVICE, data, &reply);
-        if (status != OK) return status;
-
-        if (readExceptionCode(reply)) return -EPROTO;
-        status = reply.readInt32();
-        if (reply.readInt32() != 0) {
-            device = interface_cast<ICameraDeviceUser>(reply.readStrongBinder());
-        }
-        return status;
-    }
-
-    virtual status_t addListener(const sp<ICameraServiceListener>& listener)
-    {
-        Parcel data, reply;
-        data.writeInterfaceToken(ICameraService::getInterfaceDescriptor());
-        data.writeStrongBinder(IInterface::asBinder(listener));
-        remote()->transact(BnCameraService::ADD_LISTENER, data, &reply);
-
-        if (readExceptionCode(reply)) return -EPROTO;
-        return reply.readInt32();
-    }
-
-    virtual status_t removeListener(const sp<ICameraServiceListener>& listener)
-    {
-        Parcel data, reply;
-        data.writeInterfaceToken(ICameraService::getInterfaceDescriptor());
-        data.writeStrongBinder(IInterface::asBinder(listener));
-        remote()->transact(BnCameraService::REMOVE_LISTENER, data, &reply);
-
-        if (readExceptionCode(reply)) return -EPROTO;
-        return reply.readInt32();
-    }
-
-    virtual status_t getLegacyParameters(int cameraId, String16* parameters) {
-        if (parameters == NULL) {
-            ALOGE("%s: parameters must not be null", __FUNCTION__);
-            return BAD_VALUE;
-        }
-
-        Parcel data, reply;
-        data.writeInterfaceToken(ICameraService::getInterfaceDescriptor());
-
-        data.writeInt32(cameraId);
-        remote()->transact(BnCameraService::GET_LEGACY_PARAMETERS, data, &reply);
-        if (readExceptionCode(reply)) return -EPROTO;
-
-        status_t res = data.readInt32();
-        int32_t length = data.readInt32(); // -1 means null
-        if (length > 0) {
-            *parameters = data.readString16();
-        } else {
-            *parameters = String16();
-        }
-
-        return res;
-    }
-
-    virtual status_t supportsCameraApi(int cameraId, int apiVersion) {
-        Parcel data, reply;
-
-        data.writeInterfaceToken(ICameraService::getInterfaceDescriptor());
-        data.writeInt32(cameraId);
-        data.writeInt32(apiVersion);
-        remote()->transact(BnCameraService::SUPPORTS_CAMERA_API, data, &reply);
-        if (readExceptionCode(reply)) return -EPROTO;
-
-        status_t res = data.readInt32();
-        return res;
-    }
-
-    virtual void notifySystemEvent(int32_t eventId, const int32_t* args, size_t len) {
-        Parcel data, reply;
-        data.writeInterfaceToken(ICameraService::getInterfaceDescriptor());
-        data.writeInt32(eventId);
-        data.writeInt32Array(len, args);
-        remote()->transact(BnCameraService::NOTIFY_SYSTEM_EVENT, data, &reply,
-                IBinder::FLAG_ONEWAY);
-    }
-
-};
-
-IMPLEMENT_META_INTERFACE(CameraService, "android.hardware.ICameraService");
-
-// ----------------------------------------------------------------------
-
-status_t BnCameraService::onTransact(
-    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
-{
-    switch(code) {
-        case GET_NUMBER_OF_CAMERAS: {
-            CHECK_INTERFACE(ICameraService, data, reply);
-            reply->writeNoException();
-            reply->writeInt32(getNumberOfCameras(data.readInt32()));
-            return NO_ERROR;
-        } break;
-        case GET_CAMERA_INFO: {
-            CHECK_INTERFACE(ICameraService, data, reply);
-            CameraInfo cameraInfo = CameraInfo();
-            memset(&cameraInfo, 0, sizeof(cameraInfo));
-            status_t result = getCameraInfo(data.readInt32(), &cameraInfo);
-            reply->writeNoException();
-            reply->writeInt32(result);
-
-            // Fake a parcelable object here
-            reply->writeInt32(1); // means the parcelable is included
-            reply->writeInt32(cameraInfo.facing);
-            reply->writeInt32(cameraInfo.orientation);
-            return NO_ERROR;
-        } break;
-        case GET_CAMERA_CHARACTERISTICS: {
-            CHECK_INTERFACE(ICameraService, data, reply);
-            CameraMetadata info;
-            status_t result = getCameraCharacteristics(data.readInt32(), &info);
-            reply->writeNoException();
-            reply->writeInt32(result);
-
-            // out-variables are after exception and return value
-            reply->writeInt32(1); // means the parcelable is included
-            info.writeToParcel(reply);
-            return NO_ERROR;
-        } break;
-        case GET_CAMERA_VENDOR_TAG_DESCRIPTOR: {
-            CHECK_INTERFACE(ICameraService, data, reply);
-            sp<VendorTagDescriptor> d;
-            status_t result = getCameraVendorTagDescriptor(d);
-            reply->writeNoException();
-            reply->writeInt32(result);
-
-            // out-variables are after exception and return value
-            if (d == NULL) {
-                reply->writeInt32(0);
-            } else {
-                reply->writeInt32(1); // means the parcelable is included
-                d->writeToParcel(reply);
-            }
-            return NO_ERROR;
-        } break;
-        case CONNECT: {
-            CHECK_INTERFACE(ICameraService, data, reply);
-            sp<ICameraClient> cameraClient =
-                    interface_cast<ICameraClient>(data.readStrongBinder());
-            int32_t cameraId = data.readInt32();
-            const String16 clientName = data.readString16();
-            int32_t clientUid = data.readInt32();
-            sp<ICamera> camera;
-            status_t status = connect(cameraClient, cameraId,
-                    clientName, clientUid, /*out*/camera);
-            reply->writeNoException();
-            reply->writeInt32(status);
-            if (camera != NULL) {
-                reply->writeInt32(1);
-                reply->writeStrongBinder(IInterface::asBinder(camera));
-            } else {
-                reply->writeInt32(0);
-            }
-            return NO_ERROR;
-        } break;
-        case CONNECT_DEVICE: {
-            CHECK_INTERFACE(ICameraService, data, reply);
-            sp<ICameraDeviceCallbacks> cameraClient =
-                interface_cast<ICameraDeviceCallbacks>(data.readStrongBinder());
-            int32_t cameraId = data.readInt32();
-            const String16 clientName = data.readString16();
-            int32_t clientUid = data.readInt32();
-            sp<ICameraDeviceUser> camera;
-            status_t status = connectDevice(cameraClient, cameraId,
-                    clientName, clientUid, /*out*/camera);
-            reply->writeNoException();
-            reply->writeInt32(status);
-            if (camera != NULL) {
-                reply->writeInt32(1);
-                reply->writeStrongBinder(IInterface::asBinder(camera));
-            } else {
-                reply->writeInt32(0);
-            }
-            return NO_ERROR;
-        } break;
-        case ADD_LISTENER: {
-            CHECK_INTERFACE(ICameraService, data, reply);
-            sp<ICameraServiceListener> listener =
-                interface_cast<ICameraServiceListener>(data.readStrongBinder());
-            reply->writeNoException();
-            reply->writeInt32(addListener(listener));
-            return NO_ERROR;
-        } break;
-        case REMOVE_LISTENER: {
-            CHECK_INTERFACE(ICameraService, data, reply);
-            sp<ICameraServiceListener> listener =
-                interface_cast<ICameraServiceListener>(data.readStrongBinder());
-            reply->writeNoException();
-            reply->writeInt32(removeListener(listener));
-            return NO_ERROR;
-        } break;
-        case GET_LEGACY_PARAMETERS: {
-            CHECK_INTERFACE(ICameraService, data, reply);
-            int cameraId = data.readInt32();
-            String16 parameters;
-
-            reply->writeNoException();
-            // return value
-            reply->writeInt32(getLegacyParameters(cameraId, &parameters));
-            // out parameters
-            reply->writeInt32(1); // parameters is always available
-            reply->writeString16(parameters);
-            return NO_ERROR;
-        } break;
-        case SUPPORTS_CAMERA_API: {
-            CHECK_INTERFACE(ICameraService, data, reply);
-            int cameraId = data.readInt32();
-            int apiVersion = data.readInt32();
-
-            reply->writeNoException();
-            // return value
-            reply->writeInt32(supportsCameraApi(cameraId, apiVersion));
-            return NO_ERROR;
-        } break;
-        case CONNECT_LEGACY: {
-            CHECK_INTERFACE(ICameraService, data, reply);
-            sp<ICameraClient> cameraClient =
-                    interface_cast<ICameraClient>(data.readStrongBinder());
-            int32_t cameraId = data.readInt32();
-            int32_t halVersion = data.readInt32();
-            const String16 clientName = data.readString16();
-            int32_t clientUid = data.readInt32();
-            sp<ICamera> camera;
-            status_t status = connectLegacy(cameraClient, cameraId, halVersion,
-                    clientName, clientUid, /*out*/camera);
-            reply->writeNoException();
-            reply->writeInt32(status);
-            if (camera != NULL) {
-                reply->writeInt32(1);
-                reply->writeStrongBinder(IInterface::asBinder(camera));
-            } else {
-                reply->writeInt32(0);
-            }
-            return NO_ERROR;
-        } break;
-        case SET_TORCH_MODE: {
-            CHECK_INTERFACE(ICameraService, data, reply);
-            String16 cameraId = data.readString16();
-            bool enabled = data.readInt32() != 0 ? true : false;
-            const sp<IBinder> clientBinder = data.readStrongBinder();
-            status_t status = setTorchMode(cameraId, enabled, clientBinder);
-            reply->writeNoException();
-            reply->writeInt32(status);
-            return NO_ERROR;
-        } break;
-        case NOTIFY_SYSTEM_EVENT: {
-            CHECK_INTERFACE(ICameraService, data, reply);
-            int32_t eventId = data.readInt32();
-            int32_t len = data.readInt32();
-            if (len < 0) {
-                ALOGE("%s: Received poorly formatted length in binder request: notifySystemEvent.",
-                        __FUNCTION__);
-                return FAILED_TRANSACTION;
-            }
-            if (len > 512) {
-                ALOGE("%s: Length %" PRIi32 " too long in binder request: notifySystemEvent.",
-                        __FUNCTION__, len);
-                return FAILED_TRANSACTION;
-            }
-            int32_t events[len];
-            memset(events, 0, sizeof(int32_t) * len);
-            status_t status = data.read(events, sizeof(int32_t) * len);
-            if (status != NO_ERROR) {
-                ALOGE("%s: Received poorly formatted binder request: notifySystemEvent.",
-                        __FUNCTION__);
-                return FAILED_TRANSACTION;
-            }
-            notifySystemEvent(eventId, events, len);
-            return NO_ERROR;
-        } break;
-        default:
-            return BBinder::onTransact(code, data, reply, flags);
-    }
-}
-
-// ----------------------------------------------------------------------------
-
-}; // namespace android
diff --git a/camera/ICameraServiceListener.cpp b/camera/ICameraServiceListener.cpp
deleted file mode 100644
index 0010325..0000000
--- a/camera/ICameraServiceListener.cpp
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
-**
-** Copyright 2013, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-#include <stdint.h>
-#include <sys/types.h>
-
-#include <binder/Parcel.h>
-#include <binder/IPCThreadState.h>
-#include <binder/IServiceManager.h>
-
-#include <camera/ICameraServiceListener.h>
-
-namespace android {
-
-namespace {
-    enum {
-        STATUS_CHANGED = IBinder::FIRST_CALL_TRANSACTION,
-        TORCH_STATUS_CHANGED,
-    };
-}; // namespace anonymous
-
-class BpCameraServiceListener: public BpInterface<ICameraServiceListener>
-{
-
-public:
-    BpCameraServiceListener(const sp<IBinder>& impl)
-        : BpInterface<ICameraServiceListener>(impl)
-    {
-    }
-
-    virtual void onStatusChanged(Status status, int32_t cameraId)
-    {
-        Parcel data, reply;
-        data.writeInterfaceToken(ICameraServiceListener::getInterfaceDescriptor());
-
-        data.writeInt32(static_cast<int32_t>(status));
-        data.writeInt32(cameraId);
-
-        remote()->transact(STATUS_CHANGED,
-                           data,
-                           &reply,
-                           IBinder::FLAG_ONEWAY);
-    }
-
-    virtual void onTorchStatusChanged(TorchStatus status, const String16 &cameraId)
-    {
-        Parcel data, reply;
-        data.writeInterfaceToken(ICameraServiceListener::getInterfaceDescriptor());
-
-        data.writeInt32(static_cast<int32_t>(status));
-        data.writeString16(cameraId);
-
-        remote()->transact(TORCH_STATUS_CHANGED,
-                           data,
-                           &reply,
-                           IBinder::FLAG_ONEWAY);
-    }
-};
-
-IMPLEMENT_META_INTERFACE(CameraServiceListener, "android.hardware.ICameraServiceListener");
-
-// ----------------------------------------------------------------------
-
-status_t BnCameraServiceListener::onTransact(uint32_t code, const Parcel& data, Parcel* reply,
-        uint32_t flags) {
-    switch(code) {
-        case STATUS_CHANGED: {
-            CHECK_INTERFACE(ICameraServiceListener, data, reply);
-
-            Status status = static_cast<Status>(data.readInt32());
-            int32_t cameraId = data.readInt32();
-
-            onStatusChanged(status, cameraId);
-
-            return NO_ERROR;
-        } break;
-        case TORCH_STATUS_CHANGED: {
-            CHECK_INTERFACE(ICameraServiceListener, data, reply);
-
-            TorchStatus status = static_cast<TorchStatus>(data.readInt32());
-            String16 cameraId = data.readString16();
-
-            onTorchStatusChanged(status, cameraId);
-
-            return NO_ERROR;
-        } break;
-        default:
-            return BBinder::onTransact(code, data, reply, flags);
-    }
-}
-
-// ----------------------------------------------------------------------------
-
-}; // namespace android
diff --git a/camera/VendorTagDescriptor.cpp b/camera/VendorTagDescriptor.cpp
index dce313a..5538da9 100644
--- a/camera/VendorTagDescriptor.cpp
+++ b/camera/VendorTagDescriptor.cpp
@@ -46,7 +46,9 @@
 static Mutex sLock;
 static sp<VendorTagDescriptor> sGlobalVendorTagDescriptor;
 
-VendorTagDescriptor::VendorTagDescriptor() {}
+namespace hardware {
+namespace camera2 {
+namespace params {
 
 VendorTagDescriptor::~VendorTagDescriptor() {
     size_t len = mReverseMapping.size();
@@ -55,90 +57,46 @@
     }
 }
 
-status_t VendorTagDescriptor::createDescriptorFromOps(const vendor_tag_ops_t* vOps,
-            /*out*/
-            sp<VendorTagDescriptor>& descriptor) {
-    if (vOps == NULL) {
-        ALOGE("%s: vendor_tag_ops argument was NULL.", __FUNCTION__);
-        return BAD_VALUE;
-    }
-
-    int tagCount = vOps->get_tag_count(vOps);
-    if (tagCount < 0 || tagCount > INT32_MAX) {
-        ALOGE("%s: tag count %d from vendor ops is invalid.", __FUNCTION__, tagCount);
-        return BAD_VALUE;
-    }
-
-    Vector<uint32_t> tagArray;
-    LOG_ALWAYS_FATAL_IF(tagArray.resize(tagCount) != tagCount,
-            "%s: too many (%u) vendor tags defined.", __FUNCTION__, tagCount);
-
-    vOps->get_all_tags(vOps, /*out*/tagArray.editArray());
-
-    sp<VendorTagDescriptor> desc = new VendorTagDescriptor();
-    desc->mTagCount = tagCount;
-
-    SortedVector<String8> sections;
-    KeyedVector<uint32_t, String8> tagToSectionMap;
-
-    for (size_t i = 0; i < static_cast<size_t>(tagCount); ++i) {
-        uint32_t tag = tagArray[i];
-        if (tag < CAMERA_METADATA_VENDOR_TAG_BOUNDARY) {
-            ALOGE("%s: vendor tag %d not in vendor tag section.", __FUNCTION__, tag);
-            return BAD_VALUE;
-        }
-        const char *tagName = vOps->get_tag_name(vOps, tag);
-        if (tagName == NULL) {
-            ALOGE("%s: no tag name defined for vendor tag %d.", __FUNCTION__, tag);
-            return BAD_VALUE;
-        }
-        desc->mTagToNameMap.add(tag, String8(tagName));
-        const char *sectionName = vOps->get_section_name(vOps, tag);
-        if (sectionName == NULL) {
-            ALOGE("%s: no section name defined for vendor tag %d.", __FUNCTION__, tag);
-            return BAD_VALUE;
-        }
-
-        String8 sectionString(sectionName);
-
-        sections.add(sectionString);
-        tagToSectionMap.add(tag, sectionString);
-
-        int tagType = vOps->get_tag_type(vOps, tag);
-        if (tagType < 0 || tagType >= NUM_TYPES) {
-            ALOGE("%s: tag type %d from vendor ops does not exist.", __FUNCTION__, tagType);
-            return BAD_VALUE;
-        }
-        desc->mTagToTypeMap.add(tag, tagType);
-    }
-
-    desc->mSections = sections;
-
-    for (size_t i = 0; i < static_cast<size_t>(tagCount); ++i) {
-        uint32_t tag = tagArray[i];
-        String8 sectionString = tagToSectionMap.valueFor(tag);
-
-        // Set up tag to section index map
-        ssize_t index = sections.indexOf(sectionString);
-        LOG_ALWAYS_FATAL_IF(index < 0, "index %zd must be non-negative", index);
-        desc->mTagToSectionMap.add(tag, static_cast<uint32_t>(index));
-
-        // Set up reverse mapping
-        ssize_t reverseIndex = -1;
-        if ((reverseIndex = desc->mReverseMapping.indexOfKey(sectionString)) < 0) {
-            KeyedVector<String8, uint32_t>* nameMapper = new KeyedVector<String8, uint32_t>();
-            reverseIndex = desc->mReverseMapping.add(sectionString, nameMapper);
-        }
-        desc->mReverseMapping[reverseIndex]->add(desc->mTagToNameMap.valueFor(tag), tag);
-    }
-
-    descriptor = desc;
-    return OK;
+VendorTagDescriptor::VendorTagDescriptor() :
+        mTagCount(0),
+        mVendorOps() {
 }
 
-status_t VendorTagDescriptor::createFromParcel(const Parcel* parcel,
-            /*out*/
-            sp<VendorTagDescriptor>& descriptor) {
+VendorTagDescriptor::VendorTagDescriptor(const VendorTagDescriptor& src) {
+    copyFrom(src);
+}
+
+VendorTagDescriptor& VendorTagDescriptor::operator=(const VendorTagDescriptor& rhs) {
+    copyFrom(rhs);
+    return *this;
+}
+
+void VendorTagDescriptor::copyFrom(const VendorTagDescriptor& src) {
+    if (this == &src) return;
+
+    size_t len = mReverseMapping.size();
+    for (size_t i = 0; i < len; ++i) {
+        delete mReverseMapping[i];
+    }
+    mReverseMapping.clear();
+
+    len = src.mReverseMapping.size();
+    // Have to copy KeyedVectors inside mReverseMapping
+    for (size_t i = 0; i < len; ++i) {
+        KeyedVector<String8, uint32_t>* nameMapper = new KeyedVector<String8, uint32_t>();
+        *nameMapper = *(src.mReverseMapping.valueAt(i));
+        mReverseMapping.add(src.mReverseMapping.keyAt(i), nameMapper);
+    }
+    // Everything else is simple
+    mTagToNameMap = src.mTagToNameMap;
+    mTagToSectionMap = src.mTagToSectionMap;
+    mTagToTypeMap = src.mTagToTypeMap;
+    mSections = src.mSections;
+    mTagCount = src.mTagCount;
+    mVendorOps = src.mVendorOps;
+}
+
+status_t VendorTagDescriptor::readFromParcel(const Parcel* parcel) {
     status_t res = OK;
     if (parcel == NULL) {
         ALOGE("%s: parcel argument was NULL.", __FUNCTION__);
@@ -156,8 +114,7 @@
         return BAD_VALUE;
     }
 
-    sp<VendorTagDescriptor> desc = new VendorTagDescriptor();
-    desc->mTagCount = tagCount;
+    mTagCount = tagCount;
 
     uint32_t tag, sectionIndex;
     uint32_t maxSectionIndex = 0;
@@ -197,9 +154,9 @@
         maxSectionIndex = (maxSectionIndex >= sectionIndex) ? maxSectionIndex : sectionIndex;
 
         allTags.add(tag);
-        desc->mTagToNameMap.add(tag, tagName);
-        desc->mTagToSectionMap.add(tag, sectionIndex);
-        desc->mTagToTypeMap.add(tag, tagType);
+        mTagToNameMap.add(tag, tagName);
+        mTagToSectionMap.add(tag, sectionIndex);
+        mTagToTypeMap.add(tag, tagType);
     }
 
     if (res != OK) {
@@ -217,7 +174,7 @@
                     __FUNCTION__, sectionCount, (maxSectionIndex + 1));
             return BAD_VALUE;
         }
-        LOG_ALWAYS_FATAL_IF(desc->mSections.setCapacity(sectionCount) <= 0,
+        LOG_ALWAYS_FATAL_IF(mSections.setCapacity(sectionCount) <= 0,
                 "Vector capacity must be positive");
         for (size_t i = 0; i < sectionCount; ++i) {
             String8 sectionName = parcel->readString8();
@@ -226,7 +183,7 @@
                       __FUNCTION__, i);
                 return NOT_ENOUGH_DATA;
             }
-            desc->mSections.add(sectionName);
+            mSections.add(sectionName);
         }
     }
 
@@ -235,17 +192,16 @@
     // Set up reverse mapping
     for (size_t i = 0; i < static_cast<size_t>(tagCount); ++i) {
         uint32_t tag = allTags[i];
-        String8 sectionString = desc->mSections[desc->mTagToSectionMap.valueFor(tag)];
+        String8 sectionString = mSections[mTagToSectionMap.valueFor(tag)];
 
         ssize_t reverseIndex = -1;
-        if ((reverseIndex = desc->mReverseMapping.indexOfKey(sectionString)) < 0) {
+        if ((reverseIndex = mReverseMapping.indexOfKey(sectionString)) < 0) {
             KeyedVector<String8, uint32_t>* nameMapper = new KeyedVector<String8, uint32_t>();
-            reverseIndex = desc->mReverseMapping.add(sectionString, nameMapper);
+            reverseIndex = mReverseMapping.add(sectionString, nameMapper);
         }
-        desc->mReverseMapping[reverseIndex]->add(desc->mTagToNameMap.valueFor(tag), tag);
+        mReverseMapping[reverseIndex]->add(mTagToNameMap.valueFor(tag), tag);
     }
 
-    descriptor = desc;
     return res;
 }
 
@@ -377,6 +333,92 @@
 
 }
 
+} // namespace params
+} // namespace camera2
+} // namespace hardware
+
+
+status_t VendorTagDescriptor::createDescriptorFromOps(const vendor_tag_ops_t* vOps,
+            /*out*/
+            sp<VendorTagDescriptor>& descriptor) {
+    if (vOps == NULL) {
+        ALOGE("%s: vendor_tag_ops argument was NULL.", __FUNCTION__);
+        return BAD_VALUE;
+    }
+
+    int tagCount = vOps->get_tag_count(vOps);
+    if (tagCount < 0 || tagCount > INT32_MAX) {
+        ALOGE("%s: tag count %d from vendor ops is invalid.", __FUNCTION__, tagCount);
+        return BAD_VALUE;
+    }
+
+    Vector<uint32_t> tagArray;
+    LOG_ALWAYS_FATAL_IF(tagArray.resize(tagCount) != tagCount,
+            "%s: too many (%u) vendor tags defined.", __FUNCTION__, tagCount);
+
+    vOps->get_all_tags(vOps, /*out*/tagArray.editArray());
+
+    sp<VendorTagDescriptor> desc = new VendorTagDescriptor();
+    desc->mTagCount = tagCount;
+
+    SortedVector<String8> sections;
+    KeyedVector<uint32_t, String8> tagToSectionMap;
+
+    for (size_t i = 0; i < static_cast<size_t>(tagCount); ++i) {
+        uint32_t tag = tagArray[i];
+        if (tag < CAMERA_METADATA_VENDOR_TAG_BOUNDARY) {
+            ALOGE("%s: vendor tag %d not in vendor tag section.", __FUNCTION__, tag);
+            return BAD_VALUE;
+        }
+        const char *tagName = vOps->get_tag_name(vOps, tag);
+        if (tagName == NULL) {
+            ALOGE("%s: no tag name defined for vendor tag %d.", __FUNCTION__, tag);
+            return BAD_VALUE;
+        }
+        desc->mTagToNameMap.add(tag, String8(tagName));
+        const char *sectionName = vOps->get_section_name(vOps, tag);
+        if (sectionName == NULL) {
+            ALOGE("%s: no section name defined for vendor tag %d.", __FUNCTION__, tag);
+            return BAD_VALUE;
+        }
+
+        String8 sectionString(sectionName);
+
+        sections.add(sectionString);
+        tagToSectionMap.add(tag, sectionString);
+
+        int tagType = vOps->get_tag_type(vOps, tag);
+        if (tagType < 0 || tagType >= NUM_TYPES) {
+            ALOGE("%s: tag type %d from vendor ops does not exist.", __FUNCTION__, tagType);
+            return BAD_VALUE;
+        }
+        desc->mTagToTypeMap.add(tag, tagType);
+    }
+
+    desc->mSections = sections;
+
+    for (size_t i = 0; i < static_cast<size_t>(tagCount); ++i) {
+        uint32_t tag = tagArray[i];
+        String8 sectionString = tagToSectionMap.valueFor(tag);
+
+        // Set up tag to section index map
+        ssize_t index = sections.indexOf(sectionString);
+        LOG_ALWAYS_FATAL_IF(index < 0, "index %zd must be non-negative", index);
+        desc->mTagToSectionMap.add(tag, static_cast<uint32_t>(index));
+
+        // Set up reverse mapping
+        ssize_t reverseIndex = -1;
+        if ((reverseIndex = desc->mReverseMapping.indexOfKey(sectionString)) < 0) {
+            KeyedVector<String8, uint32_t>* nameMapper = new KeyedVector<String8, uint32_t>();
+            reverseIndex = desc->mReverseMapping.add(sectionString, nameMapper);
+        }
+        desc->mReverseMapping[reverseIndex]->add(desc->mTagToNameMap.valueFor(tag), tag);
+    }
+
+    descriptor = desc;
+    return OK;
+}
+
 status_t VendorTagDescriptor::setAsGlobalVendorTagDescriptor(const sp<VendorTagDescriptor>& desc) {
     status_t res = OK;
     Mutex::Autolock al(sLock);
diff --git a/services/camera/libcameraservice/api1/client2/ZslProcessorInterface.cpp b/camera/aidl/android/hardware/CameraInfo.aidl
similarity index 69%
copy from services/camera/libcameraservice/api1/client2/ZslProcessorInterface.cpp
copy to camera/aidl/android/hardware/CameraInfo.aidl
index 9efeaba..c6a3a61 100644
--- a/services/camera/libcameraservice/api1/client2/ZslProcessorInterface.cpp
+++ b/camera/aidl/android/hardware/CameraInfo.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2014 The Android Open Source Project
+ * Copyright (C) 2013 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,15 +14,7 @@
  * limitations under the License.
  */
 
-#include "ZslProcessorInterface.h"
+package android.hardware;
 
-namespace android {
-namespace camera2 {
-
-status_t ZslProcessorInterface::disconnect() {
-    return OK;
-}
-
-}; //namespace camera2
-}; //namespace android
-
+/** @hide */
+parcelable CameraInfo cpp_header "camera/CameraBase.h";
diff --git a/services/camera/libcameraservice/api1/client2/ZslProcessorInterface.cpp b/camera/aidl/android/hardware/ICamera.aidl
similarity index 65%
copy from services/camera/libcameraservice/api1/client2/ZslProcessorInterface.cpp
copy to camera/aidl/android/hardware/ICamera.aidl
index 9efeaba..f9db842 100644
--- a/services/camera/libcameraservice/api1/client2/ZslProcessorInterface.cpp
+++ b/camera/aidl/android/hardware/ICamera.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2014 The Android Open Source Project
+ * Copyright (C) 2013 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,15 +14,15 @@
  * limitations under the License.
  */
 
-#include "ZslProcessorInterface.h"
+package android.hardware;
 
-namespace android {
-namespace camera2 {
-
-status_t ZslProcessorInterface::disconnect() {
-    return OK;
+/** @hide */
+interface ICamera
+{
+    /**
+     * Only one call exposed, for ICameraService testing purposes
+     *
+     * Keep up-to-date with frameworks/av/include/camera/ICamera.h
+     */
+    void disconnect();
 }
-
-}; //namespace camera2
-}; //namespace android
-
diff --git a/services/camera/libcameraservice/api1/client2/ZslProcessorInterface.cpp b/camera/aidl/android/hardware/ICameraClient.aidl
similarity index 69%
copy from services/camera/libcameraservice/api1/client2/ZslProcessorInterface.cpp
copy to camera/aidl/android/hardware/ICameraClient.aidl
index 9efeaba..808edee 100644
--- a/services/camera/libcameraservice/api1/client2/ZslProcessorInterface.cpp
+++ b/camera/aidl/android/hardware/ICameraClient.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2014 The Android Open Source Project
+ * Copyright (C) 2013 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,15 +14,10 @@
  * limitations under the License.
  */
 
-#include "ZslProcessorInterface.h"
+package android.hardware;
 
-namespace android {
-namespace camera2 {
-
-status_t ZslProcessorInterface::disconnect() {
-    return OK;
+/** @hide */
+interface ICameraClient
+{
+    // For now, empty because there is a manual implementation
 }
-
-}; //namespace camera2
-}; //namespace android
-
diff --git a/camera/aidl/android/hardware/ICameraService.aidl b/camera/aidl/android/hardware/ICameraService.aidl
new file mode 100644
index 0000000..e94fd0c
--- /dev/null
+++ b/camera/aidl/android/hardware/ICameraService.aidl
@@ -0,0 +1,147 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware;
+
+import android.hardware.ICamera;
+import android.hardware.ICameraClient;
+import android.hardware.camera2.ICameraDeviceUser;
+import android.hardware.camera2.ICameraDeviceCallbacks;
+import android.hardware.camera2.params.VendorTagDescriptor;
+import android.hardware.camera2.impl.CameraMetadataNative;
+import android.hardware.ICameraServiceListener;
+import android.hardware.CameraInfo;
+
+/**
+ * Binder interface for the native camera service running in mediaserver.
+ *
+ * @hide
+ */
+interface ICameraService
+{
+    /**
+     * All camera service and device Binder calls may return a
+     * ServiceSpecificException with the following error codes
+     */
+    const int ERROR_PERMISSION_DENIED = 1;
+    const int ERROR_ALREADY_EXISTS = 2;
+    const int ERROR_ILLEGAL_ARGUMENT = 3;
+    const int ERROR_DISCONNECTED = 4;
+    const int ERROR_TIMED_OUT = 5;
+    const int ERROR_DISABLED = 6;
+    const int ERROR_CAMERA_IN_USE = 7;
+    const int ERROR_MAX_CAMERAS_IN_USE = 8;
+    const int ERROR_DEPRECATED_HAL = 9;
+    const int ERROR_INVALID_OPERATION = 10;
+
+    /**
+     * Types for getNumberOfCameras
+     */
+    const int CAMERA_TYPE_BACKWARD_COMPATIBLE = 0;
+    const int CAMERA_TYPE_ALL = 1;
+
+    /**
+     * Return the number of camera devices available in the system
+     */
+    int getNumberOfCameras(int type);
+
+    /**
+     * Fetch basic camera information for a camera device
+     */
+    CameraInfo getCameraInfo(int cameraId);
+
+    /**
+     * Default UID/PID values for non-privileged callers of
+     * connect(), connectDevice(), and connectLegacy()
+     */
+    const int USE_CALLING_UID = -1;
+    const int USE_CALLING_PID = -1;
+
+    /**
+     * Open a camera device through the old camera API
+     */
+    ICamera connect(ICameraClient client,
+            int cameraId,
+            String opPackageName,
+            int clientUid, int clientPid);
+
+    /**
+     * Open a camera device through the new camera API
+     * Only supported for device HAL versions >= 3.2
+     */
+    ICameraDeviceUser connectDevice(ICameraDeviceCallbacks callbacks,
+            int cameraId,
+            String opPackageName,
+            int clientUid);
+
+    /**
+     * halVersion constant for connectLegacy
+     */
+    const int CAMERA_HAL_API_VERSION_UNSPECIFIED = -1;
+
+    /**
+     * Open a camera device in legacy mode, if supported by the camera module HAL.
+     */
+    ICamera connectLegacy(ICameraClient client,
+            int cameraId,
+            int halVersion,
+            String opPackageName,
+            int clientUid);
+
+    /**
+     * Add/remove listeners for changes to camera device and flashlight state
+     */
+    void addListener(ICameraServiceListener listener);
+    void removeListener(ICameraServiceListener listener);
+
+    /**
+     * Read the static camera metadata for a camera device.
+     * Only supported for device HAL versions >= 3.2
+     */
+    CameraMetadataNative getCameraCharacteristics(int cameraId);
+
+    /**
+     * Read in the vendor tag descriptors from the camera module HAL.
+     * Intended to be used by the native code of CameraMetadataNative to correctly
+     * interpret camera metadata with vendor tags.
+     */
+    VendorTagDescriptor getCameraVendorTagDescriptor();
+
+    /**
+     * Read the legacy camera1 parameters into a String
+     */
+    String getLegacyParameters(int cameraId);
+
+    /**
+     * apiVersion constants for supportsCameraApi
+     */
+    const int API_VERSION_1 = 1;
+    const int API_VERSION_2 = 2;
+
+    // Determines if a particular API version is supported directly
+    boolean supportsCameraApi(int cameraId, int apiVersion);
+
+    void setTorchMode(String CameraId, boolean enabled, IBinder clientBinder);
+
+    /**
+     * Notify the camera service of a system event.  Should only be called from system_server.
+     *
+     * Callers require the android.permission.CAMERA_SEND_SYSTEM_EVENTS permission.
+     */
+    const int EVENT_NONE = 0;
+    const int EVENT_USER_SWITCHED = 1;
+    oneway void notifySystemEvent(int eventId, in int[] args);
+}
diff --git a/camera/aidl/android/hardware/ICameraServiceListener.aidl b/camera/aidl/android/hardware/ICameraServiceListener.aidl
new file mode 100644
index 0000000..4e2a8c7
--- /dev/null
+++ b/camera/aidl/android/hardware/ICameraServiceListener.aidl
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware;
+
+/** @hide */
+interface ICameraServiceListener
+{
+
+    /**
+     * Initial status will be transmitted with onStatusChange immediately
+     * after this listener is added to the service listener list.
+     *
+     * Allowed transitions:
+     *
+     *     (Any)               -> NOT_PRESENT
+     *     NOT_PRESENT         -> PRESENT
+     *     NOT_PRESENT         -> ENUMERATING
+     *     ENUMERATING         -> PRESENT
+     *     PRESENT             -> NOT_AVAILABLE
+     *     NOT_AVAILABLE       -> PRESENT
+     *
+     * A state will never immediately transition back to itself.
+     *
+     * The enums must match the values in
+     * include/hardware/camera_common.h when applicable
+     */
+    // Device physically unplugged
+    const int STATUS_NOT_PRESENT      = 0;
+    // Device physically has been plugged in and the camera can be used exlusively
+    const int STATUS_PRESENT          = 1;
+    // Device physically has been plugged in but it will not be connect-able until enumeration is
+    // complete
+    const int STATUS_ENUMERATING      = 2;
+    // Camera is in use by another app and cannot be used exclusively
+    const int STATUS_NOT_AVAILABLE    = -2;
+
+    // Use to initialize variables only
+    const int STATUS_UNKNOWN          = -1;
+
+    oneway void onStatusChanged(int status, int cameraId);
+
+    /**
+     * The torch mode status of a camera.
+     *
+     * Initial status will be transmitted with onTorchStatusChanged immediately
+     * after this listener is added to the service listener list.
+     *
+     * The enums must match the values in
+     * include/hardware/camera_common.h
+     */
+    // The camera's torch mode has become not available to use via
+    // setTorchMode().
+    const int TORCH_STATUS_NOT_AVAILABLE = 0;
+    // The camera's torch mode is off and available to be turned on via
+    // setTorchMode().
+    const int TORCH_STATUS_AVAILABLE_OFF = 1;
+    // The camera's torch mode is on and available to be turned off via
+    // setTorchMode().
+    const int TORCH_STATUS_AVAILABLE_ON  = 2;
+
+    // Use to initialize variables only
+    const int TORCH_STATUS_UNKNOWN = -1;
+
+    oneway void onTorchStatusChanged(int status, String cameraId);
+}
diff --git a/camera/aidl/android/hardware/ICameraServiceProxy.aidl b/camera/aidl/android/hardware/ICameraServiceProxy.aidl
new file mode 100644
index 0000000..0e654d5
--- /dev/null
+++ b/camera/aidl/android/hardware/ICameraServiceProxy.aidl
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware;
+
+/**
+ * Binder interface for the camera service proxy running in system_server.
+ *
+ * Keep in sync with frameworks/av/include/camera/ICameraServiceProxy.h
+ *
+ * @hide
+ */
+interface ICameraServiceProxy
+{
+    /**
+     * Ping the service proxy to update the valid users for the camera service.
+     */
+    oneway void pingForUserUpdate();
+
+    /**
+     * Update the status of a camera device
+     */
+     oneway void notifyCameraState(String cameraId, int newCameraState);
+}
diff --git a/services/camera/libcameraservice/api1/client2/ZslProcessorInterface.cpp b/camera/aidl/android/hardware/camera2/CaptureRequest.aidl
similarity index 69%
copy from services/camera/libcameraservice/api1/client2/ZslProcessorInterface.cpp
copy to camera/aidl/android/hardware/camera2/CaptureRequest.aidl
index 9efeaba..9931fc7 100644
--- a/services/camera/libcameraservice/api1/client2/ZslProcessorInterface.cpp
+++ b/camera/aidl/android/hardware/camera2/CaptureRequest.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2014 The Android Open Source Project
+ * Copyright (C) 2013 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,15 +14,7 @@
  * limitations under the License.
  */
 
-#include "ZslProcessorInterface.h"
+package android.hardware.camera2;
 
-namespace android {
-namespace camera2 {
-
-status_t ZslProcessorInterface::disconnect() {
-    return OK;
-}
-
-}; //namespace camera2
-}; //namespace android
-
+/** @hide */
+parcelable CaptureRequest cpp_header "camera/camera2/CaptureRequest.h";
diff --git a/camera/aidl/android/hardware/camera2/ICameraDeviceCallbacks.aidl b/camera/aidl/android/hardware/camera2/ICameraDeviceCallbacks.aidl
new file mode 100644
index 0000000..755ec8e
--- /dev/null
+++ b/camera/aidl/android/hardware/camera2/ICameraDeviceCallbacks.aidl
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.camera2;
+
+import android.hardware.camera2.impl.CameraMetadataNative;
+import android.hardware.camera2.impl.CaptureResultExtras;
+
+/** @hide */
+interface ICameraDeviceCallbacks
+{
+    // Error codes for onDeviceError
+    const int ERROR_CAMERA_INVALID_ERROR = -1; // To indicate all invalid error codes
+    const int ERROR_CAMERA_DISCONNECTED = 0;
+    const int ERROR_CAMERA_DEVICE = 1;
+    const int ERROR_CAMERA_SERVICE = 2;
+    const int ERROR_CAMERA_REQUEST = 3;
+    const int ERROR_CAMERA_RESULT = 4;
+    const int ERROR_CAMERA_BUFFER = 5;
+
+    oneway void onDeviceError(int errorCode, in CaptureResultExtras resultExtras);
+    oneway void onDeviceIdle();
+    oneway void onCaptureStarted(in CaptureResultExtras resultExtras, long timestamp);
+    oneway void onResultReceived(in CameraMetadataNative result,
+                                 in CaptureResultExtras resultExtras);
+    oneway void onPrepared(int streamId);
+
+    /**
+     * Repeating request encountered an error and was stopped.
+     *
+     * @param lastFrameNumber Frame number of the last frame of the streaming request.
+     */
+    oneway void onRepeatingRequestError(in long lastFrameNumber);
+}
diff --git a/camera/aidl/android/hardware/camera2/ICameraDeviceUser.aidl b/camera/aidl/android/hardware/camera2/ICameraDeviceUser.aidl
new file mode 100644
index 0000000..1e8744b
--- /dev/null
+++ b/camera/aidl/android/hardware/camera2/ICameraDeviceUser.aidl
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.camera2;
+
+import android.hardware.camera2.CaptureRequest;
+import android.hardware.camera2.impl.CameraMetadataNative;
+import android.hardware.camera2.params.OutputConfiguration;
+import android.hardware.camera2.utils.SubmitInfo;
+import android.view.Surface;
+
+/** @hide */
+interface ICameraDeviceUser
+{
+    void disconnect();
+
+    const int NO_IN_FLIGHT_REPEATING_FRAMES = -1;
+
+    SubmitInfo submitRequest(in CaptureRequest request, boolean streaming);
+    SubmitInfo submitRequestList(in CaptureRequest[] requestList, boolean streaming);
+
+    /**
+     * Cancel the repeating request specified by requestId
+     * Returns the frame number of the last frame that will be produced from this
+     * repeating request, or NO_IN_FLIGHT_REPEATING_FRAMES if no frames were produced
+     * by this repeating request.
+     *
+     * Repeating request may be stopped by camera device due to an error. Canceling a stopped
+     * repeating request will trigger ERROR_ILLEGAL_ARGUMENT.
+     */
+    long cancelRequest(int requestId);
+
+    /**
+     * Begin the device configuration.
+     *
+     * <p>
+     * beginConfigure must be called before any call to deleteStream, createStream,
+     * or endConfigure.  It is not valid to call this when the device is not idle.
+     * <p>
+     */
+    void beginConfigure();
+
+    /**
+     * End the device configuration.
+     *
+     * <p>
+     * endConfigure must be called after stream configuration is complete (i.e. after
+     * a call to beginConfigure and subsequent createStream/deleteStream calls).  This
+     * must be called before any requests can be submitted.
+     * <p>
+     */
+    void endConfigure(boolean isConstrainedHighSpeed);
+
+    void deleteStream(int streamId);
+
+    /**
+     * Create an output stream
+     *
+     * <p>Create an output stream based on the given output configuration</p>
+     *
+     * @param outputConfiguration size, format, and other parameters for the stream
+     * @return new stream ID
+     */
+    int createStream(in OutputConfiguration outputConfiguration);
+
+    /**
+     * Create an input stream
+     *
+     * <p>Create an input stream of width, height, and format</p>
+     *
+     * @param width Width of the input buffers
+     * @param height Height of the input buffers
+     * @param format Format of the input buffers. One of HAL_PIXEL_FORMAT_*.
+     *
+     * @return new stream ID
+     */
+    int createInputStream(int width, int height, int format);
+
+    /**
+     * Get the surface of the input stream.
+     *
+     * <p>It's valid to call this method only after a stream configuration is completed
+     * successfully and the stream configuration includes a input stream.</p>
+     *
+     * @param surface An output argument for the surface of the input stream buffer queue.
+     */
+    Surface getInputSurface();
+
+    // Keep in sync with public API in
+    // frameworks/base/core/java/android/hardware/camera2/CameraDevice.java
+    const int TEMPLATE_PREVIEW = 1;
+    const int TEMPLATE_STILL_CAPTURE = 2;
+    const int TEMPLATE_RECORD = 3;
+    const int TEMPLATE_VIDEO_SNAPSHOT = 4;
+    const int TEMPLATE_ZERO_SHUTTER_LAG = 5;
+    const int TEMPLATE_MANUAL = 6;
+
+    CameraMetadataNative createDefaultRequest(int templateId);
+
+    CameraMetadataNative getCameraInfo();
+
+    void waitUntilIdle();
+
+    long flush();
+
+    void prepare(int streamId);
+
+    void tearDown(int streamId);
+
+    void prepare2(int maxCount, int streamId);
+}
diff --git a/services/camera/libcameraservice/api1/client2/ZslProcessorInterface.cpp b/camera/aidl/android/hardware/camera2/impl/CameraMetadataNative.aidl
similarity index 69%
copy from services/camera/libcameraservice/api1/client2/ZslProcessorInterface.cpp
copy to camera/aidl/android/hardware/camera2/impl/CameraMetadataNative.aidl
index 9efeaba..507f575 100644
--- a/services/camera/libcameraservice/api1/client2/ZslProcessorInterface.cpp
+++ b/camera/aidl/android/hardware/camera2/impl/CameraMetadataNative.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2014 The Android Open Source Project
+ * Copyright (C) 2013 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,15 +14,7 @@
  * limitations under the License.
  */
 
-#include "ZslProcessorInterface.h"
+package android.hardware.camera2.impl;
 
-namespace android {
-namespace camera2 {
-
-status_t ZslProcessorInterface::disconnect() {
-    return OK;
-}
-
-}; //namespace camera2
-}; //namespace android
-
+/** @hide */
+parcelable CameraMetadataNative cpp_header "camera/CameraMetadata.h";
diff --git a/services/camera/libcameraservice/api1/client2/ZslProcessorInterface.cpp b/camera/aidl/android/hardware/camera2/impl/CaptureResultExtras.aidl
similarity index 76%
rename from services/camera/libcameraservice/api1/client2/ZslProcessorInterface.cpp
rename to camera/aidl/android/hardware/camera2/impl/CaptureResultExtras.aidl
index 9efeaba..5f47eda 100644
--- a/services/camera/libcameraservice/api1/client2/ZslProcessorInterface.cpp
+++ b/camera/aidl/android/hardware/camera2/impl/CaptureResultExtras.aidl
@@ -14,15 +14,7 @@
  * limitations under the License.
  */
 
-#include "ZslProcessorInterface.h"
+package android.hardware.camera2.impl;
 
-namespace android {
-namespace camera2 {
-
-status_t ZslProcessorInterface::disconnect() {
-    return OK;
-}
-
-}; //namespace camera2
-}; //namespace android
-
+/** @hide */
+parcelable CaptureResultExtras cpp_header "camera/CaptureResult.h";
diff --git a/services/camera/libcameraservice/api1/client2/ZslProcessorInterface.cpp b/camera/aidl/android/hardware/camera2/params/OutputConfiguration.aidl
similarity index 69%
copy from services/camera/libcameraservice/api1/client2/ZslProcessorInterface.cpp
copy to camera/aidl/android/hardware/camera2/params/OutputConfiguration.aidl
index 9efeaba..a8ad832 100644
--- a/services/camera/libcameraservice/api1/client2/ZslProcessorInterface.cpp
+++ b/camera/aidl/android/hardware/camera2/params/OutputConfiguration.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2014 The Android Open Source Project
+ * Copyright (C) 2015 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,15 +14,7 @@
  * limitations under the License.
  */
 
-#include "ZslProcessorInterface.h"
+package android.hardware.camera2.params;
 
-namespace android {
-namespace camera2 {
-
-status_t ZslProcessorInterface::disconnect() {
-    return OK;
-}
-
-}; //namespace camera2
-}; //namespace android
-
+/** @hide */
+parcelable OutputConfiguration cpp_header "camera/camera2/OutputConfiguration.h";
diff --git a/services/camera/libcameraservice/api1/client2/ZslProcessorInterface.cpp b/camera/aidl/android/hardware/camera2/params/VendorTagDescriptor.aidl
similarity index 69%
copy from services/camera/libcameraservice/api1/client2/ZslProcessorInterface.cpp
copy to camera/aidl/android/hardware/camera2/params/VendorTagDescriptor.aidl
index 9efeaba..9ee4263 100644
--- a/services/camera/libcameraservice/api1/client2/ZslProcessorInterface.cpp
+++ b/camera/aidl/android/hardware/camera2/params/VendorTagDescriptor.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2014 The Android Open Source Project
+ * Copyright (C) 2016 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,15 +14,7 @@
  * limitations under the License.
  */
 
-#include "ZslProcessorInterface.h"
+package android.hardware.camera2.params;
 
-namespace android {
-namespace camera2 {
-
-status_t ZslProcessorInterface::disconnect() {
-    return OK;
-}
-
-}; //namespace camera2
-}; //namespace android
-
+/** @hide */
+parcelable VendorTagDescriptor cpp_header "camera/VendorTagDescriptor.h";
diff --git a/services/camera/libcameraservice/api1/client2/ZslProcessorInterface.cpp b/camera/aidl/android/hardware/camera2/utils/SubmitInfo.aidl
similarity index 69%
copy from services/camera/libcameraservice/api1/client2/ZslProcessorInterface.cpp
copy to camera/aidl/android/hardware/camera2/utils/SubmitInfo.aidl
index 9efeaba..57531ad 100644
--- a/services/camera/libcameraservice/api1/client2/ZslProcessorInterface.cpp
+++ b/camera/aidl/android/hardware/camera2/utils/SubmitInfo.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2014 The Android Open Source Project
+ * Copyright (C) 2015 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,15 +14,7 @@
  * limitations under the License.
  */
 
-#include "ZslProcessorInterface.h"
+package android.hardware.camera2.utils;
 
-namespace android {
-namespace camera2 {
-
-status_t ZslProcessorInterface::disconnect() {
-    return OK;
-}
-
-}; //namespace camera2
-}; //namespace android
-
+/** @hide */
+parcelable SubmitInfo cpp_header "camera/camera2/SubmitInfo.h";
diff --git a/camera/camera2/CaptureRequest.cpp b/camera/camera2/CaptureRequest.cpp
index 4217bc6..fb43708 100644
--- a/camera/camera2/CaptureRequest.cpp
+++ b/camera/camera2/CaptureRequest.cpp
@@ -25,8 +25,10 @@
 #include <gui/Surface.h>
 
 namespace android {
+namespace hardware {
+namespace camera2 {
 
-status_t CaptureRequest::readFromParcel(Parcel* parcel) {
+status_t CaptureRequest::readFromParcel(const Parcel* parcel) {
     if (parcel == NULL) {
         ALOGE("%s: Null parcel", __FUNCTION__);
         return BAD_VALUE;
@@ -130,4 +132,6 @@
     return OK;
 }
 
-}; // namespace android
+} // namespace camera2
+} // namespace hardware
+} // namespace android
diff --git a/camera/camera2/ICameraDeviceCallbacks.cpp b/camera/camera2/ICameraDeviceCallbacks.cpp
deleted file mode 100644
index f599879..0000000
--- a/camera/camera2/ICameraDeviceCallbacks.cpp
+++ /dev/null
@@ -1,190 +0,0 @@
-/*
-**
-** Copyright 2013, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-//#define LOG_NDEBUG 0
-#define LOG_TAG "ICameraDeviceCallbacks"
-#include <utils/Log.h>
-#include <stdint.h>
-#include <sys/types.h>
-
-#include <binder/Parcel.h>
-#include <gui/IGraphicBufferProducer.h>
-#include <gui/Surface.h>
-#include <utils/Mutex.h>
-
-#include <camera/camera2/ICameraDeviceCallbacks.h>
-#include "camera/CameraMetadata.h"
-#include "camera/CaptureResult.h"
-
-namespace android {
-
-enum {
-    CAMERA_ERROR = IBinder::FIRST_CALL_TRANSACTION,
-    CAMERA_IDLE,
-    CAPTURE_STARTED,
-    RESULT_RECEIVED,
-    PREPARED
-};
-
-class BpCameraDeviceCallbacks: public BpInterface<ICameraDeviceCallbacks>
-{
-public:
-    BpCameraDeviceCallbacks(const sp<IBinder>& impl)
-        : BpInterface<ICameraDeviceCallbacks>(impl)
-    {
-    }
-
-    void onDeviceError(CameraErrorCode errorCode, const CaptureResultExtras& resultExtras)
-    {
-        ALOGV("onDeviceError");
-        Parcel data, reply;
-        data.writeInterfaceToken(ICameraDeviceCallbacks::getInterfaceDescriptor());
-        data.writeInt32(static_cast<int32_t>(errorCode));
-        data.writeInt32(1); // to mark presence of CaptureResultExtras object
-        resultExtras.writeToParcel(&data);
-        remote()->transact(CAMERA_ERROR, data, &reply, IBinder::FLAG_ONEWAY);
-        data.writeNoException();
-    }
-
-    void onDeviceIdle()
-    {
-        ALOGV("onDeviceIdle");
-        Parcel data, reply;
-        data.writeInterfaceToken(ICameraDeviceCallbacks::getInterfaceDescriptor());
-        remote()->transact(CAMERA_IDLE, data, &reply, IBinder::FLAG_ONEWAY);
-        data.writeNoException();
-    }
-
-    void onCaptureStarted(const CaptureResultExtras& result, int64_t timestamp)
-    {
-        ALOGV("onCaptureStarted");
-        Parcel data, reply;
-        data.writeInterfaceToken(ICameraDeviceCallbacks::getInterfaceDescriptor());
-        data.writeInt32(1); // to mark presence of CaptureResultExtras object
-        result.writeToParcel(&data);
-        data.writeInt64(timestamp);
-        remote()->transact(CAPTURE_STARTED, data, &reply, IBinder::FLAG_ONEWAY);
-        data.writeNoException();
-    }
-
-    void onResultReceived(const CameraMetadata& metadata,
-            const CaptureResultExtras& resultExtras) {
-        ALOGV("onResultReceived");
-        Parcel data, reply;
-        data.writeInterfaceToken(ICameraDeviceCallbacks::getInterfaceDescriptor());
-        data.writeInt32(1); // to mark presence of metadata object
-        metadata.writeToParcel(&data);
-        data.writeInt32(1); // to mark presence of CaptureResult object
-        resultExtras.writeToParcel(&data);
-        remote()->transact(RESULT_RECEIVED, data, &reply, IBinder::FLAG_ONEWAY);
-        data.writeNoException();
-    }
-
-    void onPrepared(int streamId)
-    {
-        ALOGV("onPrepared");
-        Parcel data, reply;
-        data.writeInterfaceToken(ICameraDeviceCallbacks::getInterfaceDescriptor());
-        data.writeInt32(streamId);
-        remote()->transact(PREPARED, data, &reply, IBinder::FLAG_ONEWAY);
-        data.writeNoException();
-    }
-
-};
-
-IMPLEMENT_META_INTERFACE(CameraDeviceCallbacks,
-                         "android.hardware.camera2.ICameraDeviceCallbacks");
-
-// ----------------------------------------------------------------------
-
-status_t BnCameraDeviceCallbacks::onTransact(
-    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
-{
-    ALOGV("onTransact - code = %d", code);
-    switch(code) {
-        case CAMERA_ERROR: {
-            ALOGV("onDeviceError");
-            CHECK_INTERFACE(ICameraDeviceCallbacks, data, reply);
-            CameraErrorCode errorCode =
-                    static_cast<CameraErrorCode>(data.readInt32());
-            CaptureResultExtras resultExtras;
-            if (data.readInt32() != 0) {
-                resultExtras.readFromParcel(const_cast<Parcel*>(&data));
-            } else {
-                ALOGE("No CaptureResultExtras object is present!");
-            }
-            onDeviceError(errorCode, resultExtras);
-            data.readExceptionCode();
-            return NO_ERROR;
-        } break;
-        case CAMERA_IDLE: {
-            ALOGV("onDeviceIdle");
-            CHECK_INTERFACE(ICameraDeviceCallbacks, data, reply);
-            onDeviceIdle();
-            data.readExceptionCode();
-            return NO_ERROR;
-        } break;
-        case CAPTURE_STARTED: {
-            ALOGV("onCaptureStarted");
-            CHECK_INTERFACE(ICameraDeviceCallbacks, data, reply);
-            CaptureResultExtras result;
-            if (data.readInt32() != 0) {
-                result.readFromParcel(const_cast<Parcel*>(&data));
-            } else {
-                ALOGE("No CaptureResultExtras object is present in result!");
-            }
-            int64_t timestamp = data.readInt64();
-            onCaptureStarted(result, timestamp);
-            data.readExceptionCode();
-            return NO_ERROR;
-        } break;
-        case RESULT_RECEIVED: {
-            ALOGV("onResultReceived");
-            CHECK_INTERFACE(ICameraDeviceCallbacks, data, reply);
-            CameraMetadata metadata;
-            if (data.readInt32() != 0) {
-                metadata.readFromParcel(const_cast<Parcel*>(&data));
-            } else {
-                ALOGW("No metadata object is present in result");
-            }
-            CaptureResultExtras resultExtras;
-            if (data.readInt32() != 0) {
-                resultExtras.readFromParcel(const_cast<Parcel*>(&data));
-            } else {
-                ALOGW("No capture result extras object is present in result");
-            }
-            onResultReceived(metadata, resultExtras);
-            data.readExceptionCode();
-            return NO_ERROR;
-        } break;
-        case PREPARED: {
-            ALOGV("onPrepared");
-            CHECK_INTERFACE(ICameraDeviceCallbacks, data, reply);
-            CaptureResultExtras result;
-            int streamId = data.readInt32();
-            onPrepared(streamId);
-            data.readExceptionCode();
-            return NO_ERROR;
-        } break;
-        default:
-            return BBinder::onTransact(code, data, reply, flags);
-    }
-}
-
-// ----------------------------------------------------------------------------
-
-}; // namespace android
diff --git a/camera/camera2/ICameraDeviceUser.cpp b/camera/camera2/ICameraDeviceUser.cpp
deleted file mode 100644
index 2a9fd2b..0000000
--- a/camera/camera2/ICameraDeviceUser.cpp
+++ /dev/null
@@ -1,626 +0,0 @@
-/*
-**
-** Copyright 2013, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-// #define LOG_NDEBUG 0
-#define LOG_TAG "ICameraDeviceUser"
-#include <utils/Log.h>
-#include <stdint.h>
-#include <sys/types.h>
-#include <binder/Parcel.h>
-#include <camera/camera2/ICameraDeviceUser.h>
-#include <gui/IGraphicBufferProducer.h>
-#include <gui/Surface.h>
-#include <camera/CameraMetadata.h>
-#include <camera/camera2/CaptureRequest.h>
-#include <camera/camera2/OutputConfiguration.h>
-
-namespace android {
-
-typedef Parcel::WritableBlob WritableBlob;
-typedef Parcel::ReadableBlob ReadableBlob;
-
-enum {
-    DISCONNECT = IBinder::FIRST_CALL_TRANSACTION,
-    SUBMIT_REQUEST,
-    SUBMIT_REQUEST_LIST,
-    CANCEL_REQUEST,
-    BEGIN_CONFIGURE,
-    END_CONFIGURE,
-    DELETE_STREAM,
-    CREATE_STREAM,
-    CREATE_INPUT_STREAM,
-    GET_INPUT_SURFACE,
-    CREATE_DEFAULT_REQUEST,
-    GET_CAMERA_INFO,
-    WAIT_UNTIL_IDLE,
-    FLUSH,
-    PREPARE,
-    TEAR_DOWN,
-    PREPARE2
-};
-
-namespace {
-    // Read empty strings without printing a false error message.
-    String16 readMaybeEmptyString16(const Parcel& parcel) {
-        size_t len;
-        const char16_t* str = parcel.readString16Inplace(&len);
-        if (str != NULL) {
-            return String16(str, len);
-        } else {
-            return String16();
-        }
-    }
-};
-
-class BpCameraDeviceUser : public BpInterface<ICameraDeviceUser>
-{
-public:
-    BpCameraDeviceUser(const sp<IBinder>& impl)
-        : BpInterface<ICameraDeviceUser>(impl)
-    {
-    }
-
-    // disconnect from camera service
-    void disconnect()
-    {
-        ALOGV("disconnect");
-        Parcel data, reply;
-        data.writeInterfaceToken(ICameraDeviceUser::getInterfaceDescriptor());
-        remote()->transact(DISCONNECT, data, &reply);
-        reply.readExceptionCode();
-    }
-
-    virtual int submitRequest(sp<CaptureRequest> request, bool repeating,
-                              int64_t *lastFrameNumber)
-    {
-        Parcel data, reply;
-        data.writeInterfaceToken(ICameraDeviceUser::getInterfaceDescriptor());
-
-        // arg0 = CaptureRequest
-        if (request != 0) {
-            data.writeInt32(1);
-            request->writeToParcel(&data);
-        } else {
-            data.writeInt32(0);
-        }
-
-        // arg1 = streaming (bool)
-        data.writeInt32(repeating);
-
-        remote()->transact(SUBMIT_REQUEST, data, &reply);
-
-        reply.readExceptionCode();
-        status_t res = reply.readInt32();
-
-        status_t resFrameNumber = BAD_VALUE;
-        if (reply.readInt32() != 0) {
-            if (lastFrameNumber != NULL) {
-                resFrameNumber = reply.readInt64(lastFrameNumber);
-            }
-        }
-
-        if (res < 0 || (resFrameNumber != NO_ERROR)) {
-            res = FAILED_TRANSACTION;
-        }
-        return res;
-    }
-
-    virtual int submitRequestList(List<sp<CaptureRequest> > requestList, bool repeating,
-                                  int64_t *lastFrameNumber)
-    {
-        Parcel data, reply;
-        data.writeInterfaceToken(ICameraDeviceUser::getInterfaceDescriptor());
-
-        data.writeInt32(requestList.size());
-
-        for (List<sp<CaptureRequest> >::iterator it = requestList.begin();
-                it != requestList.end(); ++it) {
-            sp<CaptureRequest> request = *it;
-            if (request != 0) {
-                data.writeInt32(1);
-                if (request->writeToParcel(&data) != OK) {
-                    return BAD_VALUE;
-                }
-            } else {
-                data.writeInt32(0);
-            }
-        }
-
-        data.writeInt32(repeating);
-
-        remote()->transact(SUBMIT_REQUEST_LIST, data, &reply);
-
-        reply.readExceptionCode();
-        status_t res = reply.readInt32();
-
-        status_t resFrameNumber = BAD_VALUE;
-        if (reply.readInt32() != 0) {
-            if (lastFrameNumber != NULL) {
-                resFrameNumber = reply.readInt64(lastFrameNumber);
-            }
-        }
-        if (res < 0 || (resFrameNumber != NO_ERROR)) {
-            res = FAILED_TRANSACTION;
-        }
-        return res;
-    }
-
-    virtual status_t cancelRequest(int requestId, int64_t *lastFrameNumber)
-    {
-        Parcel data, reply;
-        data.writeInterfaceToken(ICameraDeviceUser::getInterfaceDescriptor());
-        data.writeInt32(requestId);
-
-        remote()->transact(CANCEL_REQUEST, data, &reply);
-
-        reply.readExceptionCode();
-        status_t res = reply.readInt32();
-
-        status_t resFrameNumber = BAD_VALUE;
-        if (reply.readInt32() != 0) {
-            if (lastFrameNumber != NULL) {
-                resFrameNumber = reply.readInt64(lastFrameNumber);
-            }
-        }
-        if ((res != NO_ERROR) || (resFrameNumber != NO_ERROR)) {
-            res = FAILED_TRANSACTION;
-        }
-        return res;
-    }
-
-    virtual status_t beginConfigure()
-    {
-        ALOGV("beginConfigure");
-        Parcel data, reply;
-        data.writeInterfaceToken(ICameraDeviceUser::getInterfaceDescriptor());
-        remote()->transact(BEGIN_CONFIGURE, data, &reply);
-        reply.readExceptionCode();
-        return reply.readInt32();
-    }
-
-    virtual status_t endConfigure(bool isConstrainedHighSpeed)
-    {
-        ALOGV("endConfigure");
-        Parcel data, reply;
-        data.writeInterfaceToken(ICameraDeviceUser::getInterfaceDescriptor());
-        data.writeInt32(isConstrainedHighSpeed);
-
-        remote()->transact(END_CONFIGURE, data, &reply);
-        reply.readExceptionCode();
-        return reply.readInt32();
-    }
-
-    virtual status_t deleteStream(int streamId)
-    {
-        Parcel data, reply;
-        data.writeInterfaceToken(ICameraDeviceUser::getInterfaceDescriptor());
-        data.writeInt32(streamId);
-
-        remote()->transact(DELETE_STREAM, data, &reply);
-
-        reply.readExceptionCode();
-        return reply.readInt32();
-    }
-
-    virtual status_t createStream(const OutputConfiguration& outputConfiguration)
-    {
-        Parcel data, reply;
-        data.writeInterfaceToken(ICameraDeviceUser::getInterfaceDescriptor());
-        if (outputConfiguration.getGraphicBufferProducer() != NULL) {
-            data.writeInt32(1); // marker that OutputConfiguration is not null. Mimic aidl behavior
-            outputConfiguration.writeToParcel(data);
-        } else {
-            data.writeInt32(0);
-        }
-        remote()->transact(CREATE_STREAM, data, &reply);
-
-        reply.readExceptionCode();
-        return reply.readInt32();
-    }
-
-    virtual status_t createInputStream(int width, int height, int format)
-    {
-        Parcel data, reply;
-        data.writeInterfaceToken(ICameraDeviceUser::getInterfaceDescriptor());
-        data.writeInt32(width);
-        data.writeInt32(height);
-        data.writeInt32(format);
-
-        remote()->transact(CREATE_INPUT_STREAM, data, &reply);
-
-        reply.readExceptionCode();
-        return reply.readInt32();
-    }
-
-    // get the buffer producer of the input stream
-    virtual status_t getInputBufferProducer(
-            sp<IGraphicBufferProducer> *producer) {
-        if (producer == NULL) {
-            return BAD_VALUE;
-        }
-
-        Parcel data, reply;
-        data.writeInterfaceToken(ICameraDeviceUser::getInterfaceDescriptor());
-
-        remote()->transact(GET_INPUT_SURFACE, data, &reply);
-
-        reply.readExceptionCode();
-        status_t result = reply.readInt32() ;
-        if (result != OK) {
-            return result;
-        }
-
-        sp<IGraphicBufferProducer> bp = NULL;
-        if (reply.readInt32() != 0) {
-            String16 name = readMaybeEmptyString16(reply);
-            bp = interface_cast<IGraphicBufferProducer>(
-                    reply.readStrongBinder());
-        }
-
-        *producer = bp;
-
-        return *producer == NULL ? INVALID_OPERATION : OK;
-    }
-
-    // Create a request object from a template.
-    virtual status_t createDefaultRequest(int templateId,
-                                          /*out*/
-                                          CameraMetadata* request)
-    {
-        Parcel data, reply;
-        data.writeInterfaceToken(ICameraDeviceUser::getInterfaceDescriptor());
-        data.writeInt32(templateId);
-        remote()->transact(CREATE_DEFAULT_REQUEST, data, &reply);
-
-        reply.readExceptionCode();
-        status_t result = reply.readInt32();
-
-        CameraMetadata out;
-        if (reply.readInt32() != 0) {
-            out.readFromParcel(&reply);
-        }
-
-        if (request != NULL) {
-            request->swap(out);
-        }
-        return result;
-    }
-
-
-    virtual status_t getCameraInfo(CameraMetadata* info)
-    {
-        Parcel data, reply;
-        data.writeInterfaceToken(ICameraDeviceUser::getInterfaceDescriptor());
-        remote()->transact(GET_CAMERA_INFO, data, &reply);
-
-        reply.readExceptionCode();
-        status_t result = reply.readInt32();
-
-        CameraMetadata out;
-        if (reply.readInt32() != 0) {
-            out.readFromParcel(&reply);
-        }
-
-        if (info != NULL) {
-            info->swap(out);
-        }
-
-        return result;
-    }
-
-    virtual status_t waitUntilIdle()
-    {
-        ALOGV("waitUntilIdle");
-        Parcel data, reply;
-        data.writeInterfaceToken(ICameraDeviceUser::getInterfaceDescriptor());
-        remote()->transact(WAIT_UNTIL_IDLE, data, &reply);
-        reply.readExceptionCode();
-        return reply.readInt32();
-    }
-
-    virtual status_t flush(int64_t *lastFrameNumber)
-    {
-        ALOGV("flush");
-        Parcel data, reply;
-        data.writeInterfaceToken(ICameraDeviceUser::getInterfaceDescriptor());
-        remote()->transact(FLUSH, data, &reply);
-        reply.readExceptionCode();
-        status_t res = reply.readInt32();
-
-        status_t resFrameNumber = BAD_VALUE;
-        if (reply.readInt32() != 0) {
-            if (lastFrameNumber != NULL) {
-                resFrameNumber = reply.readInt64(lastFrameNumber);
-            }
-        }
-        if ((res != NO_ERROR) || (resFrameNumber != NO_ERROR)) {
-            res = FAILED_TRANSACTION;
-        }
-        return res;
-    }
-
-    virtual status_t prepare(int streamId)
-    {
-        ALOGV("prepare");
-        Parcel data, reply;
-
-        data.writeInterfaceToken(ICameraDeviceUser::getInterfaceDescriptor());
-        data.writeInt32(streamId);
-
-        remote()->transact(PREPARE, data, &reply);
-
-        reply.readExceptionCode();
-        return reply.readInt32();
-    }
-
-    virtual status_t prepare2(int maxCount, int streamId)
-    {
-        ALOGV("prepare2");
-        Parcel data, reply;
-
-        data.writeInterfaceToken(ICameraDeviceUser::getInterfaceDescriptor());
-        data.writeInt32(maxCount);
-        data.writeInt32(streamId);
-
-        remote()->transact(PREPARE2, data, &reply);
-
-        reply.readExceptionCode();
-        return reply.readInt32();
-    }
-
-    virtual status_t tearDown(int streamId)
-    {
-        ALOGV("tearDown");
-        Parcel data, reply;
-
-        data.writeInterfaceToken(ICameraDeviceUser::getInterfaceDescriptor());
-        data.writeInt32(streamId);
-
-        remote()->transact(TEAR_DOWN, data, &reply);
-
-        reply.readExceptionCode();
-        return reply.readInt32();
-    }
-
-private:
-
-
-};
-
-IMPLEMENT_META_INTERFACE(CameraDeviceUser,
-                         "android.hardware.camera2.ICameraDeviceUser");
-
-// ----------------------------------------------------------------------
-
-status_t BnCameraDeviceUser::onTransact(
-    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
-{
-    switch(code) {
-        case DISCONNECT: {
-            ALOGV("DISCONNECT");
-            CHECK_INTERFACE(ICameraDeviceUser, data, reply);
-            disconnect();
-            reply->writeNoException();
-            return NO_ERROR;
-        } break;
-        case SUBMIT_REQUEST: {
-            CHECK_INTERFACE(ICameraDeviceUser, data, reply);
-
-            // arg0 = request
-            sp<CaptureRequest> request;
-            if (data.readInt32() != 0) {
-                request = new CaptureRequest();
-                request->readFromParcel(const_cast<Parcel*>(&data));
-            }
-
-            // arg1 = streaming (bool)
-            bool repeating = data.readInt32();
-
-            // return code: requestId (int32)
-            reply->writeNoException();
-            int64_t lastFrameNumber = -1;
-            reply->writeInt32(submitRequest(request, repeating, &lastFrameNumber));
-            reply->writeInt32(1);
-            reply->writeInt64(lastFrameNumber);
-
-            return NO_ERROR;
-        } break;
-        case SUBMIT_REQUEST_LIST: {
-            CHECK_INTERFACE(ICameraDeviceUser, data, reply);
-
-            List<sp<CaptureRequest> > requestList;
-            int requestListSize = data.readInt32();
-            for (int i = 0; i < requestListSize; i++) {
-                if (data.readInt32() != 0) {
-                    sp<CaptureRequest> request = new CaptureRequest();
-                    if (request->readFromParcel(const_cast<Parcel*>(&data)) != OK) {
-                        return BAD_VALUE;
-                    }
-                    requestList.push_back(request);
-                } else {
-                    sp<CaptureRequest> request = 0;
-                    requestList.push_back(request);
-                    ALOGE("A request is missing. Sending in null request.");
-                }
-            }
-
-            bool repeating = data.readInt32();
-
-            reply->writeNoException();
-            int64_t lastFrameNumber = -1;
-            reply->writeInt32(submitRequestList(requestList, repeating, &lastFrameNumber));
-            reply->writeInt32(1);
-            reply->writeInt64(lastFrameNumber);
-
-            return NO_ERROR;
-        } break;
-        case CANCEL_REQUEST: {
-            CHECK_INTERFACE(ICameraDeviceUser, data, reply);
-            int requestId = data.readInt32();
-            reply->writeNoException();
-            int64_t lastFrameNumber = -1;
-            reply->writeInt32(cancelRequest(requestId, &lastFrameNumber));
-            reply->writeInt32(1);
-            reply->writeInt64(lastFrameNumber);
-            return NO_ERROR;
-        } break;
-        case DELETE_STREAM: {
-            CHECK_INTERFACE(ICameraDeviceUser, data, reply);
-            int streamId = data.readInt32();
-            reply->writeNoException();
-            reply->writeInt32(deleteStream(streamId));
-            return NO_ERROR;
-        } break;
-        case CREATE_STREAM: {
-            CHECK_INTERFACE(ICameraDeviceUser, data, reply);
-
-            status_t ret = BAD_VALUE;
-            if (data.readInt32() != 0) {
-                OutputConfiguration outputConfiguration(data);
-                ret = createStream(outputConfiguration);
-            } else {
-                ALOGE("%s: cannot take an empty OutputConfiguration", __FUNCTION__);
-            }
-
-            reply->writeNoException();
-            ALOGV("%s: CREATE_STREAM: write noException", __FUNCTION__);
-            reply->writeInt32(ret);
-            ALOGV("%s: CREATE_STREAM: write ret = %d", __FUNCTION__, ret);
-
-            return NO_ERROR;
-        } break;
-        case CREATE_INPUT_STREAM: {
-            CHECK_INTERFACE(ICameraDeviceUser, data, reply);
-            int width, height, format;
-
-            width = data.readInt32();
-            height = data.readInt32();
-            format = data.readInt32();
-            status_t ret = createInputStream(width, height, format);
-
-            reply->writeNoException();
-            reply->writeInt32(ret);
-            return NO_ERROR;
-
-        } break;
-        case GET_INPUT_SURFACE: {
-            CHECK_INTERFACE(ICameraDeviceUser, data, reply);
-
-            sp<IGraphicBufferProducer> bp;
-            status_t ret = getInputBufferProducer(&bp);
-            sp<IBinder> b(IInterface::asBinder(ret == OK ? bp : NULL));
-
-            reply->writeNoException();
-            reply->writeInt32(ret);
-            reply->writeInt32(1);
-            reply->writeString16(String16("camera input")); // name of surface
-            reply->writeStrongBinder(b);
-
-            return NO_ERROR;
-        } break;
-        case CREATE_DEFAULT_REQUEST: {
-            CHECK_INTERFACE(ICameraDeviceUser, data, reply);
-
-            int templateId = data.readInt32();
-
-            CameraMetadata request;
-            status_t ret;
-            ret = createDefaultRequest(templateId, &request);
-
-            reply->writeNoException();
-            reply->writeInt32(ret);
-
-            // out-variables are after exception and return value
-            reply->writeInt32(1); // to mark presence of metadata object
-            request.writeToParcel(const_cast<Parcel*>(reply));
-
-            return NO_ERROR;
-        } break;
-        case GET_CAMERA_INFO: {
-            CHECK_INTERFACE(ICameraDeviceUser, data, reply);
-
-            CameraMetadata info;
-            status_t ret;
-            ret = getCameraInfo(&info);
-
-            reply->writeNoException();
-            reply->writeInt32(ret);
-
-            // out-variables are after exception and return value
-            reply->writeInt32(1); // to mark presence of metadata object
-            info.writeToParcel(reply);
-
-            return NO_ERROR;
-        } break;
-        case WAIT_UNTIL_IDLE: {
-            CHECK_INTERFACE(ICameraDeviceUser, data, reply);
-            reply->writeNoException();
-            reply->writeInt32(waitUntilIdle());
-            return NO_ERROR;
-        } break;
-        case FLUSH: {
-            CHECK_INTERFACE(ICameraDeviceUser, data, reply);
-            reply->writeNoException();
-            int64_t lastFrameNumber = -1;
-            reply->writeInt32(flush(&lastFrameNumber));
-            reply->writeInt32(1);
-            reply->writeInt64(lastFrameNumber);
-            return NO_ERROR;
-        }
-        case BEGIN_CONFIGURE: {
-            CHECK_INTERFACE(ICameraDeviceUser, data, reply);
-            reply->writeNoException();
-            reply->writeInt32(beginConfigure());
-            return NO_ERROR;
-        } break;
-        case END_CONFIGURE: {
-            CHECK_INTERFACE(ICameraDeviceUser, data, reply);
-            bool isConstrainedHighSpeed = data.readInt32();
-            reply->writeNoException();
-            reply->writeInt32(endConfigure(isConstrainedHighSpeed));
-            return NO_ERROR;
-        } break;
-        case PREPARE: {
-            CHECK_INTERFACE(ICameraDeviceUser, data, reply);
-            int streamId = data.readInt32();
-            reply->writeNoException();
-            reply->writeInt32(prepare(streamId));
-            return NO_ERROR;
-        } break;
-        case TEAR_DOWN: {
-            CHECK_INTERFACE(ICameraDeviceUser, data, reply);
-            int streamId = data.readInt32();
-            reply->writeNoException();
-            reply->writeInt32(tearDown(streamId));
-            return NO_ERROR;
-        } break;
-        case PREPARE2: {
-            CHECK_INTERFACE(ICameraDeviceUser, data, reply);
-            int maxCount = data.readInt32();
-            int streamId = data.readInt32();
-            reply->writeNoException();
-            reply->writeInt32(prepare2(maxCount, streamId));
-            return NO_ERROR;
-        } break;
-        default:
-            return BBinder::onTransact(code, data, reply, flags);
-    }
-}
-
-// ----------------------------------------------------------------------------
-
-}; // namespace android
diff --git a/camera/camera2/OutputConfiguration.cpp b/camera/camera2/OutputConfiguration.cpp
index 20a23e0..3247d0d 100644
--- a/camera/camera2/OutputConfiguration.cpp
+++ b/camera/camera2/OutputConfiguration.cpp
@@ -16,26 +16,19 @@
 */
 
 #define LOG_TAG "OutputConfiguration"
+//#define LOG_NDEBUG 0
+
 #include <utils/Log.h>
 
 #include <camera/camera2/OutputConfiguration.h>
+#include <gui/Surface.h>
 #include <binder/Parcel.h>
 
 namespace android {
 
 
 const int OutputConfiguration::INVALID_ROTATION = -1;
-
-// Read empty strings without printing a false error message.
-String16 OutputConfiguration::readMaybeEmptyString16(const Parcel& parcel) {
-    size_t len;
-    const char16_t* str = parcel.readString16Inplace(&len);
-    if (str != NULL) {
-        return String16(str, len);
-    } else {
-        return String16();
-    }
-}
+const int OutputConfiguration::INVALID_SET_ID = -1;
 
 sp<IGraphicBufferProducer> OutputConfiguration::getGraphicBufferProducer() const {
     return mGbp;
@@ -45,40 +38,80 @@
     return mRotation;
 }
 
-OutputConfiguration::OutputConfiguration(const Parcel& parcel) {
-    status_t err;
+int OutputConfiguration::getSurfaceSetID() const {
+    return mSurfaceSetID;
+}
+
+OutputConfiguration::OutputConfiguration() :
+        mRotation(INVALID_ROTATION),
+        mSurfaceSetID(INVALID_SET_ID) {
+}
+
+OutputConfiguration::OutputConfiguration(const Parcel& parcel) :
+        mRotation(INVALID_ROTATION),
+        mSurfaceSetID(INVALID_SET_ID) {
+    readFromParcel(&parcel);
+}
+
+status_t OutputConfiguration::readFromParcel(const Parcel* parcel) {
+    status_t err = OK;
     int rotation = 0;
-    if ((err = parcel.readInt32(&rotation)) != OK) {
+
+    if (parcel == nullptr) return BAD_VALUE;
+
+    if ((err = parcel->readInt32(&rotation)) != OK) {
         ALOGE("%s: Failed to read rotation from parcel", __FUNCTION__);
-        mGbp = NULL;
-        mRotation = INVALID_ROTATION;
-        return;
+        return err;
     }
 
-    String16 name = readMaybeEmptyString16(parcel);
-    const sp<IGraphicBufferProducer>& gbp =
-            interface_cast<IGraphicBufferProducer>(parcel.readStrongBinder());
-    mGbp = gbp;
-    mRotation = rotation;
+    int setID = INVALID_SET_ID;
+    if ((err = parcel->readInt32(&setID)) != OK) {
+        ALOGE("%s: Failed to read surface set ID from parcel", __FUNCTION__);
+        return err;
+    }
 
-    ALOGV("%s: OutputConfiguration: bp = %p, name = %s", __FUNCTION__,
-          gbp.get(), String8(name).string());
+    view::Surface surfaceShim;
+    if ((err = surfaceShim.readFromParcel(parcel)) != OK) {
+        ALOGE("%s: Failed to read surface from parcel", __FUNCTION__);
+        return err;
+    }
+
+    mGbp = surfaceShim.graphicBufferProducer;
+    mRotation = rotation;
+    mSurfaceSetID = setID;
+
+    ALOGV("%s: OutputConfiguration: bp = %p, name = %s, rotation = %d, setId = %d", __FUNCTION__,
+            mGbp.get(), String8(surfaceShim.name).string(), mRotation, mSurfaceSetID);
+
+    return err;
 }
 
-OutputConfiguration::OutputConfiguration(sp<IGraphicBufferProducer>& gbp, int rotation) {
+OutputConfiguration::OutputConfiguration(sp<IGraphicBufferProducer>& gbp, int rotation,
+        int surfaceSetID) {
     mGbp = gbp;
     mRotation = rotation;
+    mSurfaceSetID = surfaceSetID;
 }
 
-status_t OutputConfiguration::writeToParcel(Parcel& parcel) const {
+status_t OutputConfiguration::writeToParcel(Parcel* parcel) const {
 
-    parcel.writeInt32(mRotation);
-    parcel.writeString16(String16("unknown_name")); // name of surface
-    sp<IBinder> b(IInterface::asBinder(mGbp));
-    parcel.writeStrongBinder(b);
+    if (parcel == nullptr) return BAD_VALUE;
+    status_t err = OK;
+
+    err = parcel->writeInt32(mRotation);
+    if (err != OK) return err;
+
+    err = parcel->writeInt32(mSurfaceSetID);
+    if (err != OK) return err;
+
+    view::Surface surfaceShim;
+    surfaceShim.name = String16("unknown_name"); // name of surface
+    surfaceShim.graphicBufferProducer = mGbp;
+
+    err = surfaceShim.writeToParcel(parcel);
+    if (err != OK) return err;
 
     return OK;
 }
 
 }; // namespace android
-
diff --git a/camera/camera2/SubmitInfo.cpp b/camera/camera2/SubmitInfo.cpp
new file mode 100644
index 0000000..d739c79
--- /dev/null
+++ b/camera/camera2/SubmitInfo.cpp
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+#include "camera/camera2/SubmitInfo.h"
+
+namespace android {
+namespace hardware {
+namespace camera2 {
+namespace utils {
+
+status_t SubmitInfo::writeToParcel(Parcel *parcel) const {
+    status_t res;
+    if (parcel == nullptr) return BAD_VALUE;
+
+    res = parcel->writeInt32(mRequestId);
+    if (res != OK) return res;
+
+    res = parcel->writeInt64(mLastFrameNumber);
+    return res;
+}
+
+status_t SubmitInfo::readFromParcel(const Parcel *parcel) {
+    status_t res;
+    if (parcel == nullptr) return BAD_VALUE;
+
+    res = parcel->readInt32(&mRequestId);
+    if (res != OK) return res;
+
+    res = parcel->readInt64(&mLastFrameNumber);
+    return res;
+}
+
+} // namespace utils
+} // namespace camera2
+} // namespace hardware
+} // namespace android
diff --git a/camera/cameraserver/Android.mk b/camera/cameraserver/Android.mk
new file mode 100644
index 0000000..7e36c5e
--- /dev/null
+++ b/camera/cameraserver/Android.mk
@@ -0,0 +1,36 @@
+# Copyright 2015 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+	main_cameraserver.cpp
+
+LOCAL_SHARED_LIBRARIES := \
+	libcameraservice \
+	libcutils \
+	libutils \
+	libbinder \
+	libcamera_client
+
+LOCAL_MODULE:= cameraserver
+LOCAL_32_BIT_ONLY := true
+
+LOCAL_CFLAGS += -Wall -Wextra -Werror -Wno-unused-parameter
+
+LOCAL_INIT_RC := cameraserver.rc
+
+include $(BUILD_EXECUTABLE)
diff --git a/camera/cameraserver/cameraserver.rc b/camera/cameraserver/cameraserver.rc
new file mode 100644
index 0000000..16d9da8
--- /dev/null
+++ b/camera/cameraserver/cameraserver.rc
@@ -0,0 +1,6 @@
+service cameraserver /system/bin/cameraserver
+    class main
+    user cameraserver
+    group audio camera drmrpc inet media mediadrm net_bt net_bt_admin net_bw_acct
+    ioprio rt 4
+    writepid /dev/cpuset/foreground/tasks
diff --git a/camera/cameraserver/main_cameraserver.cpp b/camera/cameraserver/main_cameraserver.cpp
new file mode 100644
index 0000000..f4be468
--- /dev/null
+++ b/camera/cameraserver/main_cameraserver.cpp
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "cameraserver"
+//#define LOG_NDEBUG 0
+
+// from LOCAL_C_INCLUDES
+#include "CameraService.h"
+
+using namespace android;
+
+int main(int argc __unused, char** argv __unused)
+{
+    signal(SIGPIPE, SIG_IGN);
+
+    sp<ProcessState> proc(ProcessState::self());
+    sp<IServiceManager> sm = defaultServiceManager();
+    ALOGI("ServiceManager: %p", sm.get());
+    CameraService::instantiate();
+    ProcessState::self()->startThreadPool();
+    IPCThreadState::self()->joinThreadPool();
+}
diff --git a/camera/ndk/Android.mk b/camera/ndk/Android.mk
new file mode 100644
index 0000000..40dbeef
--- /dev/null
+++ b/camera/ndk/Android.mk
@@ -0,0 +1,58 @@
+#
+# Copyright (C) 2015 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+LOCAL_PATH:= $(call my-dir)
+
+ifneq ($(TARGET_BUILD_PDK), true)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:=                  \
+    NdkCameraManager.cpp           \
+    NdkCameraMetadata.cpp          \
+    NdkCameraDevice.cpp            \
+    NdkCaptureRequest.cpp          \
+    NdkCameraCaptureSession.cpp    \
+    impl/ACameraManager.cpp        \
+    impl/ACameraMetadata.cpp       \
+    impl/ACameraDevice.cpp         \
+    impl/ACameraCaptureSession.cpp
+
+LOCAL_MODULE:= libcamera2ndk
+
+LOCAL_C_INCLUDES := \
+    frameworks/av/include/camera/ndk \
+    frameworks/av/include/ndk
+
+LOCAL_CFLAGS += -fvisibility=hidden -D EXPORT='__attribute__ ((visibility ("default")))'
+LOCAL_CFLAGS += -Wall -Wextra -Werror
+
+LOCAL_SHARED_LIBRARIES := \
+    libbinder \
+    liblog \
+    libgui \
+    libutils \
+    libandroid_runtime \
+    libcamera_client \
+    libstagefright_foundation \
+    libcutils \
+    libcamera_metadata
+
+LOCAL_CLANG := true
+
+include $(BUILD_SHARED_LIBRARY)
+
+endif
diff --git a/camera/ndk/NdkCameraCaptureSession.cpp b/camera/ndk/NdkCameraCaptureSession.cpp
new file mode 100644
index 0000000..d6eff24
--- /dev/null
+++ b/camera/ndk/NdkCameraCaptureSession.cpp
@@ -0,0 +1,137 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "NdkCameraCaptureSession"
+#define ATRACE_TAG ATRACE_TAG_CAMERA
+
+#include <utils/Log.h>
+#include <utils/Mutex.h>
+#include <utils/StrongPointer.h>
+#include <utils/Trace.h>
+
+#include "NdkCameraDevice.h"
+#include <NdkCaptureRequest.h>
+#include <NdkCameraCaptureSession.h>
+#include "impl/ACameraCaptureSession.h"
+
+using namespace android;
+
+EXPORT
+void ACameraCaptureSession_close(ACameraCaptureSession* session) {
+    ATRACE_CALL();
+    if (session != nullptr) {
+        session->closeByApp();
+    }
+    return;
+}
+
+EXPORT
+camera_status_t ACameraCaptureSession_getDevice(
+        ACameraCaptureSession* session, ACameraDevice **device) {
+    ATRACE_CALL();
+    if (session == nullptr || device == nullptr) {
+        ALOGE("%s: Error: invalid input: session %p, device %p",
+                __FUNCTION__, session, device);
+        return ACAMERA_ERROR_INVALID_PARAMETER;
+    }
+
+    if (session->isClosed()) {
+        ALOGE("%s: session %p is already closed", __FUNCTION__, session);
+        *device = nullptr;
+        return ACAMERA_ERROR_SESSION_CLOSED;
+    }
+
+    *device = session->getDevice();
+    if (*device == nullptr) {
+        // Should not reach here
+        ALOGE("%s: unknown failure: device is null", __FUNCTION__);
+        return ACAMERA_ERROR_UNKNOWN;
+    }
+    return ACAMERA_OK;
+}
+
+EXPORT
+camera_status_t ACameraCaptureSession_capture(
+        ACameraCaptureSession* session, /*optional*/ACameraCaptureSession_captureCallbacks* cbs,
+        int numRequests, ACaptureRequest** requests,
+        /*optional*/int* captureSequenceId) {
+    ATRACE_CALL();
+    if (session == nullptr || requests == nullptr || numRequests < 1) {
+        ALOGE("%s: Error: invalid input: session %p, numRequest %d, requests %p",
+                __FUNCTION__, session, numRequests, requests);
+        return ACAMERA_ERROR_INVALID_PARAMETER;
+    }
+
+    if (session->isClosed()) {
+        ALOGE("%s: session %p is already closed", __FUNCTION__, session);
+        *captureSequenceId = CAPTURE_SEQUENCE_ID_NONE;
+        return ACAMERA_ERROR_SESSION_CLOSED;
+    }
+
+    return session->capture(cbs, numRequests, requests, captureSequenceId);
+}
+
+EXPORT
+camera_status_t ACameraCaptureSession_setRepeatingRequest(
+        ACameraCaptureSession* session, /*optional*/ACameraCaptureSession_captureCallbacks* cbs,
+        int numRequests, ACaptureRequest** requests,
+        /*optional*/int* captureSequenceId) {
+    ATRACE_CALL();
+    if (session == nullptr || requests == nullptr || numRequests < 1) {
+        ALOGE("%s: Error: invalid input: session %p, numRequest %d, requests %p",
+                __FUNCTION__, session, numRequests, requests);
+        return ACAMERA_ERROR_INVALID_PARAMETER;
+    }
+
+    if (session->isClosed()) {
+        ALOGE("%s: session %p is already closed", __FUNCTION__, session);
+        *captureSequenceId = CAPTURE_SEQUENCE_ID_NONE;
+        return ACAMERA_ERROR_SESSION_CLOSED;
+    }
+
+    return session->setRepeatingRequest(cbs, numRequests, requests, captureSequenceId);
+}
+
+EXPORT
+camera_status_t ACameraCaptureSession_stopRepeating(ACameraCaptureSession* session) {
+    ATRACE_CALL();
+    if (session == nullptr) {
+        ALOGE("%s: Error: session is null", __FUNCTION__);
+        return ACAMERA_ERROR_INVALID_PARAMETER;
+    }
+
+    if (session->isClosed()) {
+        ALOGE("%s: session %p is already closed", __FUNCTION__, session);
+        return ACAMERA_ERROR_SESSION_CLOSED;
+    }
+    return session->stopRepeating();
+}
+
+EXPORT
+camera_status_t ACameraCaptureSession_abortCaptures(ACameraCaptureSession* session) {
+    ATRACE_CALL();
+    if (session == nullptr) {
+        ALOGE("%s: Error: session is null", __FUNCTION__);
+        return ACAMERA_ERROR_INVALID_PARAMETER;
+    }
+
+    if (session->isClosed()) {
+        ALOGE("%s: session %p is already closed", __FUNCTION__, session);
+        return ACAMERA_ERROR_SESSION_CLOSED;
+    }
+    return session->abortCaptures();
+}
diff --git a/camera/ndk/NdkCameraDevice.cpp b/camera/ndk/NdkCameraDevice.cpp
new file mode 100644
index 0000000..281d3e7
--- /dev/null
+++ b/camera/ndk/NdkCameraDevice.cpp
@@ -0,0 +1,161 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "NdkCameraDevice"
+#define ATRACE_TAG ATRACE_TAG_CAMERA
+
+#include <utils/Log.h>
+#include <utils/Trace.h>
+
+#include <NdkCameraDevice.h>
+#include "impl/ACameraCaptureSession.h"
+
+using namespace android;
+
+EXPORT
+camera_status_t ACameraDevice_close(ACameraDevice* device) {
+    ATRACE_CALL();
+    if (device == nullptr) {
+        ALOGE("%s: invalid argument! device is null", __FUNCTION__);
+        return ACAMERA_ERROR_INVALID_PARAMETER;
+    }
+    delete device;
+    return ACAMERA_OK;
+}
+
+EXPORT
+const char* ACameraDevice_getId(const ACameraDevice* device) {
+    ATRACE_CALL();
+    if (device == nullptr) {
+        ALOGE("%s: invalid argument! device is null", __FUNCTION__);
+        return nullptr;
+    }
+    return device->getId();
+}
+
+EXPORT
+camera_status_t ACameraDevice_createCaptureRequest(
+        const ACameraDevice* device,
+        ACameraDevice_request_template templateId,
+        ACaptureRequest** request) {
+    ATRACE_CALL();
+    if (device == nullptr || request == nullptr) {
+        ALOGE("%s: invalid argument! device %p request %p",
+                __FUNCTION__, device, request);
+        return ACAMERA_ERROR_INVALID_PARAMETER;
+    }
+    switch (templateId) {
+        case TEMPLATE_PREVIEW:
+        case TEMPLATE_STILL_CAPTURE:
+        case TEMPLATE_RECORD:
+        case TEMPLATE_VIDEO_SNAPSHOT:
+        case TEMPLATE_ZERO_SHUTTER_LAG:
+        case TEMPLATE_MANUAL:
+            break;
+        default:
+            ALOGE("%s: unknown template ID %d", __FUNCTION__, templateId);
+            return ACAMERA_ERROR_INVALID_PARAMETER;
+    }
+    return device->createCaptureRequest(templateId, request);
+}
+
+EXPORT
+camera_status_t ACaptureSessionOutputContainer_create(
+        /*out*/ACaptureSessionOutputContainer** out) {
+    ATRACE_CALL();
+    if (out == nullptr) {
+        ALOGE("%s: Error: out null", __FUNCTION__);
+        return ACAMERA_ERROR_INVALID_PARAMETER;
+    }
+    *out = new ACaptureSessionOutputContainer();
+    return ACAMERA_OK;
+}
+
+EXPORT
+void ACaptureSessionOutputContainer_free(ACaptureSessionOutputContainer* container) {
+    ATRACE_CALL();
+    if (container != nullptr) {
+        delete container;
+    }
+    return;
+}
+
+EXPORT
+camera_status_t ACaptureSessionOutput_create(
+        ANativeWindow* window, /*out*/ACaptureSessionOutput** out) {
+    ATRACE_CALL();
+    if (window == nullptr || out == nullptr) {
+        ALOGE("%s: Error: bad argument. window %p, out %p",
+                __FUNCTION__, window, out);
+        return ACAMERA_ERROR_INVALID_PARAMETER;
+    }
+    *out = new ACaptureSessionOutput(window);
+    return ACAMERA_OK;
+}
+
+EXPORT
+void ACaptureSessionOutput_free(ACaptureSessionOutput* output) {
+    ATRACE_CALL();
+    if (output != nullptr) {
+        delete output;
+    }
+    return;
+}
+
+EXPORT
+camera_status_t ACaptureSessionOutputContainer_add(
+        ACaptureSessionOutputContainer* container, const ACaptureSessionOutput* output) {
+    ATRACE_CALL();
+    if (container == nullptr || output == nullptr) {
+        ALOGE("%s: Error: invalid input: container %p, output %p",
+                __FUNCTION__, container, output);
+        return ACAMERA_ERROR_INVALID_PARAMETER;
+    }
+    auto pair = container->mOutputs.insert(*output);
+    if (!pair.second) {
+        ALOGW("%s: output %p already exists!", __FUNCTION__, output);
+    }
+    return ACAMERA_OK;
+}
+
+EXPORT
+camera_status_t ACaptureSessionOutputContainer_remove(
+        ACaptureSessionOutputContainer* container, const ACaptureSessionOutput* output) {
+    ATRACE_CALL();
+    if (container == nullptr || output == nullptr) {
+        ALOGE("%s: Error: invalid input: container %p, output %p",
+                __FUNCTION__, container, output);
+        return ACAMERA_ERROR_INVALID_PARAMETER;
+    }
+    container->mOutputs.erase(*output);
+    return ACAMERA_OK;
+}
+
+EXPORT
+camera_status_t ACameraDevice_createCaptureSession(
+        ACameraDevice* device,
+        const ACaptureSessionOutputContainer*       outputs,
+        const ACameraCaptureSession_stateCallbacks* callbacks,
+        /*out*/ACameraCaptureSession** session) {
+    ATRACE_CALL();
+    if (device == nullptr || outputs == nullptr || callbacks == nullptr || session == nullptr) {
+        ALOGE("%s: Error: invalid input: device %p, outputs %p, callbacks %p, session %p",
+                __FUNCTION__, device, outputs, callbacks, session);
+        return ACAMERA_ERROR_INVALID_PARAMETER;
+    }
+    return device->createCaptureSession(outputs, callbacks, session);
+}
diff --git a/camera/ndk/NdkCameraManager.cpp b/camera/ndk/NdkCameraManager.cpp
new file mode 100644
index 0000000..ff15263
--- /dev/null
+++ b/camera/ndk/NdkCameraManager.cpp
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "NdkCameraManager"
+#define ATRACE_TAG ATRACE_TAG_CAMERA
+
+#include <utils/Log.h>
+#include <utils/Trace.h>
+
+#include <NdkCameraManager.h>
+#include "impl/ACameraManager.h"
+
+using namespace android;
+
+EXPORT
+ACameraManager* ACameraManager_create() {
+    ATRACE_CALL();
+    return new ACameraManager();
+}
+
+EXPORT
+void ACameraManager_delete(ACameraManager* manager) {
+    ATRACE_CALL();
+    if (manager != nullptr) {
+        delete manager;
+    }
+}
+
+EXPORT
+camera_status_t ACameraManager_getCameraIdList(
+        ACameraManager* manager, ACameraIdList** cameraIdList) {
+    ATRACE_CALL();
+    if (manager == nullptr || cameraIdList == nullptr) {
+        ALOGE("%s: invalid argument! manager %p, cameraIdList %p",
+              __FUNCTION__, manager, cameraIdList);
+        return ACAMERA_ERROR_INVALID_PARAMETER;
+    }
+    return manager->getCameraIdList(cameraIdList);
+}
+
+EXPORT
+void ACameraManager_deleteCameraIdList(ACameraIdList* cameraIdList) {
+    ATRACE_CALL();
+    if (cameraIdList != nullptr) {
+        ACameraManager::deleteCameraIdList(cameraIdList);
+    }
+}
+
+EXPORT
+camera_status_t ACameraManager_registerAvailabilityCallback(
+        ACameraManager*, const ACameraManager_AvailabilityCallbacks *callback) {
+    ATRACE_CALL();
+    if (callback == nullptr) {
+        ALOGE("%s: invalid argument! callback is null!", __FUNCTION__);
+        return ACAMERA_ERROR_INVALID_PARAMETER;
+    }
+    if (callback->onCameraAvailable == nullptr || callback->onCameraUnavailable == nullptr) {
+        ALOGE("%s: invalid argument! callback %p, "
+                "onCameraAvailable %p, onCameraUnavailable %p",
+               __FUNCTION__, callback,
+               callback->onCameraAvailable, callback->onCameraUnavailable);
+        return ACAMERA_ERROR_INVALID_PARAMETER;
+    }
+    CameraManagerGlobal::getInstance().registerAvailabilityCallback(callback);
+    return ACAMERA_OK;
+}
+
+EXPORT
+camera_status_t ACameraManager_unregisterAvailabilityCallback(
+        ACameraManager*, const ACameraManager_AvailabilityCallbacks *callback) {
+    ATRACE_CALL();
+    if (callback == nullptr) {
+        ALOGE("%s: invalid argument! callback is null!", __FUNCTION__);
+        return ACAMERA_ERROR_INVALID_PARAMETER;
+    }
+    if (callback->onCameraAvailable == nullptr || callback->onCameraUnavailable == nullptr) {
+        ALOGE("%s: invalid argument! callback %p, "
+                "onCameraAvailable %p, onCameraUnavailable %p",
+               __FUNCTION__, callback,
+               callback->onCameraAvailable, callback->onCameraUnavailable);
+        return ACAMERA_ERROR_INVALID_PARAMETER;
+    }
+    CameraManagerGlobal::getInstance().unregisterAvailabilityCallback(callback);
+    return ACAMERA_OK;
+}
+
+EXPORT
+camera_status_t ACameraManager_getCameraCharacteristics(
+        ACameraManager* mgr, const char* cameraId, ACameraMetadata** chars){
+    ATRACE_CALL();
+    if (mgr == nullptr || cameraId == nullptr || chars == nullptr) {
+        ALOGE("%s: invalid argument! mgr %p cameraId %p chars %p",
+                __FUNCTION__, mgr, cameraId, chars);
+        return ACAMERA_ERROR_INVALID_PARAMETER;
+    }
+    return mgr->getCameraCharacteristics(cameraId, chars);
+}
+
+EXPORT
+camera_status_t ACameraManager_openCamera(
+        ACameraManager* mgr, const char* cameraId,
+        ACameraDevice_StateCallbacks* callback,
+        /*out*/ACameraDevice** device) {
+    ATRACE_CALL();
+    if (mgr == nullptr || cameraId == nullptr || callback == nullptr || device == nullptr) {
+        ALOGE("%s: invalid argument! mgr %p cameraId %p callback %p device %p",
+                __FUNCTION__, mgr, cameraId, callback, device);
+        return ACAMERA_ERROR_INVALID_PARAMETER;
+    }
+    return mgr->openCamera(cameraId, callback, device);
+}
diff --git a/camera/ndk/NdkCameraMetadata.cpp b/camera/ndk/NdkCameraMetadata.cpp
new file mode 100644
index 0000000..85fe75b
--- /dev/null
+++ b/camera/ndk/NdkCameraMetadata.cpp
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "NdkCameraMetadata"
+#define ATRACE_TAG ATRACE_TAG_CAMERA
+
+#include <utils/Log.h>
+#include <utils/Trace.h>
+
+#include "NdkCameraMetadata.h"
+#include "impl/ACameraMetadata.h"
+
+using namespace android;
+
+EXPORT
+camera_status_t ACameraMetadata_getConstEntry(
+        const ACameraMetadata* acm, uint32_t tag, ACameraMetadata_const_entry* entry) {
+    ATRACE_CALL();
+    if (acm == nullptr || entry == nullptr) {
+        ALOGE("%s: invalid argument! metadata %p, tag 0x%x, entry %p",
+               __FUNCTION__, acm, tag, entry);
+        return ACAMERA_ERROR_INVALID_PARAMETER;
+    }
+    return acm->getConstEntry(tag, entry);
+}
+
+EXPORT
+camera_status_t ACameraMetadata_getAllTags(
+        const ACameraMetadata* acm, /*out*/int32_t* numTags, /*out*/const uint32_t** tags) {
+    ATRACE_CALL();
+    if (acm == nullptr || numTags == nullptr || tags == nullptr) {
+        ALOGE("%s: invalid argument! metadata %p, numTags %p, tags %p",
+               __FUNCTION__, acm, numTags, tags);
+        return ACAMERA_ERROR_INVALID_PARAMETER;
+    }
+    return acm->getTags(numTags, tags);
+}
+
+EXPORT
+ACameraMetadata* ACameraMetadata_copy(const ACameraMetadata* src) {
+    ATRACE_CALL();
+    if (src == nullptr) {
+        ALOGE("%s: src is null!", __FUNCTION__);
+        return nullptr;
+    }
+    return new ACameraMetadata(*src);
+}
+
+EXPORT
+void ACameraMetadata_free(ACameraMetadata* metadata) {
+    ATRACE_CALL();
+    if (metadata != nullptr) {
+        delete metadata;
+    }
+}
diff --git a/camera/ndk/NdkCaptureRequest.cpp b/camera/ndk/NdkCaptureRequest.cpp
new file mode 100644
index 0000000..77b9a33
--- /dev/null
+++ b/camera/ndk/NdkCaptureRequest.cpp
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "NdkCaptureRequest"
+#define ATRACE_TAG ATRACE_TAG_CAMERA
+
+#include <utils/Log.h>
+#include <utils/Trace.h>
+
+#include "NdkCaptureRequest.h"
+#include "impl/ACameraMetadata.h"
+#include "impl/ACaptureRequest.h"
+
+EXPORT
+camera_status_t ACameraOutputTarget_create(
+        ANativeWindow* window, ACameraOutputTarget** out) {
+    ATRACE_CALL();
+    if (window == nullptr) {
+        ALOGE("%s: Error: input window is null", __FUNCTION__);
+        return ACAMERA_ERROR_INVALID_PARAMETER;
+    }
+    *out = new ACameraOutputTarget(window);
+    return ACAMERA_OK;
+}
+
+EXPORT
+void ACameraOutputTarget_free(ACameraOutputTarget* target) {
+    ATRACE_CALL();
+    if (target != nullptr) {
+        delete target;
+    }
+    return;
+}
+
+EXPORT
+camera_status_t ACaptureRequest_addTarget(
+        ACaptureRequest* req, const ACameraOutputTarget* target) {
+    ATRACE_CALL();
+    if (req == nullptr || req->targets == nullptr || target == nullptr) {
+        ALOGE("%s: Error: invalid input: req %p, req-targets %p, target %p",
+                __FUNCTION__, req, req->targets, target);
+        return ACAMERA_ERROR_INVALID_PARAMETER;
+    }
+    auto pair = req->targets->mOutputs.insert(*target);
+    if (!pair.second) {
+        ALOGW("%s: target %p already exists!", __FUNCTION__, target);
+    }
+    return ACAMERA_OK;
+}
+
+EXPORT
+camera_status_t ACaptureRequest_removeTarget(
+        ACaptureRequest* req, const ACameraOutputTarget* target) {
+    ATRACE_CALL();
+    if (req == nullptr || req->targets == nullptr || target == nullptr) {
+        ALOGE("%s: Error: invalid input: req %p, req-targets %p, target %p",
+                __FUNCTION__, req, req->targets, target);
+        return ACAMERA_ERROR_INVALID_PARAMETER;
+    }
+    req->targets->mOutputs.erase(*target);
+    return ACAMERA_OK;
+}
+
+EXPORT
+camera_status_t ACaptureRequest_getConstEntry(
+        const ACaptureRequest* req, uint32_t tag, ACameraMetadata_const_entry* entry) {
+    ATRACE_CALL();
+    if (req == nullptr || entry == nullptr) {
+        ALOGE("%s: invalid argument! req 0x%p, tag 0x%x, entry 0x%p",
+               __FUNCTION__, req, tag, entry);
+        return ACAMERA_ERROR_INVALID_PARAMETER;
+    }
+    return req->settings->getConstEntry(tag, entry);
+}
+
+EXPORT
+camera_status_t ACaptureRequest_getAllTags(
+        const ACaptureRequest* req, /*out*/int32_t* numTags, /*out*/const uint32_t** tags) {
+    ATRACE_CALL();
+    if (req == nullptr || numTags == nullptr || tags == nullptr) {
+        ALOGE("%s: invalid argument! request %p, numTags %p, tags %p",
+               __FUNCTION__, req, numTags, tags);
+        return ACAMERA_ERROR_INVALID_PARAMETER;
+    }
+    return req->settings->getTags(numTags, tags);
+}
+
+#define SET_ENTRY(NAME,NDK_TYPE)                                                        \
+EXPORT                                                                                  \
+camera_status_t ACaptureRequest_setEntry_##NAME(                                        \
+        ACaptureRequest* req, uint32_t tag, uint32_t count, const NDK_TYPE* data) {     \
+    ATRACE_CALL();                                                                      \
+    if (req == nullptr || (count > 0 && data == nullptr)) {                             \
+        ALOGE("%s: invalid argument! req %p, tag 0x%x, count %d, data 0x%p",            \
+               __FUNCTION__, req, tag, count, data);                                    \
+        return ACAMERA_ERROR_INVALID_PARAMETER;                                         \
+    }                                                                                   \
+    return req->settings->update(tag, count, data);                                     \
+}
+
+SET_ENTRY(u8,uint8_t)
+SET_ENTRY(i32,int32_t)
+SET_ENTRY(float,float)
+SET_ENTRY(double,double)
+SET_ENTRY(i64,int64_t)
+SET_ENTRY(rational,ACameraMetadata_rational)
+
+#undef SET_ENTRY
+
+EXPORT
+void ACaptureRequest_free(ACaptureRequest* request) {
+    ATRACE_CALL();
+    if (request == nullptr) {
+        return;
+    }
+    delete request->settings;
+    delete request->targets;
+    delete request;
+    return;
+}
diff --git a/camera/ndk/impl/ACameraCaptureSession.cpp b/camera/ndk/impl/ACameraCaptureSession.cpp
new file mode 100644
index 0000000..b9c159d
--- /dev/null
+++ b/camera/ndk/impl/ACameraCaptureSession.cpp
@@ -0,0 +1,178 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "ACameraCaptureSession"
+
+#include "ACameraCaptureSession.h"
+
+using namespace android;
+
+ACameraCaptureSession::~ACameraCaptureSession() {
+    ALOGV("~ACameraCaptureSession: %p notify device end of life", this);
+    sp<CameraDevice> dev = getDeviceSp();
+    if (dev != nullptr && !dev->isClosed()) {
+        dev->lockDeviceForSessionOps();
+        {
+            Mutex::Autolock _l(mSessionLock);
+            dev->notifySessionEndOfLifeLocked(this);
+        }
+        dev->unlockDevice();
+    }
+    // Fire onClosed callback
+    (*mUserSessionCallback.onClosed)(mUserSessionCallback.context, this);
+    ALOGV("~ACameraCaptureSession: %p is deleted", this);
+}
+
+void
+ACameraCaptureSession::closeByApp() {
+    {
+        Mutex::Autolock _l(mSessionLock);
+        if (mClosedByApp) {
+            // Do not close twice
+            return;
+        }
+        mClosedByApp = true;
+    }
+
+    sp<CameraDevice> dev = getDeviceSp();
+    if (dev != nullptr) {
+        dev->lockDeviceForSessionOps();
+    }
+
+    {
+        Mutex::Autolock _l(mSessionLock);
+
+        if (!mIsClosed && dev != nullptr) {
+            camera_status_t ret = dev->stopRepeatingLocked();
+            if (ret != ACAMERA_OK) {
+                ALOGE("Stop repeating request failed while closing session %p", this);
+            }
+        }
+        mIsClosed = true;
+    }
+
+    if (dev != nullptr) {
+        dev->unlockDevice();
+    }
+    this->decStrong((void*) ACameraDevice_createCaptureSession);
+}
+
+camera_status_t
+ACameraCaptureSession::stopRepeating() {
+    sp<CameraDevice> dev = getDeviceSp();
+    if (dev == nullptr) {
+        ALOGE("Error: Device associated with session %p has been closed!", this);
+        return ACAMERA_ERROR_SESSION_CLOSED;
+    }
+
+    camera_status_t ret;
+    dev->lockDeviceForSessionOps();
+    {
+        Mutex::Autolock _l(mSessionLock);
+        ret = dev->stopRepeatingLocked();
+    }
+    dev->unlockDevice();
+    return ret;
+}
+
+camera_status_t
+ACameraCaptureSession::abortCaptures() {
+    sp<CameraDevice> dev = getDeviceSp();
+    if (dev == nullptr) {
+        ALOGE("Error: Device associated with session %p has been closed!", this);
+        return ACAMERA_ERROR_SESSION_CLOSED;
+    }
+
+    camera_status_t ret;
+    dev->lockDeviceForSessionOps();
+    {
+        Mutex::Autolock _l(mSessionLock);
+        ret = dev->flushLocked(this);
+    }
+    dev->unlockDevice();
+    return ret;
+}
+
+camera_status_t
+ACameraCaptureSession::setRepeatingRequest(
+        /*optional*/ACameraCaptureSession_captureCallbacks* cbs,
+        int numRequests, ACaptureRequest** requests,
+        /*optional*/int* captureSequenceId) {
+    sp<CameraDevice> dev = getDeviceSp();
+    if (dev == nullptr) {
+        ALOGE("Error: Device associated with session %p has been closed!", this);
+        return ACAMERA_ERROR_SESSION_CLOSED;
+    }
+
+    camera_status_t ret;
+    dev->lockDeviceForSessionOps();
+    {
+        Mutex::Autolock _l(mSessionLock);
+        ret = dev->setRepeatingRequestsLocked(
+                this, cbs, numRequests, requests, captureSequenceId);
+    }
+    dev->unlockDevice();
+    return ret;
+}
+
+camera_status_t ACameraCaptureSession::capture(
+        /*optional*/ACameraCaptureSession_captureCallbacks* cbs,
+        int numRequests, ACaptureRequest** requests,
+        /*optional*/int* captureSequenceId) {
+    sp<CameraDevice> dev = getDeviceSp();
+    if (dev == nullptr) {
+        ALOGE("Error: Device associated with session %p has been closed!", this);
+        return ACAMERA_ERROR_SESSION_CLOSED;
+    }
+    camera_status_t ret;
+    dev->lockDeviceForSessionOps();
+    {
+        Mutex::Autolock _l(mSessionLock);
+        ret = dev->captureLocked(this, cbs, numRequests, requests, captureSequenceId);
+    }
+    dev->unlockDevice();
+    return ret;
+}
+
+ACameraDevice*
+ACameraCaptureSession::getDevice() {
+    Mutex::Autolock _l(mSessionLock);
+    sp<CameraDevice> dev = getDeviceSp();
+    if (dev == nullptr) {
+        ALOGE("Error: Device associated with session %p has been closed!", this);
+        return nullptr;
+    }
+    return dev->getWrapper();
+}
+
+void
+ACameraCaptureSession::closeByDevice() {
+    Mutex::Autolock _l(mSessionLock);
+    mIsClosed = true;
+}
+
+sp<CameraDevice>
+ACameraCaptureSession::getDeviceSp() {
+    sp<CameraDevice> device = mDevice.promote();
+    if (device == nullptr || device->isClosed()) {
+        ALOGW("Device is closed but session %d is not notified", mId);
+        return nullptr;
+    }
+    return device;
+}
+
+
diff --git a/camera/ndk/impl/ACameraCaptureSession.h b/camera/ndk/impl/ACameraCaptureSession.h
new file mode 100644
index 0000000..58428e6
--- /dev/null
+++ b/camera/ndk/impl/ACameraCaptureSession.h
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef _ACAMERA_CAPTURE_SESSION_H
+#define _ACAMERA_CAPTURE_SESSION_H
+
+#include <set>
+#include <hardware/camera3.h>
+#include <NdkCameraDevice.h>
+#include "ACameraDevice.h"
+
+using namespace android;
+
+struct ACaptureSessionOutput {
+    ACaptureSessionOutput(ANativeWindow* window) : mWindow(window) {};
+
+    bool operator == (const ACaptureSessionOutput& other) const {
+        return mWindow == other.mWindow;
+    }
+    bool operator != (const ACaptureSessionOutput& other) const {
+        return mWindow != other.mWindow;
+    }
+    bool operator < (const ACaptureSessionOutput& other) const {
+        return mWindow < other.mWindow;
+    }
+    bool operator > (const ACaptureSessionOutput& other) const {
+        return mWindow > other.mWindow;
+    }
+
+    ANativeWindow* mWindow;
+    int            mRotation = CAMERA3_STREAM_ROTATION_0;
+};
+
+struct ACaptureSessionOutputContainer {
+    std::set<ACaptureSessionOutput> mOutputs;
+};
+
+/**
+ * ACameraCaptureSession opaque struct definition
+ * Leave outside of android namespace because it's NDK struct
+ */
+struct ACameraCaptureSession : public RefBase {
+  public:
+    ACameraCaptureSession(
+            int id,
+            const ACaptureSessionOutputContainer* outputs,
+            const ACameraCaptureSession_stateCallbacks* cb,
+            CameraDevice* device) :
+            mId(id), mOutput(*outputs), mUserSessionCallback(*cb),
+            mDevice(device) {}
+
+    // This can be called in app calling close() or after some app callback is finished
+    // Make sure the caller does not hold device or session lock!
+    ~ACameraCaptureSession();
+
+    // No API except Session_Close will work if device is closed
+    // A session will enter closed state when one of the following happens:
+    //     1. Explicitly closed by app
+    //     2. Replaced by a newer session
+    //     3. Device is closed
+    bool isClosed() { Mutex::Autolock _l(mSessionLock); return mIsClosed; }
+
+    // Close the session and mark app no longer need this session.
+    void closeByApp();
+
+    camera_status_t stopRepeating();
+
+    camera_status_t abortCaptures();
+
+    camera_status_t setRepeatingRequest(
+            /*optional*/ACameraCaptureSession_captureCallbacks* cbs,
+            int numRequests, ACaptureRequest** requests,
+            /*optional*/int* captureSequenceId);
+
+    camera_status_t capture(
+            /*optional*/ACameraCaptureSession_captureCallbacks* cbs,
+            int numRequests, ACaptureRequest** requests,
+            /*optional*/int* captureSequenceId);
+
+    ACameraDevice* getDevice();
+
+  private:
+    friend class CameraDevice;
+
+    // Close session because app close camera device, camera device got ERROR_DISCONNECTED,
+    // or a new session is replacing this session.
+    void closeByDevice();
+
+    sp<CameraDevice> getDeviceSp();
+
+    const int mId;
+    const ACaptureSessionOutputContainer mOutput;
+    const ACameraCaptureSession_stateCallbacks mUserSessionCallback;
+    const wp<CameraDevice> mDevice;
+    bool  mIsClosed = false;
+    bool  mClosedByApp = false;
+    Mutex mSessionLock;
+};
+
+#endif // _ACAMERA_CAPTURE_SESSION_H
diff --git a/camera/ndk/impl/ACameraDevice.cpp b/camera/ndk/impl/ACameraDevice.cpp
new file mode 100644
index 0000000..7d78e2b
--- /dev/null
+++ b/camera/ndk/impl/ACameraDevice.cpp
@@ -0,0 +1,1369 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "ACameraDevice"
+
+#include <vector>
+#include <inttypes.h>
+#include <android/hardware/ICameraService.h>
+#include <camera2/SubmitInfo.h>
+#include <gui/Surface.h>
+#include "ACameraDevice.h"
+#include "ACameraMetadata.h"
+#include "ACaptureRequest.h"
+#include "ACameraCaptureSession.h"
+
+using namespace android;
+
+namespace android {
+// Static member definitions
+const char* CameraDevice::kContextKey        = "Context";
+const char* CameraDevice::kDeviceKey         = "Device";
+const char* CameraDevice::kErrorCodeKey      = "ErrorCode";
+const char* CameraDevice::kCallbackFpKey     = "Callback";
+const char* CameraDevice::kSessionSpKey      = "SessionSp";
+const char* CameraDevice::kCaptureRequestKey = "CaptureRequest";
+const char* CameraDevice::kTimeStampKey      = "TimeStamp";
+const char* CameraDevice::kCaptureResultKey  = "CaptureResult";
+const char* CameraDevice::kCaptureFailureKey = "CaptureFailure";
+const char* CameraDevice::kSequenceIdKey     = "SequenceId";
+const char* CameraDevice::kFrameNumberKey    = "FrameNumber";
+const char* CameraDevice::kAnwKey            = "Anw";
+
+/**
+ * CameraDevice Implementation
+ */
+CameraDevice::CameraDevice(
+        const char* id,
+        ACameraDevice_StateCallbacks* cb,
+        std::unique_ptr<ACameraMetadata> chars,
+        ACameraDevice* wrapper) :
+        mCameraId(id),
+        mAppCallbacks(*cb),
+        mChars(std::move(chars)),
+        mServiceCallback(new ServiceCallback(this)),
+        mWrapper(wrapper),
+        mInError(false),
+        mError(ACAMERA_OK),
+        mIdle(true) {
+    mClosing = false;
+    // Setup looper thread to perfrom device callbacks to app
+    mCbLooper = new ALooper;
+    mCbLooper->setName("C2N-dev-looper");
+    status_t err = mCbLooper->start(
+            /*runOnCallingThread*/false,
+            /*canCallJava*/       true,
+            PRIORITY_DEFAULT);
+    if (err != OK) {
+        ALOGE("%s: Unable to start camera device callback looper: %s (%d)",
+                __FUNCTION__, strerror(-err), err);
+        setCameraDeviceErrorLocked(ACAMERA_ERROR_CAMERA_DEVICE);
+    }
+    mHandler = new CallbackHandler();
+    mCbLooper->registerHandler(mHandler);
+
+    const CameraMetadata& metadata = mChars->getInternalData();
+    camera_metadata_ro_entry entry = metadata.find(ANDROID_REQUEST_PARTIAL_RESULT_COUNT);
+    if (entry.count != 1) {
+        ALOGW("%s: bad count %zu for partial result count", __FUNCTION__, entry.count);
+        mPartialResultCount = 1;
+    } else {
+        mPartialResultCount = entry.data.i32[0];
+    }
+
+    entry = metadata.find(ANDROID_LENS_INFO_SHADING_MAP_SIZE);
+    if (entry.count != 2) {
+        ALOGW("%s: bad count %zu for shading map size", __FUNCTION__, entry.count);
+        mShadingMapSize[0] = 0;
+        mShadingMapSize[1] = 0;
+    } else {
+        mShadingMapSize[0] = entry.data.i32[0];
+        mShadingMapSize[1] = entry.data.i32[1];
+    }
+}
+
+// Device close implementaiton
+CameraDevice::~CameraDevice() {
+    Mutex::Autolock _l(mDeviceLock);
+    if (!isClosed()) {
+        disconnectLocked();
+    }
+    if (mCbLooper != nullptr) {
+        mCbLooper->unregisterHandler(mHandler->id());
+        mCbLooper->stop();
+    }
+    mCbLooper.clear();
+    mHandler.clear();
+}
+
+// TODO: cached created request?
+camera_status_t
+CameraDevice::createCaptureRequest(
+        ACameraDevice_request_template templateId,
+        ACaptureRequest** request) const {
+    Mutex::Autolock _l(mDeviceLock);
+    camera_status_t ret = checkCameraClosedOrErrorLocked();
+    if (ret != ACAMERA_OK) {
+        return ret;
+    }
+    if (mRemote == nullptr) {
+        return ACAMERA_ERROR_CAMERA_DISCONNECTED;
+    }
+    CameraMetadata rawRequest;
+    binder::Status remoteRet = mRemote->createDefaultRequest(templateId, &rawRequest);
+    if (remoteRet.serviceSpecificErrorCode() ==
+            hardware::ICameraService::ERROR_ILLEGAL_ARGUMENT) {
+        ALOGW("Create capture request failed! template %d is not supported on this device",
+            templateId);
+        return ACAMERA_ERROR_INVALID_PARAMETER;
+    } else if (!remoteRet.isOk()) {
+        ALOGE("Create capture request failed: %s", remoteRet.toString8().string());
+        return ACAMERA_ERROR_UNKNOWN;
+    }
+    ACaptureRequest* outReq = new ACaptureRequest();
+    outReq->settings = new ACameraMetadata(rawRequest.release(), ACameraMetadata::ACM_REQUEST);
+    outReq->targets  = new ACameraOutputTargets();
+    *request = outReq;
+    return ACAMERA_OK;
+}
+
+camera_status_t
+CameraDevice::createCaptureSession(
+        const ACaptureSessionOutputContainer*       outputs,
+        const ACameraCaptureSession_stateCallbacks* callbacks,
+        /*out*/ACameraCaptureSession** session) {
+    Mutex::Autolock _l(mDeviceLock);
+    camera_status_t ret = checkCameraClosedOrErrorLocked();
+    if (ret != ACAMERA_OK) {
+        return ret;
+    }
+
+    if (mCurrentSession != nullptr) {
+        mCurrentSession->closeByDevice();
+        stopRepeatingLocked();
+    }
+
+    // Create new session
+    ret = configureStreamsLocked(outputs);
+    if (ret != ACAMERA_OK) {
+        ALOGE("Fail to create new session. cannot configure streams");
+        return ret;
+    }
+
+    ACameraCaptureSession* newSession = new ACameraCaptureSession(
+            mNextSessionId++, outputs, callbacks, this);
+
+    // set new session as current session
+    newSession->incStrong((void *) ACameraDevice_createCaptureSession);
+    mCurrentSession = newSession;
+    mFlushing = false;
+    *session = newSession;
+    return ACAMERA_OK;
+}
+
+camera_status_t
+CameraDevice::captureLocked(
+        sp<ACameraCaptureSession> session,
+        /*optional*/ACameraCaptureSession_captureCallbacks* cbs,
+        int numRequests, ACaptureRequest** requests,
+        /*optional*/int* captureSequenceId) {
+    return submitRequestsLocked(
+            session, cbs, numRequests, requests, captureSequenceId, /*isRepeating*/false);
+}
+
+camera_status_t
+CameraDevice::setRepeatingRequestsLocked(
+        sp<ACameraCaptureSession> session,
+        /*optional*/ACameraCaptureSession_captureCallbacks* cbs,
+        int numRequests, ACaptureRequest** requests,
+        /*optional*/int* captureSequenceId) {
+    return submitRequestsLocked(
+            session, cbs, numRequests, requests, captureSequenceId, /*isRepeating*/true);
+}
+
+camera_status_t
+CameraDevice::submitRequestsLocked(
+        sp<ACameraCaptureSession> session,
+        /*optional*/ACameraCaptureSession_captureCallbacks* cbs,
+        int numRequests, ACaptureRequest** requests,
+        /*optional*/int* captureSequenceId,
+        bool isRepeating) {
+    camera_status_t ret = checkCameraClosedOrErrorLocked();
+    if (ret != ACAMERA_OK) {
+        ALOGE("Camera %s submit capture request failed! ret %d", getId(), ret);
+        return ret;
+    }
+
+    // Form two vectors of capture request, one for internal tracking
+    std::vector<hardware::camera2::CaptureRequest> requestList;
+    Vector<sp<CaptureRequest> > requestsV;
+    requestsV.setCapacity(numRequests);
+    for (int i = 0; i < numRequests; i++) {
+        sp<CaptureRequest> req;
+        ret = allocateCaptureRequest(requests[i], req);
+        if (ret != ACAMERA_OK) {
+            ALOGE("Convert capture request to internal format failure! ret %d", ret);
+            return ret;
+        }
+        if (req->mSurfaceList.empty()) {
+            ALOGE("Capture request without output target cannot be submitted!");
+            return ACAMERA_ERROR_INVALID_PARAMETER;
+        }
+        requestList.push_back(*(req.get()));
+        requestsV.push_back(req);
+    }
+
+    if (isRepeating) {
+        ret = stopRepeatingLocked();
+        if (ret != ACAMERA_OK) {
+            ALOGE("Camera %s stop repeating failed! ret %d", getId(), ret);
+            return ret;
+        }
+    }
+
+    binder::Status remoteRet;
+    hardware::camera2::utils::SubmitInfo info;
+    remoteRet = mRemote->submitRequestList(requestList, isRepeating, &info);
+    int sequenceId = info.mRequestId;
+    int64_t lastFrameNumber = info.mLastFrameNumber;
+    if (sequenceId < 0) {
+        ALOGE("Camera %s submit request remote failure: ret %d", getId(), sequenceId);
+        return ACAMERA_ERROR_UNKNOWN;
+    }
+
+    CallbackHolder cbHolder(session, requestsV, isRepeating, cbs);
+    mSequenceCallbackMap.insert(std::make_pair(sequenceId, cbHolder));
+
+    if (isRepeating) {
+        // stopRepeating above should have cleanup repeating sequence id
+        if (mRepeatingSequenceId != REQUEST_ID_NONE) {
+            setCameraDeviceErrorLocked(ACAMERA_ERROR_CAMERA_DEVICE);
+            return ACAMERA_ERROR_CAMERA_DEVICE;
+        }
+        mRepeatingSequenceId = sequenceId;
+    } else {
+        mSequenceLastFrameNumberMap.insert(std::make_pair(sequenceId, lastFrameNumber));
+    }
+
+    if (mIdle) {
+        sp<AMessage> msg = new AMessage(kWhatSessionStateCb, mHandler);
+        msg->setPointer(kContextKey, session->mUserSessionCallback.context);
+        msg->setObject(kSessionSpKey, session);
+        msg->setPointer(kCallbackFpKey, (void*) session->mUserSessionCallback.onActive);
+        msg->post();
+    }
+    mIdle = false;
+    mBusySession = session;
+
+    if (captureSequenceId) {
+        *captureSequenceId = sequenceId;
+    }
+    return ACAMERA_OK;
+}
+
+camera_status_t
+CameraDevice::allocateCaptureRequest(
+        const ACaptureRequest* request, /*out*/sp<CaptureRequest>& outReq) {
+    camera_status_t ret;
+    sp<CaptureRequest> req(new CaptureRequest());
+    req->mMetadata = request->settings->getInternalData();
+    req->mIsReprocess = false; // NDK does not support reprocessing yet
+
+    for (auto outputTarget : request->targets->mOutputs) {
+        ANativeWindow* anw = outputTarget.mWindow;
+        sp<Surface> surface;
+        ret = getSurfaceFromANativeWindow(anw, surface);
+        if (ret != ACAMERA_OK) {
+            ALOGE("Bad output target in capture request! ret %d", ret);
+            return ret;
+        }
+        req->mSurfaceList.push_back(surface);
+    }
+    outReq = req;
+    return ACAMERA_OK;
+}
+
+ACaptureRequest*
+CameraDevice::allocateACaptureRequest(sp<CaptureRequest>& req) {
+    ACaptureRequest* pRequest = new ACaptureRequest();
+    CameraMetadata clone = req->mMetadata;
+    pRequest->settings = new ACameraMetadata(clone.release(), ACameraMetadata::ACM_REQUEST);
+    pRequest->targets  = new ACameraOutputTargets();
+    for (size_t i = 0; i < req->mSurfaceList.size(); i++) {
+        ANativeWindow* anw = static_cast<ANativeWindow*>(req->mSurfaceList[i].get());
+        ACameraOutputTarget outputTarget(anw);
+        pRequest->targets->mOutputs.insert(outputTarget);
+    }
+    return pRequest;
+}
+
+void
+CameraDevice::freeACaptureRequest(ACaptureRequest* req) {
+    if (req == nullptr) {
+        return;
+    }
+    delete req->settings;
+    delete req->targets;
+    delete req;
+}
+
+void
+CameraDevice::notifySessionEndOfLifeLocked(ACameraCaptureSession* session) {
+    if (isClosed()) {
+        // Device is closing already. do nothing
+        return;
+    }
+
+    if (session != mCurrentSession) {
+        // Session has been replaced by other seesion or device is closed
+        return;
+    }
+    mCurrentSession = nullptr;
+
+    // Should not happen
+    if (!session->mIsClosed) {
+        ALOGE("Error: unclosed session %p reaches end of life!", session);
+        setCameraDeviceErrorLocked(ACAMERA_ERROR_CAMERA_DEVICE);
+        return;
+    }
+
+    // No new session, unconfigure now
+    camera_status_t ret = configureStreamsLocked(nullptr);
+    if (ret != ACAMERA_OK) {
+        ALOGE("Unconfigure stream failed. Device might still be configured! ret %d", ret);
+    }
+}
+
+void
+CameraDevice::disconnectLocked() {
+    if (mClosing.exchange(true)) {
+        // Already closing, just return
+        ALOGW("Camera device %s is already closing.", getId());
+        return;
+    }
+
+    if (mRemote != nullptr) {
+        mRemote->disconnect();
+    }
+    mRemote = nullptr;
+
+    if (mCurrentSession != nullptr) {
+        mCurrentSession->closeByDevice();
+        mCurrentSession = nullptr;
+    }
+}
+
+camera_status_t
+CameraDevice::stopRepeatingLocked() {
+    camera_status_t ret = checkCameraClosedOrErrorLocked();
+    if (ret != ACAMERA_OK) {
+        ALOGE("Camera %s stop repeating failed! ret %d", getId(), ret);
+        return ret;
+    }
+    if (mRepeatingSequenceId != REQUEST_ID_NONE) {
+        int repeatingSequenceId = mRepeatingSequenceId;
+        mRepeatingSequenceId = REQUEST_ID_NONE;
+
+        int64_t lastFrameNumber;
+        binder::Status remoteRet = mRemote->cancelRequest(repeatingSequenceId, &lastFrameNumber);
+        if (remoteRet.serviceSpecificErrorCode() ==
+                hardware::ICameraService::ERROR_ILLEGAL_ARGUMENT) {
+            ALOGV("Repeating request is already stopped.");
+            return ACAMERA_OK;
+        } else if (!remoteRet.isOk()) {
+            ALOGE("Stop repeating request fails in remote: %s", remoteRet.toString8().string());
+            return ACAMERA_ERROR_UNKNOWN;
+        }
+        checkRepeatingSequenceCompleteLocked(repeatingSequenceId, lastFrameNumber);
+    }
+    return ACAMERA_OK;
+}
+
+camera_status_t
+CameraDevice::flushLocked(ACameraCaptureSession* session) {
+    camera_status_t ret = checkCameraClosedOrErrorLocked();
+    if (ret != ACAMERA_OK) {
+        ALOGE("Camera %s abort captures failed! ret %d", getId(), ret);
+        return ret;
+    }
+
+    // This should never happen because creating a new session will close
+    // previous one and thus reject any API call from previous session.
+    // But still good to check here in case something unexpected happen.
+    if (session != mCurrentSession) {
+        ALOGE("Camera %s session %p is not current active session!", getId(), session);
+        return ACAMERA_ERROR_INVALID_OPERATION;
+    }
+
+    if (mFlushing) {
+        ALOGW("Camera %s is already aborting captures", getId());
+        return ACAMERA_OK;
+    }
+
+    mFlushing = true;
+    // Send onActive callback to guarantee there is always active->ready transition
+    sp<AMessage> msg = new AMessage(kWhatSessionStateCb, mHandler);
+    msg->setPointer(kContextKey, session->mUserSessionCallback.context);
+    msg->setObject(kSessionSpKey, session);
+    msg->setPointer(kCallbackFpKey, (void*) session->mUserSessionCallback.onActive);
+    msg->post();
+
+    // If device is already idling, send callback and exit early
+    if (mIdle) {
+        sp<AMessage> msg = new AMessage(kWhatSessionStateCb, mHandler);
+        msg->setPointer(kContextKey, session->mUserSessionCallback.context);
+        msg->setObject(kSessionSpKey, session);
+        msg->setPointer(kCallbackFpKey, (void*) session->mUserSessionCallback.onReady);
+        msg->post();
+        mFlushing = false;
+        return ACAMERA_OK;
+    }
+
+    int64_t lastFrameNumber;
+    binder::Status remoteRet = mRemote->flush(&lastFrameNumber);
+    if (!remoteRet.isOk()) {
+        ALOGE("Abort captures fails in remote: %s", remoteRet.toString8().string());
+        return ACAMERA_ERROR_UNKNOWN;
+    }
+    if (mRepeatingSequenceId != REQUEST_ID_NONE) {
+        checkRepeatingSequenceCompleteLocked(mRepeatingSequenceId, lastFrameNumber);
+    }
+    return ACAMERA_OK;
+}
+
+camera_status_t
+CameraDevice::waitUntilIdleLocked() {
+    camera_status_t ret = checkCameraClosedOrErrorLocked();
+    if (ret != ACAMERA_OK) {
+        ALOGE("Wait until camera %s idle failed! ret %d", getId(), ret);
+        return ret;
+    }
+
+    if (mRepeatingSequenceId != REQUEST_ID_NONE) {
+        ALOGE("Camera device %s won't go to idle when there is repeating request!", getId());
+        return ACAMERA_ERROR_INVALID_OPERATION;
+    }
+
+    binder::Status remoteRet = mRemote->waitUntilIdle();
+    if (!remoteRet.isOk()) {
+        ALOGE("Camera device %s waitUntilIdle failed: %s", getId(), remoteRet.toString8().string());
+        // TODO: define a function to convert status_t -> camera_status_t
+        return ACAMERA_ERROR_UNKNOWN;
+    }
+
+    return ACAMERA_OK;
+}
+
+camera_status_t
+CameraDevice::getIGBPfromAnw(
+        ANativeWindow* anw,
+        sp<IGraphicBufferProducer>& out) {
+    if (anw == nullptr) {
+        ALOGE("Error: output ANativeWindow is null");
+        return ACAMERA_ERROR_INVALID_PARAMETER;
+    }
+    int value;
+    int err = (*anw->query)(anw, NATIVE_WINDOW_CONCRETE_TYPE, &value);
+    if (err != OK || value != NATIVE_WINDOW_SURFACE) {
+        ALOGE("Error: ANativeWindow is not backed by Surface!");
+        return ACAMERA_ERROR_INVALID_PARAMETER;
+    }
+    const sp<Surface> surface(static_cast<Surface*>(anw));
+    out = surface->getIGraphicBufferProducer();
+    return ACAMERA_OK;
+}
+
+camera_status_t
+CameraDevice::getSurfaceFromANativeWindow(
+        ANativeWindow* anw, sp<Surface>& out) {
+    if (anw == nullptr) {
+        ALOGE("Error: output ANativeWindow is null");
+        return ACAMERA_ERROR_INVALID_PARAMETER;
+    }
+    int value;
+    int err = (*anw->query)(anw, NATIVE_WINDOW_CONCRETE_TYPE, &value);
+    if (err != OK || value != NATIVE_WINDOW_SURFACE) {
+        ALOGE("Error: ANativeWindow is not backed by Surface!");
+        return ACAMERA_ERROR_INVALID_PARAMETER;
+    }
+    sp<Surface> surface(static_cast<Surface*>(anw));
+    out = surface;
+    return ACAMERA_OK;
+}
+
+camera_status_t
+CameraDevice::configureStreamsLocked(const ACaptureSessionOutputContainer* outputs) {
+    ACaptureSessionOutputContainer emptyOutput;
+    if (outputs == nullptr) {
+        outputs = &emptyOutput;
+    }
+
+    camera_status_t ret = checkCameraClosedOrErrorLocked();
+    if (ret != ACAMERA_OK) {
+        return ret;
+    }
+
+    std::set<std::pair<ANativeWindow*, OutputConfiguration>> outputSet;
+    for (auto outConfig : outputs->mOutputs) {
+        ANativeWindow* anw = outConfig.mWindow;
+        sp<IGraphicBufferProducer> iGBP(nullptr);
+        ret = getIGBPfromAnw(anw, iGBP);
+        if (ret != ACAMERA_OK) {
+            return ret;
+        }
+        outputSet.insert(std::make_pair(
+                anw, OutputConfiguration(iGBP, outConfig.mRotation)));
+    }
+    auto addSet = outputSet;
+    std::vector<int> deleteList;
+
+    // Determine which streams need to be created, which to be deleted
+    for (auto& kvPair : mConfiguredOutputs) {
+        int streamId = kvPair.first;
+        auto& outputPair = kvPair.second;
+        if (outputSet.count(outputPair) == 0) {
+            deleteList.push_back(streamId); // Need to delete a no longer needed stream
+        } else {
+            addSet.erase(outputPair);        // No need to add already existing stream
+        }
+    }
+
+    ret = stopRepeatingLocked();
+    if (ret != ACAMERA_OK) {
+        ALOGE("Camera device %s stop repeating failed, ret %d", getId(), ret);
+        return ret;
+    }
+
+    ret = waitUntilIdleLocked();
+    if (ret != ACAMERA_OK) {
+        ALOGE("Camera device %s wait until idle failed, ret %d", getId(), ret);
+        return ret;
+    }
+
+    // Send onReady to previous session
+    // CurrentSession will be updated after configureStreamLocked, so here
+    // mCurrentSession is the session to be replaced by a new session
+    if (!mIdle && mCurrentSession != nullptr) {
+        if (mBusySession != mCurrentSession) {
+            ALOGE("Current session != busy session");
+            setCameraDeviceErrorLocked(ACAMERA_ERROR_CAMERA_DEVICE);
+            return ACAMERA_ERROR_CAMERA_DEVICE;
+        }
+        sp<AMessage> msg = new AMessage(kWhatSessionStateCb, mHandler);
+        msg->setPointer(kContextKey, mBusySession->mUserSessionCallback.context);
+        msg->setObject(kSessionSpKey, mBusySession);
+        msg->setPointer(kCallbackFpKey, (void*) mBusySession->mUserSessionCallback.onReady);
+        mBusySession.clear();
+        msg->post();
+    }
+    mIdle = true;
+
+    binder::Status remoteRet = mRemote->beginConfigure();
+    if (!remoteRet.isOk()) {
+        ALOGE("Camera device %s begin configure failed: %s", getId(), remoteRet.toString8().string());
+        return ACAMERA_ERROR_UNKNOWN;
+    }
+
+    // delete to-be-deleted streams
+    for (auto streamId : deleteList) {
+        remoteRet = mRemote->deleteStream(streamId);
+        if (!remoteRet.isOk()) {
+            ALOGE("Camera device %s failed to remove stream %d: %s", getId(), streamId,
+                    remoteRet.toString8().string());
+            return ACAMERA_ERROR_UNKNOWN;
+        }
+        mConfiguredOutputs.erase(streamId);
+    }
+
+    // add new streams
+    for (auto outputPair : addSet) {
+        int streamId;
+        remoteRet = mRemote->createStream(outputPair.second, &streamId);
+        if (!remoteRet.isOk()) {
+            ALOGE("Camera device %s failed to create stream: %s", getId(),
+                    remoteRet.toString8().string());
+            return ACAMERA_ERROR_UNKNOWN;
+        }
+        mConfiguredOutputs.insert(std::make_pair(streamId, outputPair));
+    }
+
+    remoteRet = mRemote->endConfigure(/*isConstrainedHighSpeed*/ false);
+    if (remoteRet.serviceSpecificErrorCode() == hardware::ICameraService::ERROR_ILLEGAL_ARGUMENT) {
+        ALOGE("Camera device %s cannnot support app output configuration: %s", getId(),
+                remoteRet.toString8().string());
+        return ACAMERA_ERROR_STREAM_CONFIGURE_FAIL;
+    } else if (!remoteRet.isOk()) {
+        ALOGE("Camera device %s end configure failed: %s", getId(), remoteRet.toString8().string());
+        return ACAMERA_ERROR_UNKNOWN;
+    }
+
+    return ACAMERA_OK;
+}
+
+void
+CameraDevice::setRemoteDevice(sp<hardware::camera2::ICameraDeviceUser> remote) {
+    Mutex::Autolock _l(mDeviceLock);
+    mRemote = remote;
+}
+
+camera_status_t
+CameraDevice::checkCameraClosedOrErrorLocked() const {
+    if (mRemote == nullptr) {
+        ALOGE("%s: camera device already closed", __FUNCTION__);
+        return ACAMERA_ERROR_CAMERA_DISCONNECTED;
+    }
+    if (mInError) {// triggered by onDeviceError
+        ALOGE("%s: camera device has encountered a serious error", __FUNCTION__);
+        return mError;
+    }
+    return ACAMERA_OK;
+}
+
+void
+CameraDevice::setCameraDeviceErrorLocked(camera_status_t error) {
+    mInError = true;
+    mError = error;
+    return;
+}
+
+void
+CameraDevice::FrameNumberTracker::updateTracker(int64_t frameNumber, bool isError) {
+    ALOGV("updateTracker frame %" PRId64 " isError %d", frameNumber, isError);
+    if (isError) {
+        mFutureErrorSet.insert(frameNumber);
+    } else if (frameNumber <= mCompletedFrameNumber) {
+        ALOGE("Frame number %" PRId64 " decreased! current fn %" PRId64,
+                frameNumber, mCompletedFrameNumber);
+        return;
+    } else {
+        if (frameNumber != mCompletedFrameNumber + 1) {
+            ALOGE("Frame number out of order. Expect %" PRId64 " but get %" PRId64,
+                    mCompletedFrameNumber + 1, frameNumber);
+            // Do not assert as in java implementation
+        }
+        mCompletedFrameNumber = frameNumber;
+    }
+    update();
+}
+
+void
+CameraDevice::FrameNumberTracker::update() {
+    for (auto it = mFutureErrorSet.begin(); it != mFutureErrorSet.end();) {
+        int64_t errorFrameNumber = *it;
+        if (errorFrameNumber == mCompletedFrameNumber + 1) {
+            mCompletedFrameNumber++;
+            it = mFutureErrorSet.erase(it);
+        } else if (errorFrameNumber <= mCompletedFrameNumber) {
+            // This should not happen, but deal with it anyway
+            ALOGE("Completd frame number passed through current frame number!");
+            // erase the old error since it's no longer useful
+            it = mFutureErrorSet.erase(it);
+        } else {
+            // Normal requests hasn't catched up error frames, just break
+            break;
+        }
+    }
+    ALOGV("Update complete frame %" PRId64, mCompletedFrameNumber);
+}
+
+void
+CameraDevice::onCaptureErrorLocked(
+        int32_t errorCode,
+        const CaptureResultExtras& resultExtras) {
+    int sequenceId = resultExtras.requestId;
+    int64_t frameNumber = resultExtras.frameNumber;
+    int32_t burstId = resultExtras.burstId;
+    auto it = mSequenceCallbackMap.find(sequenceId);
+    if (it == mSequenceCallbackMap.end()) {
+        ALOGE("%s: Error: capture sequence index %d not found!",
+                __FUNCTION__, sequenceId);
+        setCameraDeviceErrorLocked(ACAMERA_ERROR_CAMERA_SERVICE);
+        return;
+    }
+
+    CallbackHolder cbh = (*it).second;
+    sp<ACameraCaptureSession> session = cbh.mSession;
+    if ((size_t) burstId >= cbh.mRequests.size()) {
+        ALOGE("%s: Error: request index %d out of bound (size %zu)",
+                __FUNCTION__, burstId, cbh.mRequests.size());
+        setCameraDeviceErrorLocked(ACAMERA_ERROR_CAMERA_SERVICE);
+        return;
+    }
+    sp<CaptureRequest> request = cbh.mRequests[burstId];
+
+    // Handle buffer error
+    if (errorCode == hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_BUFFER) {
+        int32_t streamId = resultExtras.errorStreamId;
+        ACameraCaptureSession_captureCallback_bufferLost onBufferLost =
+                cbh.mCallbacks.onCaptureBufferLost;
+        auto outputPairIt = mConfiguredOutputs.find(streamId);
+        if (outputPairIt == mConfiguredOutputs.end()) {
+            ALOGE("%s: Error: stream id %d does not exist", __FUNCTION__, streamId);
+            setCameraDeviceErrorLocked(ACAMERA_ERROR_CAMERA_SERVICE);
+            return;
+        }
+        ANativeWindow* anw = outputPairIt->second.first;
+
+        ALOGV("Camera %s Lost output buffer for ANW %p frame %" PRId64,
+                getId(), anw, frameNumber);
+
+        sp<AMessage> msg = new AMessage(kWhatCaptureBufferLost, mHandler);
+        msg->setPointer(kContextKey, cbh.mCallbacks.context);
+        msg->setObject(kSessionSpKey, session);
+        msg->setPointer(kCallbackFpKey, (void*) onBufferLost);
+        msg->setObject(kCaptureRequestKey, request);
+        msg->setPointer(kAnwKey, (void*) anw);
+        msg->setInt64(kFrameNumberKey, frameNumber);
+        msg->post();
+    } else { // Handle other capture failures
+        // Fire capture failure callback if there is one registered
+        ACameraCaptureSession_captureCallback_failed onError = cbh.mCallbacks.onCaptureFailed;
+        sp<CameraCaptureFailure> failure(new CameraCaptureFailure());
+        failure->frameNumber = frameNumber;
+        // TODO: refine this when implementing flush
+        failure->reason      = CAPTURE_FAILURE_REASON_ERROR;
+        failure->sequenceId  = sequenceId;
+        failure->wasImageCaptured = (errorCode ==
+                hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_RESULT);
+
+        sp<AMessage> msg = new AMessage(kWhatCaptureFail, mHandler);
+        msg->setPointer(kContextKey, cbh.mCallbacks.context);
+        msg->setObject(kSessionSpKey, session);
+        msg->setPointer(kCallbackFpKey, (void*) onError);
+        msg->setObject(kCaptureRequestKey, request);
+        msg->setObject(kCaptureFailureKey, failure);
+        msg->post();
+
+        // Update tracker
+        mFrameNumberTracker.updateTracker(frameNumber, /*isError*/true);
+        checkAndFireSequenceCompleteLocked();
+    }
+    return;
+}
+
+void CameraDevice::CallbackHandler::onMessageReceived(
+        const sp<AMessage> &msg) {
+    switch (msg->what()) {
+        case kWhatOnDisconnected:
+        case kWhatOnError:
+        case kWhatSessionStateCb:
+        case kWhatCaptureStart:
+        case kWhatCaptureResult:
+        case kWhatCaptureFail:
+        case kWhatCaptureSeqEnd:
+        case kWhatCaptureSeqAbort:
+        case kWhatCaptureBufferLost:
+            ALOGV("%s: Received msg %d", __FUNCTION__, msg->what());
+            break;
+        default:
+            ALOGE("%s:Error: unknown device callback %d", __FUNCTION__, msg->what());
+            return;
+    }
+    // Check the common part of all message
+    void* context;
+    bool found = msg->findPointer(kContextKey, &context);
+    if (!found) {
+        ALOGE("%s: Cannot find callback context!", __FUNCTION__);
+        return;
+    }
+    switch (msg->what()) {
+        case kWhatOnDisconnected:
+        {
+            ACameraDevice* dev;
+            found = msg->findPointer(kDeviceKey, (void**) &dev);
+            if (!found || dev == nullptr) {
+                ALOGE("%s: Cannot find device pointer!", __FUNCTION__);
+                return;
+            }
+            ACameraDevice_StateCallback onDisconnected;
+            found = msg->findPointer(kCallbackFpKey, (void**) &onDisconnected);
+            if (!found) {
+                ALOGE("%s: Cannot find onDisconnected!", __FUNCTION__);
+                return;
+            }
+            if (onDisconnected == nullptr) {
+                return;
+            }
+            (*onDisconnected)(context, dev);
+            break;
+        }
+        case kWhatOnError:
+        {
+            ACameraDevice* dev;
+            found = msg->findPointer(kDeviceKey, (void**) &dev);
+            if (!found || dev == nullptr) {
+                ALOGE("%s: Cannot find device pointer!", __FUNCTION__);
+                return;
+            }
+            ACameraDevice_ErrorStateCallback onError;
+            found = msg->findPointer(kCallbackFpKey, (void**) &onError);
+            if (!found) {
+                ALOGE("%s: Cannot find onError!", __FUNCTION__);
+                return;
+            }
+            int errorCode;
+            found = msg->findInt32(kErrorCodeKey, &errorCode);
+            if (!found) {
+                ALOGE("%s: Cannot find error code!", __FUNCTION__);
+                return;
+            }
+            if (onError == nullptr) {
+                return;
+            }
+            (*onError)(context, dev, errorCode);
+            break;
+        }
+        case kWhatSessionStateCb:
+        case kWhatCaptureStart:
+        case kWhatCaptureResult:
+        case kWhatCaptureFail:
+        case kWhatCaptureSeqEnd:
+        case kWhatCaptureSeqAbort:
+        case kWhatCaptureBufferLost:
+        {
+            sp<RefBase> obj;
+            found = msg->findObject(kSessionSpKey, &obj);
+            if (!found || obj == nullptr) {
+                ALOGE("%s: Cannot find session pointer!", __FUNCTION__);
+                return;
+            }
+            sp<ACameraCaptureSession> session(static_cast<ACameraCaptureSession*>(obj.get()));
+            sp<CaptureRequest> requestSp = nullptr;
+            switch (msg->what()) {
+                case kWhatCaptureStart:
+                case kWhatCaptureResult:
+                case kWhatCaptureFail:
+                case kWhatCaptureBufferLost:
+                    found = msg->findObject(kCaptureRequestKey, &obj);
+                    if (!found) {
+                        ALOGE("%s: Cannot find capture request!", __FUNCTION__);
+                        return;
+                    }
+                    requestSp = static_cast<CaptureRequest*>(obj.get());
+                    break;
+            }
+
+            switch (msg->what()) {
+                case kWhatSessionStateCb:
+                {
+                    ACameraCaptureSession_stateCallback onState;
+                    found = msg->findPointer(kCallbackFpKey, (void**) &onState);
+                    if (!found) {
+                        ALOGE("%s: Cannot find state callback!", __FUNCTION__);
+                        return;
+                    }
+                    if (onState == nullptr) {
+                        return;
+                    }
+                    (*onState)(context, session.get());
+                    break;
+                }
+                case kWhatCaptureStart:
+                {
+                    ACameraCaptureSession_captureCallback_start onStart;
+                    found = msg->findPointer(kCallbackFpKey, (void**) &onStart);
+                    if (!found) {
+                        ALOGE("%s: Cannot find capture start callback!", __FUNCTION__);
+                        return;
+                    }
+                    if (onStart == nullptr) {
+                        return;
+                    }
+                    int64_t timestamp;
+                    found = msg->findInt64(kTimeStampKey, &timestamp);
+                    if (!found) {
+                        ALOGE("%s: Cannot find timestamp!", __FUNCTION__);
+                        return;
+                    }
+                    ACaptureRequest* request = allocateACaptureRequest(requestSp);
+                    (*onStart)(context, session.get(), request, timestamp);
+                    freeACaptureRequest(request);
+                    break;
+                }
+                case kWhatCaptureResult:
+                {
+                    ACameraCaptureSession_captureCallback_result onResult;
+                    found = msg->findPointer(kCallbackFpKey, (void**) &onResult);
+                    if (!found) {
+                        ALOGE("%s: Cannot find capture result callback!", __FUNCTION__);
+                        return;
+                    }
+                    if (onResult == nullptr) {
+                        return;
+                    }
+
+                    found = msg->findObject(kCaptureResultKey, &obj);
+                    if (!found) {
+                        ALOGE("%s: Cannot find capture result!", __FUNCTION__);
+                        return;
+                    }
+                    sp<ACameraMetadata> result(static_cast<ACameraMetadata*>(obj.get()));
+                    ACaptureRequest* request = allocateACaptureRequest(requestSp);
+                    (*onResult)(context, session.get(), request, result.get());
+                    freeACaptureRequest(request);
+                    break;
+                }
+                case kWhatCaptureFail:
+                {
+                    ACameraCaptureSession_captureCallback_failed onFail;
+                    found = msg->findPointer(kCallbackFpKey, (void**) &onFail);
+                    if (!found) {
+                        ALOGE("%s: Cannot find capture fail callback!", __FUNCTION__);
+                        return;
+                    }
+                    if (onFail == nullptr) {
+                        return;
+                    }
+
+                    found = msg->findObject(kCaptureFailureKey, &obj);
+                    if (!found) {
+                        ALOGE("%s: Cannot find capture failure!", __FUNCTION__);
+                        return;
+                    }
+                    sp<CameraCaptureFailure> failureSp(
+                            static_cast<CameraCaptureFailure*>(obj.get()));
+                    ACameraCaptureFailure* failure =
+                            static_cast<ACameraCaptureFailure*>(failureSp.get());
+                    ACaptureRequest* request = allocateACaptureRequest(requestSp);
+                    (*onFail)(context, session.get(), request, failure);
+                    freeACaptureRequest(request);
+                    delete failure;
+                    break;
+                }
+                case kWhatCaptureSeqEnd:
+                {
+                    ACameraCaptureSession_captureCallback_sequenceEnd onSeqEnd;
+                    found = msg->findPointer(kCallbackFpKey, (void**) &onSeqEnd);
+                    if (!found) {
+                        ALOGE("%s: Cannot find sequence end callback!", __FUNCTION__);
+                        return;
+                    }
+                    if (onSeqEnd == nullptr) {
+                        return;
+                    }
+                    int seqId;
+                    found = msg->findInt32(kSequenceIdKey, &seqId);
+                    if (!found) {
+                        ALOGE("%s: Cannot find frame number!", __FUNCTION__);
+                        return;
+                    }
+                    int64_t frameNumber;
+                    found = msg->findInt64(kFrameNumberKey, &frameNumber);
+                    if (!found) {
+                        ALOGE("%s: Cannot find frame number!", __FUNCTION__);
+                        return;
+                    }
+                    (*onSeqEnd)(context, session.get(), seqId, frameNumber);
+                    break;
+                }
+                case kWhatCaptureSeqAbort:
+                {
+                    ACameraCaptureSession_captureCallback_sequenceAbort onSeqAbort;
+                    found = msg->findPointer(kCallbackFpKey, (void**) &onSeqAbort);
+                    if (!found) {
+                        ALOGE("%s: Cannot find sequence end callback!", __FUNCTION__);
+                        return;
+                    }
+                    if (onSeqAbort == nullptr) {
+                        return;
+                    }
+                    int seqId;
+                    found = msg->findInt32(kSequenceIdKey, &seqId);
+                    if (!found) {
+                        ALOGE("%s: Cannot find frame number!", __FUNCTION__);
+                        return;
+                    }
+                    (*onSeqAbort)(context, session.get(), seqId);
+                    break;
+                }
+                case kWhatCaptureBufferLost:
+                {
+                    ACameraCaptureSession_captureCallback_bufferLost onBufferLost;
+                    found = msg->findPointer(kCallbackFpKey, (void**) &onBufferLost);
+                    if (!found) {
+                        ALOGE("%s: Cannot find buffer lost callback!", __FUNCTION__);
+                        return;
+                    }
+                    if (onBufferLost == nullptr) {
+                        return;
+                    }
+
+                    ANativeWindow* anw;
+                    found = msg->findPointer(kAnwKey, (void**) &anw);
+                    if (!found) {
+                        ALOGE("%s: Cannot find ANativeWindow!", __FUNCTION__);
+                        return;
+                    }
+
+                    int64_t frameNumber;
+                    found = msg->findInt64(kFrameNumberKey, &frameNumber);
+                    if (!found) {
+                        ALOGE("%s: Cannot find frame number!", __FUNCTION__);
+                        return;
+                    }
+
+                    ACaptureRequest* request = allocateACaptureRequest(requestSp);
+                    (*onBufferLost)(context, session.get(), request, anw, frameNumber);
+                    freeACaptureRequest(request);
+                    break;
+                }
+            }
+            break;
+        }
+    }
+}
+
+CameraDevice::CallbackHolder::CallbackHolder(
+    sp<ACameraCaptureSession>          session,
+    const Vector<sp<CaptureRequest> >& requests,
+    bool                               isRepeating,
+    ACameraCaptureSession_captureCallbacks* cbs) :
+    mSession(session), mRequests(requests),
+    mIsRepeating(isRepeating), mCallbacks(fillCb(cbs)) {}
+
+void
+CameraDevice::checkRepeatingSequenceCompleteLocked(
+    const int sequenceId, const int64_t lastFrameNumber) {
+    ALOGV("Repeating seqId %d lastFrameNumer %" PRId64, sequenceId, lastFrameNumber);
+    if (lastFrameNumber == NO_FRAMES_CAPTURED) {
+        if (mSequenceCallbackMap.count(sequenceId) == 0) {
+            ALOGW("No callback found for sequenceId %d", sequenceId);
+            return;
+        }
+        // remove callback holder from callback map
+        auto cbIt = mSequenceCallbackMap.find(sequenceId);
+        CallbackHolder cbh = cbIt->second;
+        mSequenceCallbackMap.erase(cbIt);
+        // send seq aborted callback
+        sp<AMessage> msg = new AMessage(kWhatCaptureSeqAbort, mHandler);
+        msg->setPointer(kContextKey, cbh.mCallbacks.context);
+        msg->setObject(kSessionSpKey, cbh.mSession);
+        msg->setPointer(kCallbackFpKey, (void*) cbh.mCallbacks.onCaptureSequenceAborted);
+        msg->setInt32(kSequenceIdKey, sequenceId);
+        msg->post();
+    } else {
+        // Use mSequenceLastFrameNumberMap to track
+        mSequenceLastFrameNumberMap.insert(std::make_pair(sequenceId, lastFrameNumber));
+
+        // Last frame might have arrived. Check now
+        checkAndFireSequenceCompleteLocked();
+    }
+}
+
+void
+CameraDevice::checkAndFireSequenceCompleteLocked() {
+    int64_t completedFrameNumber = mFrameNumberTracker.getCompletedFrameNumber();
+    //std::map<int, int64_t> mSequenceLastFrameNumberMap;
+    auto it = mSequenceLastFrameNumberMap.begin();
+    while (it != mSequenceLastFrameNumberMap.end()) {
+        int sequenceId = it->first;
+        int64_t lastFrameNumber = it->second;
+        bool seqCompleted = false;
+        bool hasCallback  = true;
+
+        if (mRemote == nullptr) {
+            ALOGW("Camera %s closed while checking sequence complete", getId());
+            return;
+        }
+
+        // Check if there is callback for this sequence
+        // This should not happen because we always register callback (with nullptr inside)
+        if (mSequenceCallbackMap.count(sequenceId) == 0) {
+            ALOGW("No callback found for sequenceId %d", sequenceId);
+            hasCallback = false;
+        }
+
+        if (lastFrameNumber <= completedFrameNumber) {
+            ALOGV("seq %d reached last frame %" PRId64 ", completed %" PRId64,
+                    sequenceId, lastFrameNumber, completedFrameNumber);
+            seqCompleted = true;
+        }
+
+        if (seqCompleted && hasCallback) {
+            // remove callback holder from callback map
+            auto cbIt = mSequenceCallbackMap.find(sequenceId);
+            CallbackHolder cbh = cbIt->second;
+            mSequenceCallbackMap.erase(cbIt);
+            // send seq complete callback
+            sp<AMessage> msg = new AMessage(kWhatCaptureSeqEnd, mHandler);
+            msg->setPointer(kContextKey, cbh.mCallbacks.context);
+            msg->setObject(kSessionSpKey, cbh.mSession);
+            msg->setPointer(kCallbackFpKey, (void*) cbh.mCallbacks.onCaptureSequenceCompleted);
+            msg->setInt32(kSequenceIdKey, sequenceId);
+            msg->setInt64(kFrameNumberKey, lastFrameNumber);
+
+            // Clear the session sp before we send out the message
+            // This will guarantee the rare case where the message is processed
+            // before cbh goes out of scope and causing we call the session
+            // destructor while holding device lock
+            cbh.mSession.clear();
+            msg->post();
+        }
+
+        // No need to track sequence complete if there is no callback registered
+        if (seqCompleted || !hasCallback) {
+            it = mSequenceLastFrameNumberMap.erase(it);
+        } else {
+            ++it;
+        }
+    }
+}
+
+/**
+  * Camera service callback implementation
+  */
+binder::Status
+CameraDevice::ServiceCallback::onDeviceError(
+        int32_t errorCode,
+        const CaptureResultExtras& resultExtras) {
+    ALOGD("Device error received, code %d, frame number %" PRId64 ", request ID %d, subseq ID %d",
+            errorCode, resultExtras.frameNumber, resultExtras.requestId, resultExtras.burstId);
+    binder::Status ret = binder::Status::ok();
+    sp<CameraDevice> dev = mDevice.promote();
+    if (dev == nullptr) {
+        return ret; // device has been closed
+    }
+
+    Mutex::Autolock _l(dev->mDeviceLock);
+    if (dev->mRemote == nullptr) {
+        return ret; // device has been closed
+    }
+    switch (errorCode) {
+        case ERROR_CAMERA_DISCONNECTED:
+        {
+            // Camera is disconnected, close the session and expect no more callbacks
+            if (dev->mCurrentSession != nullptr) {
+                dev->mCurrentSession->closeByDevice();
+                dev->mCurrentSession = nullptr;
+            }
+            sp<AMessage> msg = new AMessage(kWhatOnDisconnected, dev->mHandler);
+            msg->setPointer(kContextKey, dev->mAppCallbacks.context);
+            msg->setPointer(kDeviceKey, (void*) dev->getWrapper());
+            msg->setPointer(kCallbackFpKey, (void*) dev->mAppCallbacks.onDisconnected);
+            msg->post();
+            break;
+        }
+        default:
+            ALOGE("Unknown error from camera device: %d", errorCode);
+            // no break
+        case ERROR_CAMERA_DEVICE:
+        case ERROR_CAMERA_SERVICE:
+        {
+            switch (errorCode) {
+                case ERROR_CAMERA_DEVICE:
+                    dev->setCameraDeviceErrorLocked(ACAMERA_ERROR_CAMERA_DEVICE);
+                    break;
+                case ERROR_CAMERA_SERVICE:
+                    dev->setCameraDeviceErrorLocked(ACAMERA_ERROR_CAMERA_SERVICE);
+                    break;
+                default:
+                    dev->setCameraDeviceErrorLocked(ACAMERA_ERROR_UNKNOWN);
+                    break;
+            }
+            sp<AMessage> msg = new AMessage(kWhatOnError, dev->mHandler);
+            msg->setPointer(kContextKey, dev->mAppCallbacks.context);
+            msg->setPointer(kDeviceKey, (void*) dev->getWrapper());
+            msg->setPointer(kCallbackFpKey, (void*) dev->mAppCallbacks.onError);
+            msg->setInt32(kErrorCodeKey, errorCode);
+            msg->post();
+            break;
+        }
+        case ERROR_CAMERA_REQUEST:
+        case ERROR_CAMERA_RESULT:
+        case ERROR_CAMERA_BUFFER:
+            dev->onCaptureErrorLocked(errorCode, resultExtras);
+            break;
+    }
+    return ret;
+}
+
+binder::Status
+CameraDevice::ServiceCallback::onDeviceIdle() {
+    ALOGV("Camera is now idle");
+    binder::Status ret = binder::Status::ok();
+    sp<CameraDevice> dev = mDevice.promote();
+    if (dev == nullptr) {
+        return ret; // device has been closed
+    }
+
+    Mutex::Autolock _l(dev->mDeviceLock);
+    if (dev->isClosed() || dev->mRemote == nullptr) {
+        return ret;
+    }
+
+    if (dev->mIdle) {
+        // Already in idle state. Possibly other thread did waitUntilIdle
+        return ret;
+    }
+
+    if (dev->mCurrentSession != nullptr) {
+        ALOGE("onDeviceIdle sending state cb");
+        if (dev->mBusySession != dev->mCurrentSession) {
+            ALOGE("Current session != busy session");
+            dev->setCameraDeviceErrorLocked(ACAMERA_ERROR_CAMERA_DEVICE);
+            return ret;
+        }
+        sp<AMessage> msg = new AMessage(kWhatSessionStateCb, dev->mHandler);
+        msg->setPointer(kContextKey, dev->mBusySession->mUserSessionCallback.context);
+        msg->setObject(kSessionSpKey, dev->mBusySession);
+        msg->setPointer(kCallbackFpKey, (void*) dev->mBusySession->mUserSessionCallback.onReady);
+        // Make sure we clear the sp first so the session destructor can
+        // only happen on handler thread (where we don't hold device/session lock)
+        dev->mBusySession.clear();
+        msg->post();
+    }
+    dev->mIdle = true;
+    dev->mFlushing = false;
+    return ret;
+}
+
+binder::Status
+CameraDevice::ServiceCallback::onCaptureStarted(
+        const CaptureResultExtras& resultExtras,
+        int64_t timestamp) {
+    binder::Status ret = binder::Status::ok();
+
+    sp<CameraDevice> dev = mDevice.promote();
+    if (dev == nullptr) {
+        return ret; // device has been closed
+    }
+    Mutex::Autolock _l(dev->mDeviceLock);
+    if (dev->isClosed() || dev->mRemote == nullptr) {
+        return ret;
+    }
+
+    int sequenceId = resultExtras.requestId;
+    int32_t burstId = resultExtras.burstId;
+
+    auto it = dev->mSequenceCallbackMap.find(sequenceId);
+    if (it != dev->mSequenceCallbackMap.end()) {
+        CallbackHolder cbh = (*it).second;
+        ACameraCaptureSession_captureCallback_start onStart = cbh.mCallbacks.onCaptureStarted;
+        sp<ACameraCaptureSession> session = cbh.mSession;
+        if ((size_t) burstId >= cbh.mRequests.size()) {
+            ALOGE("%s: Error: request index %d out of bound (size %zu)",
+                    __FUNCTION__, burstId, cbh.mRequests.size());
+            dev->setCameraDeviceErrorLocked(ACAMERA_ERROR_CAMERA_SERVICE);
+        }
+        sp<CaptureRequest> request = cbh.mRequests[burstId];
+        sp<AMessage> msg = new AMessage(kWhatCaptureStart, dev->mHandler);
+        msg->setPointer(kContextKey, cbh.mCallbacks.context);
+        msg->setObject(kSessionSpKey, session);
+        msg->setPointer(kCallbackFpKey, (void*) onStart);
+        msg->setObject(kCaptureRequestKey, request);
+        msg->setInt64(kTimeStampKey, timestamp);
+        msg->post();
+    }
+    return ret;
+}
+
+binder::Status
+CameraDevice::ServiceCallback::onResultReceived(
+        const CameraMetadata& metadata,
+        const CaptureResultExtras& resultExtras) {
+    binder::Status ret = binder::Status::ok();
+
+    sp<CameraDevice> dev = mDevice.promote();
+    if (dev == nullptr) {
+        return ret; // device has been closed
+    }
+    int sequenceId = resultExtras.requestId;
+    int64_t frameNumber = resultExtras.frameNumber;
+    int32_t burstId = resultExtras.burstId;
+    bool    isPartialResult = (resultExtras.partialResultCount < dev->mPartialResultCount);
+
+    if (!isPartialResult) {
+        ALOGV("SeqId %d frame %" PRId64 " result arrive.", sequenceId, frameNumber);
+    }
+
+    Mutex::Autolock _l(dev->mDeviceLock);
+    if (dev->mRemote == nullptr) {
+        return ret; // device has been disconnected
+    }
+
+    if (dev->isClosed()) {
+        if (!isPartialResult) {
+            dev->mFrameNumberTracker.updateTracker(frameNumber, /*isError*/false);
+        }
+        // early return to avoid callback sent to closed devices
+        return ret;
+    }
+
+    CameraMetadata metadataCopy = metadata;
+    metadataCopy.update(ANDROID_LENS_INFO_SHADING_MAP_SIZE, dev->mShadingMapSize, /*data_count*/2);
+    metadataCopy.update(ANDROID_SYNC_FRAME_NUMBER, &frameNumber, /*data_count*/1);
+
+    auto it = dev->mSequenceCallbackMap.find(sequenceId);
+    if (it != dev->mSequenceCallbackMap.end()) {
+        CallbackHolder cbh = (*it).second;
+        ACameraCaptureSession_captureCallback_result onResult = isPartialResult ?
+                cbh.mCallbacks.onCaptureProgressed :
+                cbh.mCallbacks.onCaptureCompleted;
+        sp<ACameraCaptureSession> session = cbh.mSession;
+        if ((size_t) burstId >= cbh.mRequests.size()) {
+            ALOGE("%s: Error: request index %d out of bound (size %zu)",
+                    __FUNCTION__, burstId, cbh.mRequests.size());
+            dev->setCameraDeviceErrorLocked(ACAMERA_ERROR_CAMERA_SERVICE);
+        }
+        sp<CaptureRequest> request = cbh.mRequests[burstId];
+        sp<ACameraMetadata> result(new ACameraMetadata(
+                metadataCopy.release(), ACameraMetadata::ACM_RESULT));
+
+        sp<AMessage> msg = new AMessage(kWhatCaptureResult, dev->mHandler);
+        msg->setPointer(kContextKey, cbh.mCallbacks.context);
+        msg->setObject(kSessionSpKey, session);
+        msg->setPointer(kCallbackFpKey, (void*) onResult);
+        msg->setObject(kCaptureRequestKey, request);
+        msg->setObject(kCaptureResultKey, result);
+        msg->post();
+    }
+
+    if (!isPartialResult) {
+        dev->mFrameNumberTracker.updateTracker(frameNumber, /*isError*/false);
+        dev->checkAndFireSequenceCompleteLocked();
+    }
+
+    return ret;
+}
+
+binder::Status
+CameraDevice::ServiceCallback::onPrepared(int) {
+    // Prepare not yet implemented in NDK
+    return binder::Status::ok();
+}
+
+binder::Status
+CameraDevice::ServiceCallback::onRepeatingRequestError(int64_t lastFrameNumber) {
+    binder::Status ret = binder::Status::ok();
+
+    sp<CameraDevice> dev = mDevice.promote();
+    if (dev == nullptr) {
+        return ret; // device has been closed
+    }
+
+    Mutex::Autolock _l(dev->mDeviceLock);
+
+    int repeatingSequenceId = dev->mRepeatingSequenceId;
+    dev->mRepeatingSequenceId = REQUEST_ID_NONE;
+
+    dev->checkRepeatingSequenceCompleteLocked(repeatingSequenceId, lastFrameNumber);
+
+    return ret;
+}
+
+
+} // namespace android
diff --git a/camera/ndk/impl/ACameraDevice.h b/camera/ndk/impl/ACameraDevice.h
new file mode 100644
index 0000000..71e364d
--- /dev/null
+++ b/camera/ndk/impl/ACameraDevice.h
@@ -0,0 +1,317 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef _ACAMERA_DEVICE_H
+#define _ACAMERA_DEVICE_H
+
+#include <memory>
+#include <map>
+#include <set>
+#include <atomic>
+#include <utility>
+#include <utils/StrongPointer.h>
+#include <utils/Mutex.h>
+#include <utils/String8.h>
+#include <utils/List.h>
+#include <utils/Vector.h>
+
+#include <android/hardware/camera2/BnCameraDeviceCallbacks.h>
+#include <android/hardware/camera2/ICameraDeviceUser.h>
+#include <media/stagefright/foundation/ALooper.h>
+#include <media/stagefright/foundation/AHandler.h>
+#include <media/stagefright/foundation/AMessage.h>
+#include <camera/CaptureResult.h>
+#include <camera/camera2/OutputConfiguration.h>
+#include <camera/camera2/CaptureRequest.h>
+
+#include <NdkCameraDevice.h>
+#include "ACameraMetadata.h"
+
+namespace android {
+
+// Wrap ACameraCaptureFailure so it can be ref-counter
+struct CameraCaptureFailure : public RefBase, public ACameraCaptureFailure {};
+
+class CameraDevice final : public RefBase {
+  public:
+    CameraDevice(const char* id, ACameraDevice_StateCallbacks* cb,
+                  std::unique_ptr<ACameraMetadata> chars,
+                  ACameraDevice* wrapper);
+    ~CameraDevice();
+
+    inline const char* getId() const { return mCameraId.string(); }
+
+    camera_status_t createCaptureRequest(
+            ACameraDevice_request_template templateId,
+            ACaptureRequest** request) const;
+
+    camera_status_t createCaptureSession(
+            const ACaptureSessionOutputContainer*       outputs,
+            const ACameraCaptureSession_stateCallbacks* callbacks,
+            /*out*/ACameraCaptureSession** session);
+
+    // Callbacks from camera service
+    class ServiceCallback : public hardware::camera2::BnCameraDeviceCallbacks {
+      public:
+        ServiceCallback(CameraDevice* device) : mDevice(device) {}
+        binder::Status onDeviceError(int32_t errorCode,
+                           const CaptureResultExtras& resultExtras) override;
+        binder::Status onDeviceIdle() override;
+        binder::Status onCaptureStarted(const CaptureResultExtras& resultExtras,
+                              int64_t timestamp) override;
+        binder::Status onResultReceived(const CameraMetadata& metadata,
+                              const CaptureResultExtras& resultExtras) override;
+        binder::Status onPrepared(int streamId) override;
+        binder::Status onRepeatingRequestError(int64_t lastFrameNumber) override;
+      private:
+        const wp<CameraDevice> mDevice;
+    };
+    inline sp<hardware::camera2::ICameraDeviceCallbacks> getServiceCallback() {
+        return mServiceCallback;
+    };
+
+    // Camera device is only functional after remote being set
+    void setRemoteDevice(sp<hardware::camera2::ICameraDeviceUser> remote);
+
+    inline ACameraDevice* getWrapper() const { return mWrapper; };
+
+  private:
+    friend ACameraCaptureSession;
+    camera_status_t checkCameraClosedOrErrorLocked() const;
+
+    // device goes into fatal error state after this
+    void setCameraDeviceErrorLocked(camera_status_t error);
+
+    void disconnectLocked(); // disconnect from camera service
+
+    camera_status_t stopRepeatingLocked();
+
+    camera_status_t flushLocked(ACameraCaptureSession*);
+
+    camera_status_t waitUntilIdleLocked();
+
+
+    camera_status_t captureLocked(sp<ACameraCaptureSession> session,
+            /*optional*/ACameraCaptureSession_captureCallbacks* cbs,
+            int numRequests, ACaptureRequest** requests,
+            /*optional*/int* captureSequenceId);
+
+    camera_status_t setRepeatingRequestsLocked(sp<ACameraCaptureSession> session,
+            /*optional*/ACameraCaptureSession_captureCallbacks* cbs,
+            int numRequests, ACaptureRequest** requests,
+            /*optional*/int* captureSequenceId);
+
+    camera_status_t submitRequestsLocked(
+            sp<ACameraCaptureSession> session,
+            /*optional*/ACameraCaptureSession_captureCallbacks* cbs,
+            int numRequests, ACaptureRequest** requests,
+            /*out*/int* captureSequenceId,
+            bool isRepeating);
+
+    static camera_status_t allocateCaptureRequest(
+            const ACaptureRequest* request, sp<CaptureRequest>& outReq);
+
+    static ACaptureRequest* allocateACaptureRequest(sp<CaptureRequest>& req);
+    static void freeACaptureRequest(ACaptureRequest*);
+
+    // only For session to hold device lock
+    // Always grab device lock before grabbing session lock
+    void lockDeviceForSessionOps() const { mDeviceLock.lock(); };
+    void unlockDevice() const { mDeviceLock.unlock(); };
+
+    // For capture session to notify its end of life
+    void notifySessionEndOfLifeLocked(ACameraCaptureSession* session);
+
+    camera_status_t configureStreamsLocked(const ACaptureSessionOutputContainer* outputs);
+
+    static camera_status_t getIGBPfromAnw(
+            ANativeWindow* anw, sp<IGraphicBufferProducer>& out);
+
+    static camera_status_t getSurfaceFromANativeWindow(
+            ANativeWindow* anw, sp<Surface>& out);
+
+    mutable Mutex mDeviceLock;
+    const String8 mCameraId;                          // Camera ID
+    const ACameraDevice_StateCallbacks mAppCallbacks; // Callback to app
+    const std::unique_ptr<ACameraMetadata> mChars;    // Camera characteristics
+    const sp<ServiceCallback> mServiceCallback;
+    ACameraDevice* mWrapper;
+
+    // stream id -> pair of (ANW* from application, OutputConfiguration used for camera service)
+    std::map<int, std::pair<ANativeWindow*, OutputConfiguration>> mConfiguredOutputs;
+
+    // TODO: maybe a bool will suffice for synchronous implementation?
+    std::atomic_bool mClosing;
+    inline bool isClosed() { return mClosing; }
+
+    bool mInError = false;
+    camera_status_t mError = ACAMERA_OK;
+    void onCaptureErrorLocked(
+            int32_t errorCode,
+            const CaptureResultExtras& resultExtras);
+
+    bool mIdle = true;
+    // This will avoid a busy session being deleted before it's back to idle state
+    sp<ACameraCaptureSession> mBusySession;
+
+    sp<hardware::camera2::ICameraDeviceUser> mRemote;
+
+    // Looper thread to handle callback to app
+    sp<ALooper> mCbLooper;
+    // definition of handler and message
+    enum {
+        // Device state callbacks
+        kWhatOnDisconnected,   // onDisconnected
+        kWhatOnError,          // onError
+        // Session state callbacks
+        kWhatSessionStateCb,   // onReady, onActive
+        // Capture callbacks
+        kWhatCaptureStart,     // onCaptureStarted
+        kWhatCaptureResult,    // onCaptureProgressed, onCaptureCompleted
+        kWhatCaptureFail,      // onCaptureFailed
+        kWhatCaptureSeqEnd,    // onCaptureSequenceCompleted
+        kWhatCaptureSeqAbort,  // onCaptureSequenceAborted
+        kWhatCaptureBufferLost // onCaptureBufferLost
+    };
+    static const char* kContextKey;
+    static const char* kDeviceKey;
+    static const char* kErrorCodeKey;
+    static const char* kCallbackFpKey;
+    static const char* kSessionSpKey;
+    static const char* kCaptureRequestKey;
+    static const char* kTimeStampKey;
+    static const char* kCaptureResultKey;
+    static const char* kCaptureFailureKey;
+    static const char* kSequenceIdKey;
+    static const char* kFrameNumberKey;
+    static const char* kAnwKey;
+    class CallbackHandler : public AHandler {
+      public:
+        CallbackHandler() {}
+        void onMessageReceived(const sp<AMessage> &msg) override;
+    };
+    sp<CallbackHandler> mHandler;
+
+    /***********************************
+     * Capture session related members *
+     ***********************************/
+    // The current active session
+    ACameraCaptureSession* mCurrentSession = nullptr;
+    bool mFlushing = false;
+
+    int mNextSessionId = 0;
+    // TODO: might need another looper/handler to handle callbacks from service
+
+    static const int REQUEST_ID_NONE = -1;
+    int mRepeatingSequenceId = REQUEST_ID_NONE;
+
+    // sequence id -> last frame number map
+    std::map<int, int64_t> mSequenceLastFrameNumberMap;
+
+    struct CallbackHolder {
+        CallbackHolder(sp<ACameraCaptureSession>          session,
+                       const Vector<sp<CaptureRequest> >& requests,
+                       bool                               isRepeating,
+                       ACameraCaptureSession_captureCallbacks* cbs);
+
+        static ACameraCaptureSession_captureCallbacks fillCb(
+                ACameraCaptureSession_captureCallbacks* cbs) {
+            if (cbs != nullptr) {
+                return *cbs;
+            }
+            return { nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr };
+        }
+
+        sp<ACameraCaptureSession>   mSession;
+        Vector<sp<CaptureRequest> > mRequests;
+        const bool                  mIsRepeating;
+        ACameraCaptureSession_captureCallbacks mCallbacks;
+    };
+    // sequence id -> callbacks map
+    std::map<int, CallbackHolder> mSequenceCallbackMap;
+
+    static const int64_t NO_FRAMES_CAPTURED = -1;
+    class FrameNumberTracker {
+      public:
+        // TODO: Called in onResultReceived and onCaptureErrorLocked
+        void updateTracker(int64_t frameNumber, bool isError);
+        inline int64_t getCompletedFrameNumber() { return mCompletedFrameNumber; }
+      private:
+        void update();
+        void updateCompletedFrameNumber(int64_t frameNumber);
+
+        int64_t mCompletedFrameNumber = NO_FRAMES_CAPTURED;
+        List<int64_t> mSkippedFrameNumbers;
+        std::set<int64_t> mFutureErrorSet;
+    };
+    FrameNumberTracker mFrameNumberTracker;
+
+    void checkRepeatingSequenceCompleteLocked(const int sequenceId, const int64_t lastFrameNumber);
+    void checkAndFireSequenceCompleteLocked();
+
+    // Misc variables
+    int32_t mShadingMapSize[2];   // const after constructor
+    int32_t mPartialResultCount;  // const after constructor
+
+};
+
+} // namespace android;
+
+/**
+ * ACameraDevice opaque struct definition
+ * Leave outside of android namespace because it's NDK struct
+ */
+struct ACameraDevice {
+    ACameraDevice(const char* id, ACameraDevice_StateCallbacks* cb,
+                  std::unique_ptr<ACameraMetadata> chars) :
+            mDevice(new CameraDevice(id, cb, std::move(chars), this)) {}
+
+    ~ACameraDevice() {};
+
+    /*******************
+     * NDK public APIs *
+     *******************/
+    inline const char* getId() const { return mDevice->getId(); }
+
+    camera_status_t createCaptureRequest(
+            ACameraDevice_request_template templateId,
+            ACaptureRequest** request) const {
+        return mDevice->createCaptureRequest(templateId, request);
+    }
+
+    camera_status_t createCaptureSession(
+            const ACaptureSessionOutputContainer*       outputs,
+            const ACameraCaptureSession_stateCallbacks* callbacks,
+            /*out*/ACameraCaptureSession** session) {
+        return mDevice->createCaptureSession(outputs, callbacks, session);
+    }
+
+    /***********************
+     * Device interal APIs *
+     ***********************/
+    inline android::sp<android::hardware::camera2::ICameraDeviceCallbacks> getServiceCallback() {
+        return mDevice->getServiceCallback();
+    };
+
+    // Camera device is only functional after remote being set
+    inline void setRemoteDevice(android::sp<android::hardware::camera2::ICameraDeviceUser> remote) {
+        mDevice->setRemoteDevice(remote);
+    }
+
+  private:
+    android::sp<android::CameraDevice> mDevice;
+};
+
+#endif // _ACAMERA_DEVICE_H
diff --git a/camera/ndk/impl/ACameraManager.cpp b/camera/ndk/impl/ACameraManager.cpp
new file mode 100644
index 0000000..26d6679
--- /dev/null
+++ b/camera/ndk/impl/ACameraManager.cpp
@@ -0,0 +1,525 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "ACameraManager"
+
+#include <memory>
+#include "ACameraManager.h"
+#include "ACameraMetadata.h"
+#include "ACameraDevice.h"
+#include <utils/Vector.h>
+#include <stdlib.h>
+#include <camera/VendorTagDescriptor.h>
+
+using namespace android;
+
+//constants shared between ACameraManager and CameraManagerGlobal
+namespace {
+    const int kMaxCameraIdLen = 32;
+}
+
+namespace android {
+// Static member definitions
+const char* CameraManagerGlobal::kCameraIdKey   = "CameraId";
+const char* CameraManagerGlobal::kCallbackFpKey = "CallbackFp";
+const char* CameraManagerGlobal::kContextKey    = "CallbackContext";
+Mutex                CameraManagerGlobal::sLock;
+CameraManagerGlobal* CameraManagerGlobal::sInstance = nullptr;
+
+CameraManagerGlobal&
+CameraManagerGlobal::getInstance() {
+    Mutex::Autolock _l(sLock);
+    CameraManagerGlobal* instance = sInstance;
+    if (instance == nullptr) {
+        instance = new CameraManagerGlobal();
+        sInstance = instance;
+    }
+    return *instance;
+}
+
+CameraManagerGlobal::~CameraManagerGlobal() {
+    // clear sInstance so next getInstance call knows to create a new one
+    Mutex::Autolock _sl(sLock);
+    sInstance = nullptr;
+    Mutex::Autolock _l(mLock);
+    if (mCameraService != nullptr) {
+        IInterface::asBinder(mCameraService)->unlinkToDeath(mDeathNotifier);
+        mCameraService->removeListener(mCameraServiceListener);
+    }
+    mDeathNotifier.clear();
+    if (mCbLooper != nullptr) {
+        mCbLooper->unregisterHandler(mHandler->id());
+        mCbLooper->stop();
+    }
+    mCbLooper.clear();
+    mHandler.clear();
+    mCameraServiceListener.clear();
+    mCameraService.clear();
+}
+
+sp<hardware::ICameraService> CameraManagerGlobal::getCameraService() {
+    Mutex::Autolock _l(mLock);
+    if (mCameraService.get() == nullptr) {
+        sp<IServiceManager> sm = defaultServiceManager();
+        sp<IBinder> binder;
+        do {
+            binder = sm->getService(String16(kCameraServiceName));
+            if (binder != nullptr) {
+                break;
+            }
+            ALOGW("CameraService not published, waiting...");
+            usleep(kCameraServicePollDelay);
+        } while(true);
+        if (mDeathNotifier == nullptr) {
+            mDeathNotifier = new DeathNotifier(this);
+        }
+        binder->linkToDeath(mDeathNotifier);
+        mCameraService = interface_cast<hardware::ICameraService>(binder);
+
+        // Setup looper thread to perfrom availiability callbacks
+        if (mCbLooper == nullptr) {
+            mCbLooper = new ALooper;
+            mCbLooper->setName("C2N-mgr-looper");
+            status_t err = mCbLooper->start(
+                    /*runOnCallingThread*/false,
+                    /*canCallJava*/       true,
+                    PRIORITY_DEFAULT);
+            if (err != OK) {
+                ALOGE("%s: Unable to start camera service listener looper: %s (%d)",
+                        __FUNCTION__, strerror(-err), err);
+                mCbLooper.clear();
+                return nullptr;
+            }
+            if (mHandler == nullptr) {
+                mHandler = new CallbackHandler();
+            }
+            mCbLooper->registerHandler(mHandler);
+        }
+
+        // register ICameraServiceListener
+        if (mCameraServiceListener == nullptr) {
+            mCameraServiceListener = new CameraServiceListener(this);
+        }
+        mCameraService->addListener(mCameraServiceListener);
+
+        // setup vendor tags
+        sp<VendorTagDescriptor> desc = new VendorTagDescriptor();
+        binder::Status ret = mCameraService->getCameraVendorTagDescriptor(/*out*/desc.get());
+
+        if (ret.isOk()) {
+            status_t err = VendorTagDescriptor::setAsGlobalVendorTagDescriptor(desc);
+            if (err != OK) {
+                ALOGE("%s: Failed to set vendor tag descriptors, received error %s (%d)",
+                        __FUNCTION__, strerror(-err), err);
+            }
+        } else if (ret.serviceSpecificErrorCode() ==
+                hardware::ICameraService::ERROR_DEPRECATED_HAL) {
+            ALOGW("%s: Camera HAL too old; does not support vendor tags",
+                    __FUNCTION__);
+            VendorTagDescriptor::clearGlobalVendorTagDescriptor();
+        } else {
+            ALOGE("%s: Failed to get vendor tag descriptors: %s",
+                    __FUNCTION__, ret.toString8().string());
+        }
+    }
+    ALOGE_IF(mCameraService == nullptr, "no CameraService!?");
+    return mCameraService;
+}
+
+void CameraManagerGlobal::DeathNotifier::binderDied(const wp<IBinder>&)
+{
+    ALOGE("Camera service binderDied!");
+    sp<CameraManagerGlobal> cm = mCameraManager.promote();
+    if (cm != nullptr) {
+        AutoMutex lock(cm->mLock);
+        for (auto pair : cm->mDeviceStatusMap) {
+            int32_t cameraId = pair.first;
+            cm->onStatusChangedLocked(
+                    CameraServiceListener::STATUS_NOT_PRESENT, cameraId);
+        }
+        cm->mCameraService.clear();
+        // TODO: consider adding re-connect call here?
+    }
+}
+
+void CameraManagerGlobal::registerAvailabilityCallback(
+        const ACameraManager_AvailabilityCallbacks *callback) {
+    Mutex::Autolock _l(mLock);
+    Callback cb(callback);
+    auto pair = mCallbacks.insert(cb);
+    // Send initial callbacks if callback is newly registered
+    if (pair.second) {
+        for (auto pair : mDeviceStatusMap) {
+            int32_t cameraId = pair.first;
+            int32_t status = pair.second;
+
+            sp<AMessage> msg = new AMessage(kWhatSendSingleCallback, mHandler);
+            ACameraManager_AvailabilityCallback cb = isStatusAvailable(status) ?
+                    callback->onCameraAvailable : callback->onCameraUnavailable;
+            msg->setPointer(kCallbackFpKey, (void *) cb);
+            msg->setPointer(kContextKey, callback->context);
+            msg->setInt32(kCameraIdKey, cameraId);
+            msg->post();
+        }
+    }
+}
+
+void CameraManagerGlobal::unregisterAvailabilityCallback(
+        const ACameraManager_AvailabilityCallbacks *callback) {
+    Mutex::Autolock _l(mLock);
+    Callback cb(callback);
+    mCallbacks.erase(cb);
+}
+
+bool CameraManagerGlobal::validStatus(int32_t status) {
+    switch (status) {
+        case hardware::ICameraServiceListener::STATUS_NOT_PRESENT:
+        case hardware::ICameraServiceListener::STATUS_PRESENT:
+        case hardware::ICameraServiceListener::STATUS_ENUMERATING:
+        case hardware::ICameraServiceListener::STATUS_NOT_AVAILABLE:
+            return true;
+        default:
+            return false;
+    }
+}
+
+bool CameraManagerGlobal::isStatusAvailable(int32_t status) {
+    switch (status) {
+        case hardware::ICameraServiceListener::STATUS_PRESENT:
+            return true;
+        default:
+            return false;
+    }
+}
+
+void CameraManagerGlobal::CallbackHandler::sendSingleCallback(
+        int32_t cameraId, void* context,
+        ACameraManager_AvailabilityCallback cb) const {
+    char cameraIdStr[kMaxCameraIdLen];
+    snprintf(cameraIdStr, sizeof(cameraIdStr), "%d", cameraId);
+    (*cb)(context, cameraIdStr);
+}
+
+void CameraManagerGlobal::CallbackHandler::onMessageReceived(
+        const sp<AMessage> &msg) {
+    switch (msg->what()) {
+        case kWhatSendSingleCallback:
+        {
+            ACameraManager_AvailabilityCallback cb;
+            void* context;
+            int32_t cameraId;
+            bool found = msg->findPointer(kCallbackFpKey, (void**) &cb);
+            if (!found) {
+                ALOGE("%s: Cannot find camera callback fp!", __FUNCTION__);
+                return;
+            }
+            found = msg->findPointer(kContextKey, &context);
+            if (!found) {
+                ALOGE("%s: Cannot find callback context!", __FUNCTION__);
+                return;
+            }
+            found = msg->findInt32(kCameraIdKey, &cameraId);
+            if (!found) {
+                ALOGE("%s: Cannot find camera ID!", __FUNCTION__);
+                return;
+            }
+            sendSingleCallback(cameraId, context, cb);
+            break;
+        }
+        default:
+            ALOGE("%s: unknown message type %d", __FUNCTION__, msg->what());
+            break;
+    }
+}
+
+binder::Status CameraManagerGlobal::CameraServiceListener::onStatusChanged(
+        int32_t status, int32_t cameraId) {
+    sp<CameraManagerGlobal> cm = mCameraManager.promote();
+    if (cm != nullptr) {
+        cm->onStatusChanged(status, cameraId);
+    } else {
+        ALOGE("Cannot deliver status change. Global camera manager died");
+    }
+    return binder::Status::ok();
+}
+
+void CameraManagerGlobal::onStatusChanged(
+        int32_t status, int32_t cameraId) {
+    Mutex::Autolock _l(mLock);
+    onStatusChangedLocked(status, cameraId);
+}
+
+void CameraManagerGlobal::onStatusChangedLocked(
+        int32_t status, int32_t cameraId) {
+        if (!validStatus(status)) {
+            ALOGE("%s: Invalid status %d", __FUNCTION__, status);
+            return;
+        }
+
+        bool firstStatus = (mDeviceStatusMap.count(cameraId) == 0);
+        int32_t oldStatus = firstStatus ?
+                status : // first status
+                mDeviceStatusMap[cameraId];
+
+        if (!firstStatus &&
+                isStatusAvailable(status) == isStatusAvailable(oldStatus)) {
+            // No status update. No need to send callback
+            return;
+        }
+
+        // Iterate through all registered callbacks
+        mDeviceStatusMap[cameraId] = status;
+        for (auto cb : mCallbacks) {
+            sp<AMessage> msg = new AMessage(kWhatSendSingleCallback, mHandler);
+            ACameraManager_AvailabilityCallback cbFp = isStatusAvailable(status) ?
+                    cb.mAvailable : cb.mUnavailable;
+            msg->setPointer(kCallbackFpKey, (void *) cbFp);
+            msg->setPointer(kContextKey, cb.mContext);
+            msg->setInt32(kCameraIdKey, cameraId);
+            msg->post();
+        }
+}
+
+} // namespace android
+
+/**
+ * ACameraManger Implementation
+ */
+camera_status_t
+ACameraManager::getOrCreateCameraIdListLocked(ACameraIdList** cameraIdList) {
+    if (mCachedCameraIdList.numCameras == kCameraIdListNotInit) {
+        int numCameras = 0;
+        Vector<char *> cameraIds;
+        sp<hardware::ICameraService> cs = CameraManagerGlobal::getInstance().getCameraService();
+        if (cs == nullptr) {
+            ALOGE("%s: Cannot reach camera service!", __FUNCTION__);
+            return ACAMERA_ERROR_CAMERA_DISCONNECTED;
+        }
+        // Get number of cameras
+        int numAllCameras = 0;
+        binder::Status serviceRet = cs->getNumberOfCameras(hardware::ICameraService::CAMERA_TYPE_ALL,
+                &numAllCameras);
+        if (!serviceRet.isOk()) {
+            ALOGE("%s: Error getting camera count: %s", __FUNCTION__,
+                    serviceRet.toString8().string());
+            numAllCameras = 0;
+        }
+        // Filter API2 compatible cameras and push to cameraIds
+        for (int i = 0; i < numAllCameras; i++) {
+            // TODO: Only suppot HALs that supports API2 directly now
+            bool camera2Support = false;
+            serviceRet = cs->supportsCameraApi(i, hardware::ICameraService::API_VERSION_2,
+                    &camera2Support);
+            char buf[kMaxCameraIdLen];
+            if (camera2Support) {
+                numCameras++;
+                mCameraIds.insert(i);
+                snprintf(buf, sizeof(buf), "%d", i);
+                size_t cameraIdSize = strlen(buf) + 1;
+                char *cameraId = new char[cameraIdSize];
+                if (!cameraId) {
+                    ALOGE("Allocate memory for ACameraIdList failed!");
+                    return ACAMERA_ERROR_NOT_ENOUGH_MEMORY;
+                }
+                strlcpy(cameraId, buf, cameraIdSize);
+                cameraIds.push(cameraId);
+            }
+        }
+        mCachedCameraIdList.numCameras = numCameras;
+        mCachedCameraIdList.cameraIds = new const char*[numCameras];
+        if (!mCachedCameraIdList.cameraIds) {
+            ALOGE("Allocate memory for ACameraIdList failed!");
+            return ACAMERA_ERROR_NOT_ENOUGH_MEMORY;
+        }
+        for (int i = 0; i < numCameras; i++) {
+            mCachedCameraIdList.cameraIds[i] = cameraIds[i];
+        }
+    }
+    *cameraIdList = &mCachedCameraIdList;
+    return ACAMERA_OK;
+}
+
+camera_status_t
+ACameraManager::getCameraIdList(ACameraIdList** cameraIdList) {
+    Mutex::Autolock _l(mLock);
+    ACameraIdList* cachedList;
+    camera_status_t ret = getOrCreateCameraIdListLocked(&cachedList);
+    if (ret != ACAMERA_OK) {
+        ALOGE("Get camera ID list failed! err: %d", ret);
+        return ret;
+    }
+
+    int numCameras = cachedList->numCameras;
+    ACameraIdList *out = new ACameraIdList;
+    if (!out) {
+        ALOGE("Allocate memory for ACameraIdList failed!");
+        return ACAMERA_ERROR_NOT_ENOUGH_MEMORY;
+    }
+    out->numCameras = numCameras;
+    out->cameraIds = new const char*[numCameras];
+    if (!out->cameraIds) {
+        ALOGE("Allocate memory for ACameraIdList failed!");
+        return ACAMERA_ERROR_NOT_ENOUGH_MEMORY;
+    }
+    for (int i = 0; i < numCameras; i++) {
+        const char* src = cachedList->cameraIds[i];
+        size_t dstSize = strlen(src) + 1;
+        char* dst = new char[dstSize];
+        if (!dst) {
+            ALOGE("Allocate memory for ACameraIdList failed!");
+            return ACAMERA_ERROR_NOT_ENOUGH_MEMORY;
+        }
+        strlcpy(dst, src, dstSize);
+        out->cameraIds[i] = dst;
+    }
+    *cameraIdList = out;
+    return ACAMERA_OK;
+}
+
+void
+ACameraManager::deleteCameraIdList(ACameraIdList* cameraIdList) {
+    if (cameraIdList != nullptr) {
+        if (cameraIdList->cameraIds != nullptr) {
+            for (int i = 0; i < cameraIdList->numCameras; i ++) {
+                delete[] cameraIdList->cameraIds[i];
+            }
+            delete[] cameraIdList->cameraIds;
+        }
+        delete cameraIdList;
+    }
+}
+
+camera_status_t ACameraManager::getCameraCharacteristics(
+        const char *cameraIdStr, ACameraMetadata **characteristics) {
+    Mutex::Autolock _l(mLock);
+    ACameraIdList* cachedList;
+    // Make sure mCameraIds is initialized
+    camera_status_t ret = getOrCreateCameraIdListLocked(&cachedList);
+    if (ret != ACAMERA_OK) {
+        ALOGE("%s: Get camera ID list failed! err: %d", __FUNCTION__, ret);
+        return ret;
+    }
+    int cameraId = atoi(cameraIdStr);
+    if (mCameraIds.count(cameraId) == 0) {
+        ALOGE("%s: Camera ID %s does not exist!", __FUNCTION__, cameraIdStr);
+        return ACAMERA_ERROR_INVALID_PARAMETER;
+    }
+    sp<hardware::ICameraService> cs = CameraManagerGlobal::getInstance().getCameraService();
+    if (cs == nullptr) {
+        ALOGE("%s: Cannot reach camera service!", __FUNCTION__);
+        return ACAMERA_ERROR_CAMERA_DISCONNECTED;
+    }
+    CameraMetadata rawMetadata;
+    binder::Status serviceRet = cs->getCameraCharacteristics(cameraId, &rawMetadata);
+    if (!serviceRet.isOk()) {
+        ALOGE("Get camera characteristics from camera service failed: %s",
+                serviceRet.toString8().string());
+        return ACAMERA_ERROR_UNKNOWN; // should not reach here
+    }
+
+    *characteristics = new ACameraMetadata(
+            rawMetadata.release(), ACameraMetadata::ACM_CHARACTERISTICS);
+    return ACAMERA_OK;
+}
+
+camera_status_t
+ACameraManager::openCamera(
+        const char* cameraId,
+        ACameraDevice_StateCallbacks* callback,
+        /*out*/ACameraDevice** outDevice) {
+    ACameraMetadata* rawChars;
+    camera_status_t ret = getCameraCharacteristics(cameraId, &rawChars);
+    Mutex::Autolock _l(mLock);
+    if (ret != ACAMERA_OK) {
+        ALOGE("%s: cannot get camera characteristics for camera %s. err %d",
+                __FUNCTION__, cameraId, ret);
+        return ACAMERA_ERROR_INVALID_PARAMETER;
+    }
+    std::unique_ptr<ACameraMetadata> chars(rawChars);
+    rawChars = nullptr;
+
+    ACameraDevice* device = new ACameraDevice(cameraId, callback, std::move(chars));
+
+    sp<hardware::ICameraService> cs = CameraManagerGlobal::getInstance().getCameraService();
+    if (cs == nullptr) {
+        ALOGE("%s: Cannot reach camera service!", __FUNCTION__);
+        return ACAMERA_ERROR_CAMERA_DISCONNECTED;
+    }
+
+    int id = atoi(cameraId);
+    sp<hardware::camera2::ICameraDeviceCallbacks> callbacks = device->getServiceCallback();
+    sp<hardware::camera2::ICameraDeviceUser> deviceRemote;
+    // No way to get package name from native.
+    // Send a zero length package name and let camera service figure it out from UID
+    binder::Status serviceRet = cs->connectDevice(
+            callbacks, id, String16(""),
+            hardware::ICameraService::USE_CALLING_UID, /*out*/&deviceRemote);
+
+    if (!serviceRet.isOk()) {
+        ALOGE("%s: connect camera device failed: %s", __FUNCTION__, serviceRet.toString8().string());
+        // Convert serviceRet to camera_status_t
+        switch(serviceRet.serviceSpecificErrorCode()) {
+            case hardware::ICameraService::ERROR_DISCONNECTED:
+                ret = ACAMERA_ERROR_CAMERA_DISCONNECTED;
+                break;
+            case hardware::ICameraService::ERROR_CAMERA_IN_USE:
+                ret = ACAMERA_ERROR_CAMERA_IN_USE;
+                break;
+            case hardware::ICameraService::ERROR_MAX_CAMERAS_IN_USE:
+                ret = ACAMERA_ERROR_MAX_CAMERA_IN_USE;
+                break;
+            case hardware::ICameraService::ERROR_ILLEGAL_ARGUMENT:
+                ret = ACAMERA_ERROR_INVALID_PARAMETER;
+                break;
+            case hardware::ICameraService::ERROR_DEPRECATED_HAL:
+                // Should not reach here since we filtered legacy HALs earlier
+                ret = ACAMERA_ERROR_INVALID_PARAMETER;
+                break;
+            case hardware::ICameraService::ERROR_DISABLED:
+                ret = ACAMERA_ERROR_CAMERA_DISABLED;
+                break;
+            case hardware::ICameraService::ERROR_PERMISSION_DENIED:
+                ret = ACAMERA_ERROR_PERMISSION_DENIED;
+                break;
+            case hardware::ICameraService::ERROR_INVALID_OPERATION:
+            default:
+                ret = ACAMERA_ERROR_UNKNOWN;
+                break;
+        }
+
+        delete device;
+        return ret;
+    }
+    if (deviceRemote == nullptr) {
+        ALOGE("%s: connect camera device failed! remote device is null", __FUNCTION__);
+        delete device;
+        return ACAMERA_ERROR_CAMERA_DISCONNECTED;
+    }
+    device->setRemoteDevice(deviceRemote);
+    *outDevice = device;
+    return ACAMERA_OK;
+}
+
+ACameraManager::~ACameraManager() {
+    Mutex::Autolock _l(mLock);
+    if (mCachedCameraIdList.numCameras != kCameraIdListNotInit) {
+        for (int i = 0; i < mCachedCameraIdList.numCameras; i++) {
+            delete[] mCachedCameraIdList.cameraIds[i];
+        }
+        delete[] mCachedCameraIdList.cameraIds;
+    }
+}
diff --git a/camera/ndk/impl/ACameraManager.h b/camera/ndk/impl/ACameraManager.h
new file mode 100644
index 0000000..3f2262f
--- /dev/null
+++ b/camera/ndk/impl/ACameraManager.h
@@ -0,0 +1,184 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _ACAMERA_MANAGER_H
+#define _ACAMERA_MANAGER_H
+
+#include "NdkCameraManager.h"
+
+#include <android/hardware/ICameraService.h>
+#include <android/hardware/BnCameraServiceListener.h>
+#include <camera/CameraMetadata.h>
+#include <binder/IServiceManager.h>
+#include <utils/StrongPointer.h>
+#include <utils/Mutex.h>
+
+#include <media/stagefright/foundation/ALooper.h>
+#include <media/stagefright/foundation/AHandler.h>
+#include <media/stagefright/foundation/AMessage.h>
+
+#include <set>
+#include <map>
+
+namespace android {
+
+/**
+ * Per-process singleton instance of CameraManger. Shared by all ACameraManager
+ * instances. Created when first ACameraManager is created and destroyed when
+ * all ACameraManager instances are deleted.
+ *
+ * TODO: maybe CameraManagerGlobal is better sutied in libcameraclient?
+ */
+class CameraManagerGlobal final : public RefBase {
+  public:
+    static CameraManagerGlobal& getInstance();
+    sp<hardware::ICameraService> getCameraService();
+
+    void registerAvailabilityCallback(
+            const ACameraManager_AvailabilityCallbacks *callback);
+    void unregisterAvailabilityCallback(
+            const ACameraManager_AvailabilityCallbacks *callback);
+
+  private:
+    sp<hardware::ICameraService> mCameraService;
+    const int          kCameraServicePollDelay = 500000; // 0.5s
+    const char*        kCameraServiceName      = "media.camera";
+    Mutex              mLock;
+
+    class DeathNotifier : public IBinder::DeathRecipient {
+      public:
+        DeathNotifier(CameraManagerGlobal* cm) : mCameraManager(cm) {}
+      protected:
+        // IBinder::DeathRecipient implementation
+        virtual void binderDied(const wp<IBinder>& who);
+      private:
+        const wp<CameraManagerGlobal> mCameraManager;
+    };
+    sp<DeathNotifier> mDeathNotifier;
+
+    class CameraServiceListener final : public hardware::BnCameraServiceListener {
+      public:
+        CameraServiceListener(CameraManagerGlobal* cm) : mCameraManager(cm) {}
+        virtual binder::Status onStatusChanged(int32_t status, int32_t cameraId);
+
+        // Torch API not implemented yet
+        virtual binder::Status onTorchStatusChanged(int32_t, const String16&) {
+            return binder::Status::ok();
+        }
+
+      private:
+        const wp<CameraManagerGlobal> mCameraManager;
+    };
+    sp<CameraServiceListener> mCameraServiceListener;
+
+    // Wrapper of ACameraManager_AvailabilityCallbacks so we can store it in std::set
+    struct Callback {
+        Callback(const ACameraManager_AvailabilityCallbacks *callback) :
+            mAvailable(callback->onCameraAvailable),
+            mUnavailable(callback->onCameraUnavailable),
+            mContext(callback->context) {}
+
+        bool operator == (const Callback& other) const {
+            return (mAvailable == other.mAvailable &&
+                    mUnavailable == other.mUnavailable &&
+                    mContext == other.mContext);
+        }
+        bool operator != (const Callback& other) const {
+            return !(*this == other);
+        }
+        bool operator < (const Callback& other) const {
+            if (*this == other) return false;
+            if (mContext != other.mContext) return mContext < other.mContext;
+            if (mAvailable != other.mAvailable) return mAvailable < other.mAvailable;
+            return mUnavailable < other.mUnavailable;
+        }
+        bool operator > (const Callback& other) const {
+            return (*this != other && !(*this < other));
+        }
+        ACameraManager_AvailabilityCallback mAvailable;
+        ACameraManager_AvailabilityCallback mUnavailable;
+        void*                               mContext;
+    };
+    std::set<Callback> mCallbacks;
+
+    // definition of handler and message
+    enum {
+        kWhatSendSingleCallback
+    };
+    static const char* kCameraIdKey;
+    static const char* kCallbackFpKey;
+    static const char* kContextKey;
+    class CallbackHandler : public AHandler {
+      public:
+        CallbackHandler() {}
+        void onMessageReceived(const sp<AMessage> &msg) override;
+      private:
+        inline void sendSingleCallback(
+                int32_t cameraId, void* context,
+                ACameraManager_AvailabilityCallback cb) const;
+    };
+    sp<CallbackHandler> mHandler;
+    sp<ALooper>         mCbLooper; // Looper thread where callbacks actually happen on
+
+    void onStatusChanged(int32_t status, int32_t cameraId);
+    void onStatusChangedLocked(int32_t status, int32_t cameraId);
+    // Utils for status
+    static bool validStatus(int32_t status);
+    static bool isStatusAvailable(int32_t status);
+
+    // Map camera_id -> status
+    std::map<int32_t, int32_t> mDeviceStatusMap;
+
+    // For the singleton instance
+    static Mutex sLock;
+    static CameraManagerGlobal* sInstance;
+    CameraManagerGlobal() {};
+    ~CameraManagerGlobal();
+};
+
+} // namespace android;
+
+/**
+ * ACameraManager opaque struct definition
+ * Leave outside of android namespace because it's NDK struct
+ */
+struct ACameraManager {
+    ACameraManager() :
+            mCachedCameraIdList({kCameraIdListNotInit, nullptr}),
+            mGlobalManager(&(android::CameraManagerGlobal::getInstance())) {}
+    ~ACameraManager();
+    camera_status_t getCameraIdList(ACameraIdList** cameraIdList);
+    static void     deleteCameraIdList(ACameraIdList* cameraIdList);
+
+    camera_status_t getCameraCharacteristics(
+            const char *cameraId, ACameraMetadata **characteristics);
+    camera_status_t openCamera(const char* cameraId,
+                               ACameraDevice_StateCallbacks* callback,
+                               /*out*/ACameraDevice** device);
+
+  private:
+    camera_status_t getOrCreateCameraIdListLocked(ACameraIdList** cameraIdList);
+
+    enum {
+        kCameraIdListNotInit = -1
+    };
+    android::Mutex         mLock;
+    std::set<int> mCameraIds;          // Init by getOrCreateCameraIdListLocked
+    ACameraIdList mCachedCameraIdList; // Init by getOrCreateCameraIdListLocked
+    android::sp<android::CameraManagerGlobal> mGlobalManager;
+};
+
+#endif //_ACAMERA_MANAGER_H
diff --git a/camera/ndk/impl/ACameraMetadata.cpp b/camera/ndk/impl/ACameraMetadata.cpp
new file mode 100644
index 0000000..ab99e38
--- /dev/null
+++ b/camera/ndk/impl/ACameraMetadata.cpp
@@ -0,0 +1,365 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "ACameraMetadata"
+
+#include "ACameraMetadata.h"
+#include <utils/Vector.h>
+#include <system/graphics.h>
+#include "NdkImage.h"
+
+using namespace android;
+
+/**
+ * ACameraMetadata Implementation
+ */
+ACameraMetadata::ACameraMetadata(camera_metadata_t* buffer, ACAMERA_METADATA_TYPE type) :
+        mData(buffer), mType(type) {
+    if (mType == ACM_CHARACTERISTICS) {
+        filterUnsupportedFeatures();
+        filterStreamConfigurations();
+    }
+    // TODO: filter request/result keys
+}
+
+bool
+ACameraMetadata::isNdkSupportedCapability(int32_t capability) {
+    switch (capability) {
+        case ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE:
+        case ANDROID_REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR:
+        case ANDROID_REQUEST_AVAILABLE_CAPABILITIES_MANUAL_POST_PROCESSING:
+        case ANDROID_REQUEST_AVAILABLE_CAPABILITIES_RAW:
+        case ANDROID_REQUEST_AVAILABLE_CAPABILITIES_READ_SENSOR_SETTINGS:
+        case ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BURST_CAPTURE:
+        case ANDROID_REQUEST_AVAILABLE_CAPABILITIES_DEPTH_OUTPUT:
+            return true;
+        case ANDROID_REQUEST_AVAILABLE_CAPABILITIES_YUV_REPROCESSING:
+        case ANDROID_REQUEST_AVAILABLE_CAPABILITIES_PRIVATE_REPROCESSING:
+        case ANDROID_REQUEST_AVAILABLE_CAPABILITIES_CONSTRAINED_HIGH_SPEED_VIDEO:
+            return false;
+        default:
+            // Newly defined capabilities will be unsupported by default (blacklist)
+            // TODO: Should we do whitelist or blacklist here?
+            ALOGE("%s: Unknonwn capability %d", __FUNCTION__, capability);
+            return false;
+    }
+}
+
+void
+ACameraMetadata::filterUnsupportedFeatures() {
+    // Hide unsupported capabilities (reprocessing)
+    camera_metadata_entry entry = mData.find(ANDROID_REQUEST_AVAILABLE_CAPABILITIES);
+    if (entry.count == 0 || entry.type != TYPE_BYTE) {
+        ALOGE("%s: malformed available capability key! count %zu, type %d",
+                __FUNCTION__, entry.count, entry.type);
+        return;
+    }
+
+    Vector<uint8_t> capabilities;
+    capabilities.setCapacity(entry.count);
+    for (size_t i = 0; i < entry.count; i++) {
+        uint8_t capability = entry.data.u8[i];
+        if (isNdkSupportedCapability(capability)) {
+            capabilities.push(capability);
+        }
+    }
+    mData.update(ANDROID_REQUEST_AVAILABLE_CAPABILITIES, capabilities);
+}
+
+
+void
+ACameraMetadata::filterStreamConfigurations() {
+    const int STREAM_CONFIGURATION_SIZE = 4;
+    const int STREAM_FORMAT_OFFSET = 0;
+    const int STREAM_WIDTH_OFFSET = 1;
+    const int STREAM_HEIGHT_OFFSET = 2;
+    const int STREAM_IS_INPUT_OFFSET = 3;
+    camera_metadata_entry entry = mData.find(ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS);
+    if (entry.count == 0 || entry.count % 4 || entry.type != TYPE_INT32) {
+        ALOGE("%s: malformed available stream configuration key! count %zu, type %d",
+                __FUNCTION__, entry.count, entry.type);
+        return;
+    }
+
+    Vector<int32_t> filteredStreamConfigs;
+    filteredStreamConfigs.setCapacity(entry.count);
+
+    for (size_t i=0; i < entry.count; i += STREAM_CONFIGURATION_SIZE) {
+        int32_t format = entry.data.i32[i + STREAM_FORMAT_OFFSET];
+        int32_t width = entry.data.i32[i + STREAM_WIDTH_OFFSET];
+        int32_t height = entry.data.i32[i + STREAM_HEIGHT_OFFSET];
+        int32_t isInput = entry.data.i32[i + STREAM_IS_INPUT_OFFSET];
+        if (isInput == ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_INPUT) {
+            // Hide input streams
+            continue;
+        }
+        // Translate HAL formats to NDK format
+        if (format == HAL_PIXEL_FORMAT_BLOB) {
+            format = AIMAGE_FORMAT_JPEG;
+        }
+        filteredStreamConfigs.push_back(format);
+        filteredStreamConfigs.push_back(width);
+        filteredStreamConfigs.push_back(height);
+        filteredStreamConfigs.push_back(isInput);
+    }
+
+    mData.update(ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS, filteredStreamConfigs);
+
+    entry = mData.find(ANDROID_DEPTH_AVAILABLE_DEPTH_STREAM_CONFIGURATIONS);
+    Vector<int32_t> filteredDepthStreamConfigs;
+    filteredDepthStreamConfigs.setCapacity(entry.count);
+
+    for (size_t i=0; i < entry.count; i += STREAM_CONFIGURATION_SIZE) {
+        int32_t format = entry.data.i32[i + STREAM_FORMAT_OFFSET];
+        int32_t width = entry.data.i32[i + STREAM_WIDTH_OFFSET];
+        int32_t height = entry.data.i32[i + STREAM_HEIGHT_OFFSET];
+        int32_t isInput = entry.data.i32[i + STREAM_IS_INPUT_OFFSET];
+        if (isInput == ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_INPUT) {
+            // Hide input streams
+            continue;
+        }
+        // Translate HAL formats to NDK format
+        if (format == HAL_PIXEL_FORMAT_BLOB) {
+            format = AIMAGE_FORMAT_DEPTH_POINT_CLOUD;
+        } else if (format == HAL_PIXEL_FORMAT_Y16) {
+            format = AIMAGE_FORMAT_DEPTH16;
+        }
+
+        filteredDepthStreamConfigs.push_back(format);
+        filteredDepthStreamConfigs.push_back(width);
+        filteredDepthStreamConfigs.push_back(height);
+        filteredDepthStreamConfigs.push_back(isInput);
+    }
+    mData.update(ANDROID_DEPTH_AVAILABLE_DEPTH_STREAM_CONFIGURATIONS, filteredDepthStreamConfigs);
+}
+
+bool
+ACameraMetadata::isVendorTag(const uint32_t tag) {
+    uint32_t tag_section = tag >> 16;
+    if (tag_section >= VENDOR_SECTION) {
+        return true;
+    }
+    return false;
+}
+
+camera_status_t
+ACameraMetadata::getConstEntry(uint32_t tag, ACameraMetadata_const_entry* entry) const {
+    if (entry == nullptr) {
+        return ACAMERA_ERROR_INVALID_PARAMETER;
+    }
+
+    Mutex::Autolock _l(mLock);
+
+    camera_metadata_ro_entry rawEntry = mData.find(tag);
+    if (rawEntry.count == 0) {
+        ALOGE("%s: cannot find metadata tag %d", __FUNCTION__, tag);
+        return ACAMERA_ERROR_METADATA_NOT_FOUND;
+    }
+    entry->tag = tag;
+    entry->type = rawEntry.type;
+    entry->count = rawEntry.count;
+    entry->data.u8 = rawEntry.data.u8;
+    return ACAMERA_OK;
+}
+
+camera_status_t
+ACameraMetadata::update(uint32_t tag, uint32_t count, const uint8_t* data) {
+    return updateImpl<uint8_t>(tag, count, data);
+}
+
+camera_status_t
+ACameraMetadata::update(uint32_t tag, uint32_t count, const int32_t* data) {
+    return updateImpl<int32_t>(tag, count, data);
+}
+
+camera_status_t
+ACameraMetadata::update(uint32_t tag, uint32_t count, const float* data) {
+    return updateImpl<float>(tag, count, data);
+}
+
+camera_status_t
+ACameraMetadata::update(uint32_t tag, uint32_t count, const double* data) {
+    return updateImpl<double>(tag, count, data);
+}
+
+camera_status_t
+ACameraMetadata::update(uint32_t tag, uint32_t count, const int64_t* data) {
+    return updateImpl<int64_t>(tag, count, data);
+}
+
+camera_status_t
+ACameraMetadata::update(uint32_t tag, uint32_t count, const ACameraMetadata_rational* data) {
+    return updateImpl<camera_metadata_rational_t>(tag, count, data);
+}
+
+camera_status_t
+ACameraMetadata::getTags(/*out*/int32_t* numTags,
+                         /*out*/const uint32_t** tags) const {
+    Mutex::Autolock _l(mLock);
+    if (mTags.size() == 0) {
+        size_t entry_count = mData.entryCount();
+        mTags.setCapacity(entry_count);
+        const camera_metadata_t* rawMetadata = mData.getAndLock();
+        for (size_t i = 0; i < entry_count; i++) {
+            camera_metadata_ro_entry_t entry;
+            int ret = get_camera_metadata_ro_entry(rawMetadata, i, &entry);
+            if (ret != 0) {
+                ALOGE("%s: error reading metadata index %zu", __FUNCTION__, i);
+                return ACAMERA_ERROR_UNKNOWN;
+            }
+            // Hide system key from users
+            if (sSystemTags.count(entry.tag) == 0) {
+                mTags.push_back(entry.tag);
+            }
+        }
+        mData.unlock(rawMetadata);
+    }
+
+    *numTags = mTags.size();
+    *tags = mTags.array();
+    return ACAMERA_OK;
+}
+
+const CameraMetadata&
+ACameraMetadata::getInternalData() {
+    return mData;
+}
+
+// TODO: some of key below should be hidden from user
+// ex: ACAMERA_REQUEST_ID and ACAMERA_REPROCESS_EFFECTIVE_EXPOSURE_FACTOR
+/*@O~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~
+ * The key entries below this point are generated from metadata
+ * definitions in /system/media/camera/docs. Do not modify by hand or
+ * modify the comment blocks at the start or end.
+ *~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~*/
+
+bool
+ACameraMetadata::isCaptureRequestTag(const uint32_t tag) {
+    // Skip check for vendor keys
+    if (isVendorTag(tag)) {
+        return true;
+    }
+
+    switch (tag) {
+        case ACAMERA_COLOR_CORRECTION_MODE:
+        case ACAMERA_COLOR_CORRECTION_TRANSFORM:
+        case ACAMERA_COLOR_CORRECTION_GAINS:
+        case ACAMERA_COLOR_CORRECTION_ABERRATION_MODE:
+        case ACAMERA_CONTROL_AE_ANTIBANDING_MODE:
+        case ACAMERA_CONTROL_AE_EXPOSURE_COMPENSATION:
+        case ACAMERA_CONTROL_AE_LOCK:
+        case ACAMERA_CONTROL_AE_MODE:
+        case ACAMERA_CONTROL_AE_REGIONS:
+        case ACAMERA_CONTROL_AE_TARGET_FPS_RANGE:
+        case ACAMERA_CONTROL_AE_PRECAPTURE_TRIGGER:
+        case ACAMERA_CONTROL_AF_MODE:
+        case ACAMERA_CONTROL_AF_REGIONS:
+        case ACAMERA_CONTROL_AF_TRIGGER:
+        case ACAMERA_CONTROL_AWB_LOCK:
+        case ACAMERA_CONTROL_AWB_MODE:
+        case ACAMERA_CONTROL_AWB_REGIONS:
+        case ACAMERA_CONTROL_CAPTURE_INTENT:
+        case ACAMERA_CONTROL_EFFECT_MODE:
+        case ACAMERA_CONTROL_MODE:
+        case ACAMERA_CONTROL_SCENE_MODE:
+        case ACAMERA_CONTROL_VIDEO_STABILIZATION_MODE:
+        case ACAMERA_CONTROL_POST_RAW_SENSITIVITY_BOOST:
+        case ACAMERA_EDGE_MODE:
+        case ACAMERA_FLASH_MODE:
+        case ACAMERA_HOT_PIXEL_MODE:
+        case ACAMERA_JPEG_GPS_COORDINATES:
+        case ACAMERA_JPEG_GPS_PROCESSING_METHOD:
+        case ACAMERA_JPEG_GPS_TIMESTAMP:
+        case ACAMERA_JPEG_ORIENTATION:
+        case ACAMERA_JPEG_QUALITY:
+        case ACAMERA_JPEG_THUMBNAIL_QUALITY:
+        case ACAMERA_JPEG_THUMBNAIL_SIZE:
+        case ACAMERA_LENS_APERTURE:
+        case ACAMERA_LENS_FILTER_DENSITY:
+        case ACAMERA_LENS_FOCAL_LENGTH:
+        case ACAMERA_LENS_FOCUS_DISTANCE:
+        case ACAMERA_LENS_OPTICAL_STABILIZATION_MODE:
+        case ACAMERA_NOISE_REDUCTION_MODE:
+        case ACAMERA_SCALER_CROP_REGION:
+        case ACAMERA_SENSOR_EXPOSURE_TIME:
+        case ACAMERA_SENSOR_FRAME_DURATION:
+        case ACAMERA_SENSOR_SENSITIVITY:
+        case ACAMERA_SENSOR_TEST_PATTERN_DATA:
+        case ACAMERA_SENSOR_TEST_PATTERN_MODE:
+        case ACAMERA_SHADING_MODE:
+        case ACAMERA_STATISTICS_FACE_DETECT_MODE:
+        case ACAMERA_STATISTICS_HOT_PIXEL_MAP_MODE:
+        case ACAMERA_STATISTICS_LENS_SHADING_MAP_MODE:
+        case ACAMERA_TONEMAP_CURVE_BLUE:
+        case ACAMERA_TONEMAP_CURVE_GREEN:
+        case ACAMERA_TONEMAP_CURVE_RED:
+        case ACAMERA_TONEMAP_MODE:
+        case ACAMERA_TONEMAP_GAMMA:
+        case ACAMERA_TONEMAP_PRESET_CURVE:
+        case ACAMERA_BLACK_LEVEL_LOCK:
+            return true;
+        default:
+            return false;
+    }
+}
+
+// System tags that should be hidden from users
+std::unordered_set<uint32_t> ACameraMetadata::sSystemTags ({
+    ANDROID_CONTROL_SCENE_MODE_OVERRIDES,
+    ANDROID_CONTROL_AE_PRECAPTURE_ID,
+    ANDROID_CONTROL_AF_TRIGGER_ID,
+    ANDROID_DEMOSAIC_MODE,
+    ANDROID_EDGE_STRENGTH,
+    ANDROID_FLASH_FIRING_POWER,
+    ANDROID_FLASH_FIRING_TIME,
+    ANDROID_FLASH_COLOR_TEMPERATURE,
+    ANDROID_FLASH_MAX_ENERGY,
+    ANDROID_FLASH_INFO_CHARGE_DURATION,
+    ANDROID_JPEG_MAX_SIZE,
+    ANDROID_JPEG_SIZE,
+    ANDROID_NOISE_REDUCTION_STRENGTH,
+    ANDROID_QUIRKS_METERING_CROP_REGION,
+    ANDROID_QUIRKS_TRIGGER_AF_WITH_AUTO,
+    ANDROID_QUIRKS_USE_ZSL_FORMAT,
+    ANDROID_REQUEST_INPUT_STREAMS,
+    ANDROID_REQUEST_METADATA_MODE,
+    ANDROID_REQUEST_OUTPUT_STREAMS,
+    ANDROID_REQUEST_TYPE,
+    ANDROID_REQUEST_MAX_NUM_REPROCESS_STREAMS,
+    ANDROID_SCALER_AVAILABLE_RAW_MIN_DURATIONS,
+    ANDROID_SCALER_AVAILABLE_RAW_SIZES,
+    ANDROID_SENSOR_BASE_GAIN_FACTOR,
+    ANDROID_SENSOR_PROFILE_HUE_SAT_MAP_DIMENSIONS,
+    ANDROID_SENSOR_TEMPERATURE,
+    ANDROID_SENSOR_PROFILE_HUE_SAT_MAP,
+    ANDROID_SENSOR_PROFILE_TONE_CURVE,
+    ANDROID_SENSOR_OPAQUE_RAW_SIZE,
+    ANDROID_SHADING_STRENGTH,
+    ANDROID_STATISTICS_HISTOGRAM_MODE,
+    ANDROID_STATISTICS_SHARPNESS_MAP_MODE,
+    ANDROID_STATISTICS_HISTOGRAM,
+    ANDROID_STATISTICS_SHARPNESS_MAP,
+    ANDROID_STATISTICS_INFO_HISTOGRAM_BUCKET_COUNT,
+    ANDROID_STATISTICS_INFO_MAX_HISTOGRAM_COUNT,
+    ANDROID_STATISTICS_INFO_MAX_SHARPNESS_MAP_VALUE,
+    ANDROID_STATISTICS_INFO_SHARPNESS_MAP_SIZE,
+    ANDROID_DEPTH_MAX_DEPTH_SAMPLES,
+});
+
+/*~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~
+ * End generated code
+ *~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~O@*/
diff --git a/camera/ndk/impl/ACameraMetadata.h b/camera/ndk/impl/ACameraMetadata.h
new file mode 100644
index 0000000..8d050c4
--- /dev/null
+++ b/camera/ndk/impl/ACameraMetadata.h
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef _ACAMERA_METADATA_H
+#define _ACAMERA_METADATA_H
+
+#include <unordered_set>
+
+#include <sys/types.h>
+#include <utils/Mutex.h>
+#include <utils/RefBase.h>
+#include <utils/Vector.h>
+#include <camera/CameraMetadata.h>
+
+#include "NdkCameraMetadata.h"
+
+using namespace android;
+
+/**
+ * ACameraMetadata opaque struct definition
+ * Leave outside of android namespace because it's NDK struct
+ */
+struct ACameraMetadata : public RefBase {
+  public:
+    typedef enum {
+        ACM_CHARACTERISTICS, // Read only
+        ACM_REQUEST,         // Read/Write
+        ACM_RESULT,          // Read only
+    } ACAMERA_METADATA_TYPE;
+
+    // Takes ownership of pass-in buffer
+    ACameraMetadata(camera_metadata_t *buffer, ACAMERA_METADATA_TYPE type);
+    // Clone
+    ACameraMetadata(const ACameraMetadata& other) :
+            mData(other.mData), mType(other.mType) {};
+
+    camera_status_t getConstEntry(uint32_t tag, ACameraMetadata_const_entry* entry) const;
+
+    camera_status_t update(uint32_t tag, uint32_t count, const uint8_t* data);
+    camera_status_t update(uint32_t tag, uint32_t count, const int32_t* data);
+    camera_status_t update(uint32_t tag, uint32_t count, const float* data);
+    camera_status_t update(uint32_t tag, uint32_t count, const double* data);
+    camera_status_t update(uint32_t tag, uint32_t count, const int64_t* data);
+    camera_status_t update(uint32_t tag, uint32_t count, const ACameraMetadata_rational* data);
+
+    camera_status_t getTags(/*out*/int32_t* numTags,
+                            /*out*/const uint32_t** tags) const;
+
+    bool isNdkSupportedCapability(const int32_t capability);
+    static inline bool isVendorTag(const uint32_t tag);
+    static bool isCaptureRequestTag(const uint32_t tag);
+    void filterUnsupportedFeatures(); // Hide features not yet supported by NDK
+    void filterStreamConfigurations(); // Hide input streams, translate hal format to NDK formats
+
+    const CameraMetadata& getInternalData();
+
+    template<typename INTERNAL_T, typename NDK_T>
+    camera_status_t updateImpl(uint32_t tag, uint32_t count, const NDK_T* data) {
+        if (mType != ACM_REQUEST) {
+            ALOGE("Error: Write to metadata is only allowed for capture request!");
+            return ACAMERA_ERROR_INVALID_PARAMETER;
+        }
+        if (!isCaptureRequestTag(tag)) {
+            ALOGE("Error: tag %d is not writable!", tag);
+            return ACAMERA_ERROR_INVALID_PARAMETER;
+        }
+
+        Mutex::Autolock _l(mLock);
+
+        status_t ret = OK;
+        if (count == 0 && data == nullptr) {
+            ret = mData.erase(tag);
+        } else {
+            // Here we have to use reinterpret_cast because the NDK data type is
+            // exact copy of internal data type but they do not inherit from each other
+            ret = mData.update(tag, reinterpret_cast<const INTERNAL_T*>(data), count);
+        }
+
+        if (ret == OK) {
+            mTags.clear();
+            return ACAMERA_OK;
+        } else {
+            return ACAMERA_ERROR_INVALID_PARAMETER;
+        }
+    }
+
+  private:
+    // guard access of public APIs: get/update/getTags
+    mutable Mutex    mLock;
+    CameraMetadata   mData;
+    mutable Vector<uint32_t> mTags; // updated in getTags, cleared by update
+    const ACAMERA_METADATA_TYPE mType;
+
+    static std::unordered_set<uint32_t> sSystemTags;
+};
+
+#endif // _ACAMERA_METADATA_H
diff --git a/camera/ndk/impl/ACaptureRequest.h b/camera/ndk/impl/ACaptureRequest.h
new file mode 100644
index 0000000..6bd8406
--- /dev/null
+++ b/camera/ndk/impl/ACaptureRequest.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef _ACAPTURE_REQUEST_H
+#define _ACAPTURE_REQUEST_H
+
+#include "NdkCaptureRequest.h"
+#include <set>
+
+using namespace android;
+
+struct ACameraOutputTarget {
+    ACameraOutputTarget(ANativeWindow* window) : mWindow(window) {};
+
+    bool operator == (const ACameraOutputTarget& other) const {
+        return mWindow == other.mWindow;
+    }
+    bool operator != (const ACameraOutputTarget& other) const {
+        return mWindow != other.mWindow;
+    }
+    bool operator < (const ACameraOutputTarget& other) const {
+        return mWindow < other.mWindow;
+    }
+    bool operator > (const ACameraOutputTarget& other) const {
+        return mWindow > other.mWindow;
+    }
+
+    ANativeWindow* mWindow;
+};
+
+struct ACameraOutputTargets {
+    std::set<ACameraOutputTarget> mOutputs;
+};
+
+struct ACaptureRequest {
+    ACameraMetadata*      settings;
+    ACameraOutputTargets* targets;
+};
+
+#endif // _ACAPTURE_REQUEST_H
diff --git a/camera/tests/Android.mk b/camera/tests/Android.mk
index 3777d94..8019999 100644
--- a/camera/tests/Android.mk
+++ b/camera/tests/Android.mk
@@ -32,14 +32,11 @@
 	libbinder
 
 LOCAL_C_INCLUDES += \
-	system/media/camera/include \
 	system/media/private/camera/include \
 	system/media/camera/tests \
 	frameworks/av/services/camera/libcameraservice \
-	frameworks/av/include/camera \
-	frameworks/native/include \
 
-LOCAL_CFLAGS += -Wall -Wextra
+LOCAL_CFLAGS += -Wall -Wextra -Werror
 
 LOCAL_MODULE:= camera_client_test
 LOCAL_MODULE_TAGS := tests
diff --git a/camera/tests/CameraBinderTests.cpp b/camera/tests/CameraBinderTests.cpp
index 572fb72..828a758 100644
--- a/camera/tests/CameraBinderTests.cpp
+++ b/camera/tests/CameraBinderTests.cpp
@@ -32,12 +32,15 @@
 #include <hardware/gralloc.h>
 
 #include <camera/CameraMetadata.h>
-#include <camera/ICameraService.h>
-#include <camera/ICameraServiceListener.h>
+#include <android/hardware/ICameraService.h>
+#include <android/hardware/ICameraServiceListener.h>
+#include <android/hardware/BnCameraServiceListener.h>
+#include <android/hardware/camera2/ICameraDeviceUser.h>
+#include <android/hardware/camera2/ICameraDeviceCallbacks.h>
+#include <android/hardware/camera2/BnCameraDeviceCallbacks.h>
 #include <camera/camera2/CaptureRequest.h>
-#include <camera/camera2/ICameraDeviceUser.h>
-#include <camera/camera2/ICameraDeviceCallbacks.h>
 #include <camera/camera2/OutputConfiguration.h>
+#include <camera/camera2/SubmitInfo.h>
 
 #include <gui/BufferItemConsumer.h>
 #include <gui/IGraphicBufferProducer.h>
@@ -60,25 +63,27 @@
 #define IDLE_TIMEOUT 2000000000 // ns
 
 // Stub listener implementation
-class TestCameraServiceListener : public BnCameraServiceListener {
-    std::map<String16, TorchStatus> mCameraTorchStatuses;
-    std::map<int32_t, Status> mCameraStatuses;
+class TestCameraServiceListener : public hardware::BnCameraServiceListener {
+    std::map<String16, int32_t> mCameraTorchStatuses;
+    std::map<int32_t, int32_t> mCameraStatuses;
     mutable Mutex mLock;
     mutable Condition mCondition;
     mutable Condition mTorchCondition;
 public:
     virtual ~TestCameraServiceListener() {};
 
-    virtual void onStatusChanged(Status status, int32_t cameraId) {
+    virtual binder::Status onStatusChanged(int32_t status, int32_t cameraId) {
         Mutex::Autolock l(mLock);
         mCameraStatuses[cameraId] = status;
         mCondition.broadcast();
+        return binder::Status::ok();
     };
 
-    virtual void onTorchStatusChanged(TorchStatus status, const String16& cameraId) {
+    virtual binder::Status onTorchStatusChanged(int32_t status, const String16& cameraId) {
         Mutex::Autolock l(mLock);
         mCameraTorchStatuses[cameraId] = status;
         mTorchCondition.broadcast();
+        return binder::Status::ok();
     };
 
     bool waitForNumCameras(size_t num) const {
@@ -96,7 +101,7 @@
         return true;
     };
 
-    bool waitForTorchState(TorchStatus status, int32_t cameraId) const {
+    bool waitForTorchState(int32_t status, int32_t cameraId) const {
         Mutex::Autolock l(mLock);
 
         const auto& iter = mCameraTorchStatuses.find(String16(String8::format("%d", cameraId)));
@@ -116,27 +121,27 @@
         return true;
     };
 
-    TorchStatus getTorchStatus(int32_t cameraId) const {
+    int32_t getTorchStatus(int32_t cameraId) const {
         Mutex::Autolock l(mLock);
         const auto& iter = mCameraTorchStatuses.find(String16(String8::format("%d", cameraId)));
         if (iter == mCameraTorchStatuses.end()) {
-            return ICameraServiceListener::TORCH_STATUS_UNKNOWN;
+            return hardware::ICameraServiceListener::TORCH_STATUS_UNKNOWN;
         }
         return iter->second;
     };
 
-    Status getStatus(int32_t cameraId) const {
+    int32_t getStatus(int32_t cameraId) const {
         Mutex::Autolock l(mLock);
         const auto& iter = mCameraStatuses.find(cameraId);
         if (iter == mCameraStatuses.end()) {
-            return ICameraServiceListener::STATUS_UNKNOWN;
+            return hardware::ICameraServiceListener::STATUS_UNKNOWN;
         }
         return iter->second;
     };
 };
 
 // Callback implementation
-class TestCameraDeviceCallbacks : public BnCameraDeviceCallbacks {
+class TestCameraDeviceCallbacks : public hardware::camera2::BnCameraDeviceCallbacks {
 public:
     enum Status {
         IDLE,
@@ -144,13 +149,14 @@
         PREPARED,
         RUNNING,
         SENT_RESULT,
-        UNINITIALIZED
+        UNINITIALIZED,
+        REPEATING_REQUEST_ERROR,
     };
 
 protected:
     bool mError;
-    Status mLastStatus;
-    mutable std::vector<Status> mStatusesHit;
+    int32_t mLastStatus;
+    mutable std::vector<int32_t> mStatusesHit;
     mutable Mutex mLock;
     mutable Condition mStatusCondition;
 public:
@@ -158,45 +164,65 @@
 
     virtual ~TestCameraDeviceCallbacks() {}
 
-    virtual void onDeviceError(CameraErrorCode errorCode,
+    virtual binder::Status onDeviceError(int errorCode,
             const CaptureResultExtras& resultExtras) {
+        (void) resultExtras;
         ALOGE("%s: onDeviceError occurred with: %d", __FUNCTION__, static_cast<int>(errorCode));
         Mutex::Autolock l(mLock);
         mError = true;
         mLastStatus = ERROR;
         mStatusesHit.push_back(mLastStatus);
         mStatusCondition.broadcast();
+        return binder::Status::ok();
     }
 
-    virtual void onDeviceIdle() {
+    virtual binder::Status onDeviceIdle() {
         Mutex::Autolock l(mLock);
         mLastStatus = IDLE;
         mStatusesHit.push_back(mLastStatus);
         mStatusCondition.broadcast();
+        return binder::Status::ok();
     }
 
-    virtual void onCaptureStarted(const CaptureResultExtras& resultExtras,
+    virtual binder::Status onCaptureStarted(const CaptureResultExtras& resultExtras,
             int64_t timestamp) {
+        (void) resultExtras;
+        (void) timestamp;
         Mutex::Autolock l(mLock);
         mLastStatus = RUNNING;
         mStatusesHit.push_back(mLastStatus);
         mStatusCondition.broadcast();
+        return binder::Status::ok();
     }
 
 
-    virtual void onResultReceived(const CameraMetadata& metadata,
+    virtual binder::Status onResultReceived(const CameraMetadata& metadata,
             const CaptureResultExtras& resultExtras) {
+        (void) metadata;
+        (void) resultExtras;
         Mutex::Autolock l(mLock);
         mLastStatus = SENT_RESULT;
         mStatusesHit.push_back(mLastStatus);
         mStatusCondition.broadcast();
+        return binder::Status::ok();
     }
 
-    virtual void onPrepared(int streamId) {
+    virtual binder::Status onPrepared(int streamId) {
+        (void) streamId;
         Mutex::Autolock l(mLock);
         mLastStatus = PREPARED;
         mStatusesHit.push_back(mLastStatus);
         mStatusCondition.broadcast();
+        return binder::Status::ok();
+    }
+
+    virtual binder::Status onRepeatingRequestError(int64_t lastFrameNumber) {
+        (void) lastFrameNumber;
+        Mutex::Autolock l(mLock);
+        mLastStatus = REPEATING_REQUEST_ERROR;
+        mStatusesHit.push_back(mLastStatus);
+        mStatusCondition.broadcast();
+        return binder::Status::ok();
     }
 
     // Test helper functions:
@@ -237,95 +263,132 @@
 
 };
 
+namespace {
+    Mutex                     gLock;
+    class DeathNotifier : public IBinder::DeathRecipient
+    {
+    public:
+        DeathNotifier() {}
+
+        virtual void binderDied(const wp<IBinder>& /*who*/) {
+            ALOGV("binderDied");
+            Mutex::Autolock _l(gLock);
+            ALOGW("Camera service died!");
+        }
+    };
+    sp<DeathNotifier>         gDeathNotifier;
+}; // anonymous namespace
+
 // Exercise basic binder calls for the camera service
 TEST(CameraServiceBinderTest, CheckBinderCameraService) {
     ProcessState::self()->startThreadPool();
     sp<IServiceManager> sm = defaultServiceManager();
     sp<IBinder> binder = sm->getService(String16("media.camera"));
     ASSERT_NOT_NULL(binder);
-    sp<ICameraService> service = interface_cast<ICameraService>(binder);
+    if (gDeathNotifier == NULL) {
+        gDeathNotifier = new DeathNotifier();
+    }
+    binder->linkToDeath(gDeathNotifier);
+    sp<hardware::ICameraService> service =
+            interface_cast<hardware::ICameraService>(binder);
 
+    binder::Status res;
 
-    int32_t numCameras = service->getNumberOfCameras();
+    int32_t numCameras = 0;
+    res = service->getNumberOfCameras(hardware::ICameraService::CAMERA_TYPE_ALL, &numCameras);
+    EXPECT_TRUE(res.isOk()) << res;
     EXPECT_LE(0, numCameras);
 
     // Check listener binder calls
     sp<TestCameraServiceListener> listener(new TestCameraServiceListener());
-    EXPECT_EQ(OK, service->addListener(listener));
+    res = service->addListener(listener);
+    EXPECT_TRUE(res.isOk()) << res;
 
     EXPECT_TRUE(listener->waitForNumCameras(numCameras));
 
     for (int32_t i = 0; i < numCameras; i++) {
+        bool isSupported = false;
+        res = service->supportsCameraApi(i,
+                hardware::ICameraService::API_VERSION_2, &isSupported);
+        EXPECT_TRUE(res.isOk()) << res;
+
         // We only care about binder calls for the Camera2 API.  Camera1 is deprecated.
-        status_t camera2Support = service->supportsCameraApi(i, ICameraService::API_VERSION_2);
-        if (camera2Support != OK) {
-            EXPECT_EQ(-EOPNOTSUPP, camera2Support);
+        if (!isSupported) {
             continue;
         }
 
         // Check metadata binder call
         CameraMetadata metadata;
-        EXPECT_EQ(OK, service->getCameraCharacteristics(i, &metadata));
+        res = service->getCameraCharacteristics(i, &metadata);
+        EXPECT_TRUE(res.isOk()) << res;
         EXPECT_FALSE(metadata.isEmpty());
 
         // Make sure we're available, or skip device tests otherwise
-        ICameraServiceListener::Status s = listener->getStatus(i);
-        EXPECT_EQ(ICameraServiceListener::STATUS_AVAILABLE, s);
-        if (s != ICameraServiceListener::STATUS_AVAILABLE) {
+        int32_t s = listener->getStatus(i);
+        EXPECT_EQ(::android::hardware::ICameraServiceListener::STATUS_PRESENT, s);
+        if (s != ::android::hardware::ICameraServiceListener::STATUS_PRESENT) {
             continue;
         }
 
         // Check connect binder calls
         sp<TestCameraDeviceCallbacks> callbacks(new TestCameraDeviceCallbacks());
-        sp<ICameraDeviceUser> device;
-        EXPECT_EQ(OK, service->connectDevice(callbacks, i, String16("meeeeeeeee!"),
-                ICameraService::USE_CALLING_UID, /*out*/device));
+        sp<hardware::camera2::ICameraDeviceUser> device;
+        res = service->connectDevice(callbacks, i, String16("meeeeeeeee!"),
+                hardware::ICameraService::USE_CALLING_UID, /*out*/&device);
+        EXPECT_TRUE(res.isOk()) << res;
         ASSERT_NE(nullptr, device.get());
         device->disconnect();
         EXPECT_FALSE(callbacks->hadError());
 
-        ICameraServiceListener::TorchStatus torchStatus = listener->getTorchStatus(i);
-        if (torchStatus == ICameraServiceListener::TORCH_STATUS_AVAILABLE_OFF) {
+        int32_t torchStatus = listener->getTorchStatus(i);
+        if (torchStatus == hardware::ICameraServiceListener::TORCH_STATUS_AVAILABLE_OFF) {
             // Check torch calls
-            EXPECT_EQ(OK, service->setTorchMode(String16(String8::format("%d", i)),
-                    /*enabled*/true, callbacks));
+            res = service->setTorchMode(String16(String8::format("%d", i)),
+                    /*enabled*/true, callbacks);
+            EXPECT_TRUE(res.isOk()) << res;
             EXPECT_TRUE(listener->waitForTorchState(
-                    ICameraServiceListener::TORCH_STATUS_AVAILABLE_ON, i));
-            EXPECT_EQ(OK, service->setTorchMode(String16(String8::format("%d", i)),
-                    /*enabled*/false, callbacks));
+                    hardware::ICameraServiceListener::TORCH_STATUS_AVAILABLE_ON, i));
+            res = service->setTorchMode(String16(String8::format("%d", i)),
+                    /*enabled*/false, callbacks);
+            EXPECT_TRUE(res.isOk()) << res;
             EXPECT_TRUE(listener->waitForTorchState(
-                    ICameraServiceListener::TORCH_STATUS_AVAILABLE_OFF, i));
+                    hardware::ICameraServiceListener::TORCH_STATUS_AVAILABLE_OFF, i));
         }
     }
 
-    EXPECT_EQ(OK, service->removeListener(listener));
+    res = service->removeListener(listener);
+    EXPECT_TRUE(res.isOk()) << res;
 }
 
 // Test fixture for client focused binder tests
 class CameraClientBinderTest : public testing::Test {
 protected:
-    sp<ICameraService> service;
+    sp<hardware::ICameraService> service;
     int32_t numCameras;
-    std::vector<std::pair<sp<TestCameraDeviceCallbacks>, sp<ICameraDeviceUser>>> openDeviceList;
+    std::vector<std::pair<sp<TestCameraDeviceCallbacks>, sp<hardware::camera2::ICameraDeviceUser>>>
+            openDeviceList;
     sp<TestCameraServiceListener> serviceListener;
 
-    std::pair<sp<TestCameraDeviceCallbacks>, sp<ICameraDeviceUser>> openNewDevice(int deviceId) {
-
+    std::pair<sp<TestCameraDeviceCallbacks>, sp<hardware::camera2::ICameraDeviceUser>>
+            openNewDevice(int deviceId) {
         sp<TestCameraDeviceCallbacks> callbacks(new TestCameraDeviceCallbacks());
-        sp<ICameraDeviceUser> device;
+        sp<hardware::camera2::ICameraDeviceUser> device;
         {
             SCOPED_TRACE("openNewDevice");
-            EXPECT_EQ(OK, service->connectDevice(callbacks, deviceId, String16("meeeeeeeee!"),
-                    ICameraService::USE_CALLING_UID, /*out*/device));
+            binder::Status res = service->connectDevice(callbacks, deviceId, String16("meeeeeeeee!"),
+                    hardware::ICameraService::USE_CALLING_UID, /*out*/&device);
+            EXPECT_TRUE(res.isOk()) << res;
         }
         auto p = std::make_pair(callbacks, device);
         openDeviceList.push_back(p);
         return p;
     }
 
-    void closeDevice(std::pair<sp<TestCameraDeviceCallbacks>, sp<ICameraDeviceUser>>& p) {
+    void closeDevice(std::pair<sp<TestCameraDeviceCallbacks>,
+            sp<hardware::camera2::ICameraDeviceUser>>& p) {
         if (p.second.get() != nullptr) {
-            p.second->disconnect();
+            binder::Status res = p.second->disconnect();
+            EXPECT_TRUE(res.isOk()) << res;
             {
                 SCOPED_TRACE("closeDevice");
                 EXPECT_FALSE(p.first->hadError());
@@ -341,10 +404,11 @@
         ProcessState::self()->startThreadPool();
         sp<IServiceManager> sm = defaultServiceManager();
         sp<IBinder> binder = sm->getService(String16("media.camera"));
-        service = interface_cast<ICameraService>(binder);
+        service = interface_cast<hardware::ICameraService>(binder);
         serviceListener = new TestCameraServiceListener();
         service->addListener(serviceListener);
-        numCameras = service->getNumberOfCameras();
+        service->getNumberOfCameras(hardware::ICameraService::CAMERA_TYPE_BACKWARD_COMPATIBLE,
+                &numCameras);
     }
 
     virtual void TearDown() {
@@ -359,19 +423,19 @@
 
 TEST_F(CameraClientBinderTest, CheckBinderCameraDeviceUser) {
     ASSERT_NOT_NULL(service);
-
     EXPECT_TRUE(serviceListener->waitForNumCameras(numCameras));
     for (int32_t i = 0; i < numCameras; i++) {
         // Make sure we're available, or skip device tests otherwise
-        ICameraServiceListener::Status s = serviceListener->getStatus(i);
-        EXPECT_EQ(ICameraServiceListener::STATUS_AVAILABLE, s);
-        if (s != ICameraServiceListener::STATUS_AVAILABLE) {
+        int32_t s = serviceListener->getStatus(i);
+        EXPECT_EQ(hardware::ICameraServiceListener::STATUS_PRESENT, s);
+        if (s != hardware::ICameraServiceListener::STATUS_PRESENT) {
             continue;
         }
+        binder::Status res;
 
         auto p = openNewDevice(i);
         sp<TestCameraDeviceCallbacks> callbacks = p.first;
-        sp<ICameraDeviceUser> device = p.second;
+        sp<hardware::camera2::ICameraDeviceUser> device = p.second;
 
         // Setup a buffer queue; I'm just using the vendor opaque format here as that is
         // guaranteed to be present
@@ -392,50 +456,65 @@
         OutputConfiguration output(gbProducer, /*rotation*/0);
 
         // Can we configure?
-        EXPECT_EQ(OK, device->beginConfigure());
-        status_t streamId = device->createStream(output);
+        res = device->beginConfigure();
+        EXPECT_TRUE(res.isOk()) << res;
+        status_t streamId;
+        res = device->createStream(output, &streamId);
+        EXPECT_TRUE(res.isOk()) << res;
         EXPECT_LE(0, streamId);
-        EXPECT_EQ(OK, device->endConfigure());
+        res = device->endConfigure(/*isConstrainedHighSpeed*/ false);
+        EXPECT_TRUE(res.isOk()) << res;
         EXPECT_FALSE(callbacks->hadError());
 
         // Can we make requests?
         CameraMetadata requestTemplate;
-        EXPECT_EQ(OK, device->createDefaultRequest(/*preview template*/1,
-                /*out*/&requestTemplate));
-        sp<CaptureRequest> request(new CaptureRequest());
-        request->mMetadata = requestTemplate;
-        request->mSurfaceList.add(surface);
-        request->mIsReprocess = false;
+        res = device->createDefaultRequest(/*preview template*/1,
+                /*out*/&requestTemplate);
+        EXPECT_TRUE(res.isOk()) << res;
+
+        hardware::camera2::CaptureRequest request;
+        request.mMetadata = requestTemplate;
+        request.mSurfaceList.add(surface);
+        request.mIsReprocess = false;
         int64_t lastFrameNumber = 0;
         int64_t lastFrameNumberPrev = 0;
         callbacks->clearStatus();
-        int requestId = device->submitRequest(request, /*streaming*/true, /*out*/&lastFrameNumber);
+
+        hardware::camera2::utils::SubmitInfo info;
+        res = device->submitRequest(request, /*streaming*/true, /*out*/&info);
+        EXPECT_TRUE(res.isOk()) << res;
         EXPECT_TRUE(callbacks->waitForStatus(TestCameraDeviceCallbacks::SENT_RESULT));
-        EXPECT_LE(0, requestId);
+        EXPECT_LE(0, info.mRequestId);
 
         // Can we stop requests?
-        EXPECT_EQ(OK, device->cancelRequest(requestId, /*out*/&lastFrameNumber));
+        res = device->cancelRequest(info.mRequestId, /*out*/&lastFrameNumber);
+        EXPECT_TRUE(res.isOk()) << res;
         EXPECT_TRUE(callbacks->waitForIdle());
         EXPECT_FALSE(callbacks->hadError());
 
         // Can we do it again?
-        lastFrameNumberPrev = lastFrameNumber;
+        lastFrameNumberPrev = info.mLastFrameNumber;
         lastFrameNumber = 0;
         requestTemplate.clear();
-        EXPECT_EQ(OK, device->createDefaultRequest(/*preview template*/1,
-                /*out*/&requestTemplate));
-        sp<CaptureRequest> request2(new CaptureRequest());
-        request2->mMetadata = requestTemplate;
-        request2->mSurfaceList.add(surface);
-        request2->mIsReprocess = false;
+        res = device->createDefaultRequest(hardware::camera2::ICameraDeviceUser::TEMPLATE_PREVIEW,
+                /*out*/&requestTemplate);
+        EXPECT_TRUE(res.isOk()) << res;
+        hardware::camera2::CaptureRequest request2;
+        request2.mMetadata = requestTemplate;
+        request2.mSurfaceList.add(surface);
+        request2.mIsReprocess = false;
         callbacks->clearStatus();
-        int requestId2 = device->submitRequest(request2, /*streaming*/true,
-                /*out*/&lastFrameNumber);
-        EXPECT_EQ(-1, lastFrameNumber);
+        hardware::camera2::utils::SubmitInfo info2;
+        res = device->submitRequest(request2, /*streaming*/true,
+                /*out*/&info2);
+        EXPECT_TRUE(res.isOk()) << res;
+        EXPECT_EQ(hardware::camera2::ICameraDeviceUser::NO_IN_FLIGHT_REPEATING_FRAMES,
+                info2.mLastFrameNumber);
         lastFrameNumber = 0;
         EXPECT_TRUE(callbacks->waitForStatus(TestCameraDeviceCallbacks::SENT_RESULT));
-        EXPECT_LE(0, requestId2);
-        EXPECT_EQ(OK, device->cancelRequest(requestId2, /*out*/&lastFrameNumber));
+        EXPECT_LE(0, info2.mRequestId);
+        res = device->cancelRequest(info2.mRequestId, /*out*/&lastFrameNumber);
+        EXPECT_TRUE(res.isOk()) << res;
         EXPECT_TRUE(callbacks->waitForIdle());
         EXPECT_LE(lastFrameNumberPrev, lastFrameNumber);
         sleep(/*second*/1); // allow some time for errors to show up, if any
@@ -446,35 +525,44 @@
         lastFrameNumber = 0;
         requestTemplate.clear();
         CameraMetadata requestTemplate2;
-        EXPECT_EQ(OK, device->createDefaultRequest(/*preview template*/1,
-                /*out*/&requestTemplate));
-        EXPECT_EQ(OK, device->createDefaultRequest(/*preview template*/1,
-                /*out*/&requestTemplate2));
-        sp<CaptureRequest> request3(new CaptureRequest());
-        sp<CaptureRequest> request4(new CaptureRequest());
-        request3->mMetadata = requestTemplate;
-        request3->mSurfaceList.add(surface);
-        request3->mIsReprocess = false;
-        request4->mMetadata = requestTemplate2;
-        request4->mSurfaceList.add(surface);
-        request4->mIsReprocess = false;
-        List<sp<CaptureRequest>> requestList;
+        res = device->createDefaultRequest(hardware::camera2::ICameraDeviceUser::TEMPLATE_PREVIEW,
+                /*out*/&requestTemplate);
+        EXPECT_TRUE(res.isOk()) << res;
+        res = device->createDefaultRequest(hardware::camera2::ICameraDeviceUser::TEMPLATE_PREVIEW,
+                /*out*/&requestTemplate2);
+        EXPECT_TRUE(res.isOk()) << res;
+        android::hardware::camera2::CaptureRequest request3;
+        android::hardware::camera2::CaptureRequest request4;
+        request3.mMetadata = requestTemplate;
+        request3.mSurfaceList.add(surface);
+        request3.mIsReprocess = false;
+        request4.mMetadata = requestTemplate2;
+        request4.mSurfaceList.add(surface);
+        request4.mIsReprocess = false;
+        std::vector<hardware::camera2::CaptureRequest> requestList;
         requestList.push_back(request3);
         requestList.push_back(request4);
 
         callbacks->clearStatus();
-        int requestId3 = device->submitRequestList(requestList, /*streaming*/false,
-                /*out*/&lastFrameNumber);
+        hardware::camera2::utils::SubmitInfo info3;
+        res = device->submitRequestList(requestList, /*streaming*/false,
+                /*out*/&info3);
+        EXPECT_TRUE(res.isOk()) << res;
+        EXPECT_LE(0, info3.mRequestId);
         EXPECT_TRUE(callbacks->waitForStatus(TestCameraDeviceCallbacks::SENT_RESULT));
         EXPECT_TRUE(callbacks->waitForIdle());
-        EXPECT_LE(lastFrameNumberPrev, lastFrameNumber);
+        EXPECT_LE(lastFrameNumberPrev, info3.mLastFrameNumber);
         sleep(/*second*/1); // allow some time for errors to show up, if any
         EXPECT_FALSE(callbacks->hadError());
 
         // Can we unconfigure?
-        EXPECT_EQ(OK, device->beginConfigure());
-        EXPECT_EQ(OK, device->deleteStream(streamId));
-        EXPECT_EQ(OK, device->endConfigure());
+        res = device->beginConfigure();
+        EXPECT_TRUE(res.isOk()) << res;
+        res = device->deleteStream(streamId);
+        EXPECT_TRUE(res.isOk()) << res;
+        res = device->endConfigure(/*isConstrainedHighSpeed*/ false);
+        EXPECT_TRUE(res.isOk()) << res;
+
         sleep(/*second*/1); // allow some time for errors to show up, if any
         EXPECT_FALSE(callbacks->hadError());
 
diff --git a/camera/tests/VendorTagDescriptorTests.cpp b/camera/tests/VendorTagDescriptorTests.cpp
index 9082dbf..75cfb73 100644
--- a/camera/tests/VendorTagDescriptorTests.cpp
+++ b/camera/tests/VendorTagDescriptorTests.cpp
@@ -53,27 +53,27 @@
 
 extern "C" {
 
-static int zero_get_tag_count(const vendor_tag_ops_t* vOps) {
+static int zero_get_tag_count(const vendor_tag_ops_t*) {
     return 0;
 }
 
-static int default_get_tag_count(const vendor_tag_ops_t* vOps) {
+static int default_get_tag_count(const vendor_tag_ops_t*) {
     return VENDOR_TAG_COUNT_ERR;
 }
 
-static void default_get_all_tags(const vendor_tag_ops_t* vOps, uint32_t* tagArray) {
+static void default_get_all_tags(const vendor_tag_ops_t*, uint32_t*) {
     //Noop
 }
 
-static const char* default_get_section_name(const vendor_tag_ops_t* vOps, uint32_t tag) {
+static const char* default_get_section_name(const vendor_tag_ops_t*, uint32_t) {
     return VENDOR_SECTION_NAME_ERR;
 }
 
-static const char* default_get_tag_name(const vendor_tag_ops_t* vOps, uint32_t tag) {
+static const char* default_get_tag_name(const vendor_tag_ops_t*, uint32_t) {
     return VENDOR_TAG_NAME_ERR;
 }
 
-static int default_get_tag_type(const vendor_tag_ops_t* vOps, uint32_t tag) {
+static int default_get_tag_type(const vendor_tag_ops_t*, uint32_t) {
     return VENDOR_TAG_TYPE_ERR;
 }
 
@@ -141,7 +141,8 @@
     // Check whether parcel read/write succeed
     EXPECT_EQ(OK, vDescOriginal->writeToParcel(&p));
     p.setDataPosition(0);
-    ASSERT_EQ(OK, VendorTagDescriptor::createFromParcel(&p, vDescParceled));
+
+    ASSERT_EQ(OK, vDescParceled->readFromParcel(&p));
 
     // Ensure consistent tag count
     int tagCount = vDescOriginal->getTagCount();
@@ -197,7 +198,6 @@
     EXPECT_EQ(VENDOR_TAG_TYPE_ERR, vDesc->getTagType(BAD_TAG));
 
     // Make sure global can be set/cleared
-    const vendor_tag_ops_t *fakeOps = &fakevendor_ops;
     sp<VendorTagDescriptor> prevGlobal = VendorTagDescriptor::getGlobalVendorTagDescriptor();
     VendorTagDescriptor::clearGlobalVendorTagDescriptor();
 
@@ -208,4 +208,3 @@
     EXPECT_EQ(OK, VendorTagDescriptor::setAsGlobalVendorTagDescriptor(prevGlobal));
     EXPECT_EQ(prevGlobal, VendorTagDescriptor::getGlobalVendorTagDescriptor());
 }
-
diff --git a/cmds/screenrecord/FrameOutput.cpp b/cmds/screenrecord/FrameOutput.cpp
index bef74f5..ee7ace6 100644
--- a/cmds/screenrecord/FrameOutput.cpp
+++ b/cmds/screenrecord/FrameOutput.cpp
@@ -74,7 +74,7 @@
                 GL_TEXTURE_EXTERNAL_OES, true, false);
     mGlConsumer->setName(String8("virtual display"));
     mGlConsumer->setDefaultBufferSize(width, height);
-    mGlConsumer->setDefaultMaxBufferCount(5);
+    producer->setMaxDequeuedBufferCount(4);
     mGlConsumer->setConsumerUsageBits(GRALLOC_USAGE_HW_TEXTURE);
 
     mGlConsumer->setFrameAvailableListener(this);
diff --git a/cmds/screenrecord/Overlay.cpp b/cmds/screenrecord/Overlay.cpp
index c659170..9fd192c 100644
--- a/cmds/screenrecord/Overlay.cpp
+++ b/cmds/screenrecord/Overlay.cpp
@@ -176,7 +176,7 @@
                 GL_TEXTURE_EXTERNAL_OES, true, false);
     mGlConsumer->setName(String8("virtual display"));
     mGlConsumer->setDefaultBufferSize(width, height);
-    mGlConsumer->setDefaultMaxBufferCount(5);
+    mProducer->setMaxDequeuedBufferCount(4);
     mGlConsumer->setConsumerUsageBits(GRALLOC_USAGE_HW_TEXTURE);
 
     mGlConsumer->setFrameAvailableListener(this);
diff --git a/cmds/stagefright/Android.mk b/cmds/stagefright/Android.mk
index 20c0094..9e15a81 100644
--- a/cmds/stagefright/Android.mk
+++ b/cmds/stagefright/Android.mk
@@ -9,7 +9,7 @@
 
 LOCAL_SHARED_LIBRARIES := \
 	libstagefright libmedia libutils libbinder libstagefright_foundation \
-        libjpeg libgui libcutils liblog
+	libjpeg libgui libcutils liblog
 
 LOCAL_C_INCLUDES:= \
 	frameworks/av/media/libstagefright \
@@ -31,15 +31,16 @@
 include $(CLEAR_VARS)
 
 LOCAL_SRC_FILES:=         \
-        SineSource.cpp    \
-        record.cpp
+	SineSource.cpp    \
+	record.cpp
 
 LOCAL_SHARED_LIBRARIES := \
-	libstagefright liblog libutils libbinder libstagefright_foundation
+	libstagefright libmedia liblog libutils libbinder libstagefright_foundation
 
 LOCAL_C_INCLUDES:= \
 	frameworks/av/media/libstagefright \
-	$(TOP)/frameworks/native/include/media/openmax
+	$(TOP)/frameworks/native/include/media/openmax \
+	$(TOP)/frameworks/native/include/media/hardware
 
 LOCAL_CFLAGS += -Wno-multichar -Werror -Wall
 LOCAL_CLANG := true
@@ -55,15 +56,16 @@
 include $(CLEAR_VARS)
 
 LOCAL_SRC_FILES:=         \
-        SineSource.cpp    \
-        recordvideo.cpp
+	SineSource.cpp    \
+	recordvideo.cpp
 
 LOCAL_SHARED_LIBRARIES := \
-	libstagefright liblog libutils libbinder libstagefright_foundation
+	libstagefright libmedia liblog libutils libbinder libstagefright_foundation
 
 LOCAL_C_INCLUDES:= \
 	frameworks/av/media/libstagefright \
-	$(TOP)/frameworks/native/include/media/openmax
+	$(TOP)/frameworks/native/include/media/openmax \
+	$(TOP)/frameworks/native/include/media/hardware
 
 LOCAL_CFLAGS += -Wno-multichar -Werror -Wall
 LOCAL_CLANG := true
@@ -80,11 +82,11 @@
 include $(CLEAR_VARS)
 
 LOCAL_SRC_FILES:=         \
-        SineSource.cpp    \
-        audioloop.cpp
+	SineSource.cpp    \
+	audioloop.cpp
 
 LOCAL_SHARED_LIBRARIES := \
-	libstagefright liblog libutils libbinder libstagefright_foundation
+	libstagefright libmedia liblog libutils libbinder libstagefright_foundation
 
 LOCAL_C_INCLUDES:= \
 	frameworks/av/media/libstagefright \
@@ -108,7 +110,7 @@
 
 LOCAL_SHARED_LIBRARIES := \
 	libstagefright liblog libutils libbinder libgui \
-        libstagefright_foundation libmedia libcutils
+	libstagefright_foundation libmedia libcutils
 
 LOCAL_C_INCLUDES:= \
 	frameworks/av/media/libstagefright \
@@ -128,11 +130,11 @@
 include $(CLEAR_VARS)
 
 LOCAL_SRC_FILES:=         \
-        sf2.cpp    \
+	sf2.cpp    \
 
 LOCAL_SHARED_LIBRARIES := \
 	libstagefright liblog libutils libbinder libstagefright_foundation \
-        libmedia libgui libcutils libui
+	libmedia libgui libcutils libui
 
 LOCAL_C_INCLUDES:= \
 	frameworks/av/media/libstagefright \
@@ -152,12 +154,12 @@
 include $(CLEAR_VARS)
 
 LOCAL_SRC_FILES:=               \
-        codec.cpp               \
-        SimplePlayer.cpp        \
+	codec.cpp               \
+	SimplePlayer.cpp        \
 
 LOCAL_SHARED_LIBRARIES := \
 	libstagefright liblog libutils libbinder libstagefright_foundation \
-        libmedia libgui libcutils libui
+	libmedia libgui libcutils libui
 
 LOCAL_C_INCLUDES:= \
 	frameworks/av/media/libstagefright \
@@ -220,11 +222,11 @@
 include $(CLEAR_VARS)
 
 LOCAL_SRC_FILES:=               \
-        muxer.cpp            \
+	muxer.cpp            \
 
 LOCAL_SHARED_LIBRARIES := \
 	libstagefright liblog libutils libbinder libstagefright_foundation \
-        libmedia libgui libcutils libui libc
+	libmedia libgui libcutils libui libc
 
 LOCAL_C_INCLUDES:= \
 	frameworks/av/media/libstagefright \
diff --git a/cmds/stagefright/SineSource.cpp b/cmds/stagefright/SineSource.cpp
index 587077a..cad8caf 100644
--- a/cmds/stagefright/SineSource.cpp
+++ b/cmds/stagefright/SineSource.cpp
@@ -53,6 +53,7 @@
     meta->setInt32(kKeyChannelCount, mNumChannels);
     meta->setInt32(kKeySampleRate, mSampleRate);
     meta->setInt32(kKeyMaxInputSize, kBufferSize);
+    meta->setInt32(kKeyPcmEncoding, kAudioEncodingPcm16bit);
 
     return meta;
 }
diff --git a/cmds/stagefright/audioloop.cpp b/cmds/stagefright/audioloop.cpp
index 6e9e6ec..ed44b4d 100644
--- a/cmds/stagefright/audioloop.cpp
+++ b/cmds/stagefright/audioloop.cpp
@@ -23,13 +23,14 @@
 #include <binder/ProcessState.h>
 #include <media/mediarecorder.h>
 #include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/AMessage.h>
 #include <media/stagefright/AMRWriter.h>
 #include <media/stagefright/AudioPlayer.h>
 #include <media/stagefright/AudioSource.h>
+#include <media/stagefright/MediaCodecSource.h>
 #include <media/stagefright/MediaDefs.h>
 #include <media/stagefright/MetaData.h>
-#include <media/stagefright/OMXClient.h>
-#include <media/stagefright/OMXCodec.h>
+#include <media/stagefright/SimpleDecodingSource.h>
 #include "SineSource.h"
 
 using namespace android;
@@ -79,8 +80,6 @@
     const int32_t kBitRate = outputWBAMR ? 16000 : 8000;
 
     android::ProcessState::self()->startThreadPool();
-    OMXClient client;
-    CHECK_EQ(client.connect(), (status_t)OK);
     sp<MediaSource> source;
 
     if (useMic) {
@@ -95,24 +94,25 @@
         source = new SineSource(kSampleRate, channels);
     }
 
-    sp<MetaData> meta = new MetaData;
-    meta->setCString(
-            kKeyMIMEType,
+    sp<AMessage> meta = new AMessage;
+    meta->setString(
+            "mime",
             outputWBAMR ? MEDIA_MIMETYPE_AUDIO_AMR_WB
                     : MEDIA_MIMETYPE_AUDIO_AMR_NB);
 
-    meta->setInt32(kKeyChannelCount, channels);
-    meta->setInt32(kKeySampleRate, kSampleRate);
-    meta->setInt32(kKeyBitRate, kBitRate);
+    meta->setInt32("channel-count", channels);
+    meta->setInt32("sample-rate", kSampleRate);
+    meta->setInt32("bitrate", kBitRate);
     int32_t maxInputSize;
     if (source->getFormat()->findInt32(kKeyMaxInputSize, &maxInputSize)) {
-        meta->setInt32(kKeyMaxInputSize, maxInputSize);
+        meta->setInt32("max-input-size", maxInputSize);
     }
 
-    sp<MediaSource> encoder = OMXCodec::Create(
-            client.interface(),
-            meta, true /* createEncoder */,
-            source);
+    sp<ALooper> looper = new ALooper;
+    looper->setName("audioloop");
+    looper->start();
+
+    sp<IMediaSource> encoder = MediaCodecSource::Create(looper, meta, source);
 
     if (fileOut != NULL) {
         // target file specified, write encoded AMR output
@@ -128,17 +128,15 @@
         writer->stop();
     } else {
         // otherwise decode to speaker
-        sp<MediaSource> decoder = OMXCodec::Create(
-                client.interface(),
-                meta, false /* createEncoder */,
-                encoder);
+        sp<IMediaSource> decoder = SimpleDecodingSource::Create(encoder);
 
         if (playToSpeaker) {
             AudioPlayer *player = new AudioPlayer(NULL);
             player->setSource(decoder);
             player->start();
             sleep(duration);
-            source->stop(); // must stop source otherwise delete player will hang
+
+            decoder.clear(); // must clear |decoder| otherwise delete player will hang.
             delete player; // there is no player->stop()...
         } else {
             CHECK_EQ(decoder->start(), (status_t)OK);
diff --git a/cmds/stagefright/muxer.cpp b/cmds/stagefright/muxer.cpp
index 36fa3b5..0a3bdf3 100644
--- a/cmds/stagefright/muxer.cpp
+++ b/cmds/stagefright/muxer.cpp
@@ -43,6 +43,7 @@
     fprintf(stderr, "       -h help\n");
     fprintf(stderr, "       -a use audio\n");
     fprintf(stderr, "       -v use video\n");
+    fprintf(stderr, "       -w mux into WebM container (default is MP4)\n");
     fprintf(stderr, "       -s Time in milli-seconds when the trim should start\n");
     fprintf(stderr, "       -e Time in milli-seconds when the trim should end\n");
     fprintf(stderr, "       -o output file name. Default is /sdcard/muxeroutput.mp4\n");
@@ -60,7 +61,8 @@
         bool enableTrim,
         int trimStartTimeMs,
         int trimEndTimeMs,
-        int rotationDegrees) {
+        int rotationDegrees,
+        MediaMuxer::OutputFormat container = MediaMuxer::OUTPUT_FORMAT_MPEG_4) {
     sp<NuMediaExtractor> extractor = new NuMediaExtractor;
     if (extractor->setDataSource(NULL /* httpService */, path) != OK) {
         fprintf(stderr, "unable to instantiate extractor. %s\n", path);
@@ -80,8 +82,7 @@
         ALOGE("couldn't open file");
         return fd;
     }
-    sp<MediaMuxer> muxer = new MediaMuxer(fd,
-                                          MediaMuxer::OUTPUT_FORMAT_MPEG_4);
+    sp<MediaMuxer> muxer = new MediaMuxer(fd, container);
     close(fd);
 
     size_t trackCount = extractor->countTracks();
@@ -237,9 +238,10 @@
     // When trimStartTimeMs and trimEndTimeMs seems valid, we turn this switch
     // to true.
     bool enableTrim = false;
+    MediaMuxer::OutputFormat container = MediaMuxer::OUTPUT_FORMAT_MPEG_4;
 
     int res;
-    while ((res = getopt(argc, argv, "h?avo:s:e:r:")) >= 0) {
+    while ((res = getopt(argc, argv, "h?avo:s:e:r:w")) >= 0) {
         switch (res) {
             case 'a':
             {
@@ -253,6 +255,12 @@
                 break;
             }
 
+            case 'w':
+            {
+                container = MediaMuxer::OUTPUT_FORMAT_WEBM;
+                break;
+            }
+
             case 'o':
             {
                 outputFileName = optarg;
@@ -318,7 +326,7 @@
     looper->start();
 
     int result = muxing(argv[0], useAudio, useVideo, outputFileName,
-                        enableTrim, trimStartTimeMs, trimEndTimeMs, rotationDegrees);
+                        enableTrim, trimStartTimeMs, trimEndTimeMs, rotationDegrees, container);
 
     looper->stop();
 
diff --git a/cmds/stagefright/record.cpp b/cmds/stagefright/record.cpp
index 594c933..9aa0156 100644
--- a/cmds/stagefright/record.cpp
+++ b/cmds/stagefright/record.cpp
@@ -18,16 +18,18 @@
 
 #include <binder/ProcessState.h>
 #include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/ALooper.h>
+#include <media/stagefright/foundation/AMessage.h>
 #include <media/stagefright/AudioPlayer.h>
 #include <media/stagefright/CameraSource.h>
 #include <media/stagefright/FileSource.h>
 #include <media/stagefright/MediaBufferGroup.h>
 #include <media/stagefright/MediaDefs.h>
+#include <media/stagefright/MediaCodecSource.h>
 #include <media/stagefright/MetaData.h>
 #include <media/stagefright/MediaExtractor.h>
 #include <media/stagefright/MPEG4Writer.h>
-#include <media/stagefright/OMXClient.h>
-#include <media/stagefright/OMXCodec.h>
+#include <media/stagefright/SimpleDecodingSource.h>
 #include <media/MediaPlayerInterface.h>
 
 using namespace android;
@@ -182,9 +184,6 @@
         fprintf(stderr, "input color format must be 0 (YUV420SP) or 1 (YUV420P)\n");
         return 1;
     }
-    OMXClient client;
-    CHECK_EQ(client.connect(), (status_t)OK);
-
     status_t err = OK;
 
 #if 0
@@ -197,8 +196,7 @@
 
     sp<MetaData> meta = source->getFormat();
 
-    sp<MediaSource> decoder = OMXCodec::Create(
-            client.interface(), meta, false /* createEncoder */, source);
+    sp<MediaSource> decoder = SimpleDecodingSource::Create(source);
 
     int width, height;
     bool success = meta->findInt32(kKeyWidth, &width);
@@ -210,22 +208,21 @@
     sp<MediaSource> decoder = new DummySource(width, height, colorFormat);
 #endif
 
-    sp<MetaData> enc_meta = new MetaData;
-    // enc_meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_H263);
-    // enc_meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_MPEG4);
-    enc_meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_AVC);
-    enc_meta->setInt32(kKeyWidth, width);
-    enc_meta->setInt32(kKeyHeight, height);
-    enc_meta->setInt32(kKeySampleRate, kFramerate);
-    enc_meta->setInt32(kKeyBitRate, kVideoBitRate);
-    enc_meta->setInt32(kKeyStride, width);
-    enc_meta->setInt32(kKeySliceHeight, height);
-    enc_meta->setInt32(kKeyIFramesInterval, kIFramesIntervalSec);
-    enc_meta->setInt32(kKeyColorFormat, colorFormat);
+    sp<AMessage> enc_meta = new AMessage;
+    // enc_meta->setString("mime", MEDIA_MIMETYPE_VIDEO_H263);
+    // enc_meta->setString("mime", MEDIA_MIMETYPE_VIDEO_MPEG4);
+    enc_meta->setString("mime", MEDIA_MIMETYPE_VIDEO_AVC);
+    enc_meta->setInt32("width", width);
+    enc_meta->setInt32("height", height);
+    enc_meta->setInt32("sample-rate", kFramerate);
+    enc_meta->setInt32("bitrate", kVideoBitRate);
+    // enc_meta->setInt32("stride", width);
+    // enc_meta->setInt32("slice-height", height);
+    enc_meta->setInt32("i-frame-interval", kIFramesIntervalSec);
+    enc_meta->setInt32("color-format", colorFormat);
 
     sp<MediaSource> encoder =
-        OMXCodec::Create(
-                client.interface(), enc_meta, true /* createEncoder */, decoder);
+        MediaCodecSource::Create(looper, format, decoder);
 
 #if 1
     sp<MPEG4Writer> writer = new MPEG4Writer("/sdcard/output.mp4");
@@ -260,7 +257,6 @@
 #endif
 
     printf("$\n");
-    client.disconnect();
 #endif
 
 #if 0
@@ -299,9 +295,6 @@
 int main(int /* argc */, char ** /* argv */) {
     android::ProcessState::self()->startThreadPool();
 
-    OMXClient client;
-    CHECK_EQ(client.connect(), (status_t)OK);
-
     const int32_t kSampleRate = 22050;
     const int32_t kNumChannels = 2;
     sp<MediaSource> audioSource = new SineSource(kSampleRate, kNumChannels);
@@ -317,16 +310,20 @@
     player->stop();
 #endif
 
-    sp<MetaData> encMeta = new MetaData;
-    encMeta->setCString(kKeyMIMEType,
+    sp<AMessage> encMeta = new AMessage;
+    encMeta->setString("mime",
             0 ? MEDIA_MIMETYPE_AUDIO_AMR_WB : MEDIA_MIMETYPE_AUDIO_AAC);
-    encMeta->setInt32(kKeySampleRate, kSampleRate);
-    encMeta->setInt32(kKeyChannelCount, kNumChannels);
-    encMeta->setInt32(kKeyMaxInputSize, 8192);
-    encMeta->setInt32(kKeyBitRate, kAudioBitRate);
+    encMeta->setInt32("sample-rate", kSampleRate);
+    encMeta->setInt32("channel-count", kNumChannels);
+    encMeta->setInt32("max-input-size", 8192);
+    encMeta->setInt32("bitrate", kAudioBitRate);
 
-    sp<MediaSource> encoder =
-        OMXCodec::Create(client.interface(), encMeta, true, audioSource);
+    sp<ALooper> looper = new ALooper;
+    looper->setName("record");
+    looper->start();
+
+    sp<IMediaSource> encoder =
+        MediaCodecSource::Create(looper, encMeta, audioSource);
 
     encoder->start();
 
@@ -348,8 +345,6 @@
 
     encoder->stop();
 
-    client.disconnect();
-
     return 0;
 }
 #endif
diff --git a/cmds/stagefright/recordvideo.cpp b/cmds/stagefright/recordvideo.cpp
index 2ad40bd..7a3c842 100644
--- a/cmds/stagefright/recordvideo.cpp
+++ b/cmds/stagefright/recordvideo.cpp
@@ -23,15 +23,18 @@
 
 #include <binder/ProcessState.h>
 #include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/ALooper.h>
+#include <media/stagefright/foundation/AMessage.h>
 #include <media/stagefright/AudioPlayer.h>
 #include <media/stagefright/MediaBufferGroup.h>
+#include <media/stagefright/MediaCodecSource.h>
 #include <media/stagefright/MediaDefs.h>
 #include <media/stagefright/MetaData.h>
 #include <media/stagefright/MPEG4Writer.h>
-#include <media/stagefright/OMXClient.h>
-#include <media/stagefright/OMXCodec.h>
 #include <media/MediaPlayerInterface.h>
 
+#include <OMX_Video.h>
+
 using namespace android;
 
 // Print usage showing how to use this utility to record videos
@@ -265,44 +268,45 @@
         }
     }
 
-    OMXClient client;
-    CHECK_EQ(client.connect(), (status_t)OK);
-
     status_t err = OK;
     sp<MediaSource> source =
         new DummySource(width, height, nFrames, frameRateFps, colorFormat);
 
-    sp<MetaData> enc_meta = new MetaData;
+    sp<AMessage> enc_meta = new AMessage;
     switch (codec) {
         case 1:
-            enc_meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_MPEG4);
+            enc_meta->setString("mime", MEDIA_MIMETYPE_VIDEO_MPEG4);
             break;
         case 2:
-            enc_meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_H263);
+            enc_meta->setString("mime", MEDIA_MIMETYPE_VIDEO_H263);
             break;
         default:
-            enc_meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_AVC);
+            enc_meta->setString("mime", MEDIA_MIMETYPE_VIDEO_AVC);
             break;
     }
-    enc_meta->setInt32(kKeyWidth, width);
-    enc_meta->setInt32(kKeyHeight, height);
-    enc_meta->setInt32(kKeyFrameRate, frameRateFps);
-    enc_meta->setInt32(kKeyBitRate, bitRateBps);
-    enc_meta->setInt32(kKeyStride, width);
-    enc_meta->setInt32(kKeySliceHeight, height);
-    enc_meta->setInt32(kKeyIFramesInterval, iFramesIntervalSeconds);
-    enc_meta->setInt32(kKeyColorFormat, colorFormat);
+    enc_meta->setInt32("width", width);
+    enc_meta->setInt32("height", height);
+    enc_meta->setInt32("frame-rate", frameRateFps);
+    enc_meta->setInt32("bitrate", bitRateBps);
+    enc_meta->setInt32("stride", width);
+    enc_meta->setInt32("slice-height", height);
+    enc_meta->setInt32("i-frame-interval", iFramesIntervalSeconds);
+    enc_meta->setInt32("color-format", colorFormat);
     if (level != -1) {
-        enc_meta->setInt32(kKeyVideoLevel, level);
+        enc_meta->setInt32("level", level);
     }
     if (profile != -1) {
-        enc_meta->setInt32(kKeyVideoProfile, profile);
+        enc_meta->setInt32("profile", profile);
     }
 
-    sp<MediaSource> encoder =
-        OMXCodec::Create(
-                client.interface(), enc_meta, true /* createEncoder */, source,
-                0, preferSoftwareCodec ? OMXCodec::kPreferSoftwareCodecs : 0);
+    sp<ALooper> looper = new ALooper;
+    looper->setName("recordvideo");
+    looper->start();
+
+    sp<IMediaSource> encoder =
+        MediaCodecSource::Create(
+                looper, enc_meta, source, NULL /* consumer */,
+                preferSoftwareCodec ? MediaCodecSource::FLAG_PREFER_SOFTWARE_CODEC : 0);
 
     int fd = open(fileName, O_CREAT | O_LARGEFILE | O_TRUNC | O_RDWR, S_IRUSR | S_IWUSR);
     if (fd < 0) {
@@ -321,7 +325,6 @@
     int64_t end = systemTime();
 
     fprintf(stderr, "$\n");
-    client.disconnect();
 
     if (err != OK && err != ERROR_END_OF_STREAM) {
         fprintf(stderr, "record failed: %d\n", err);
diff --git a/cmds/stagefright/sf2.cpp b/cmds/stagefright/sf2.cpp
index 0d64d2f..1a4bf08 100644
--- a/cmds/stagefright/sf2.cpp
+++ b/cmds/stagefright/sf2.cpp
@@ -118,7 +118,7 @@
                     DataSource::CreateFromURI(
                             NULL /* httpService */, mURI.c_str());
 
-                sp<MediaExtractor> extractor =
+                sp<IMediaExtractor> extractor =
                     MediaExtractor::Create(dataSource);
 
                 for (size_t i = 0; i < extractor->countTracks(); ++i) {
@@ -264,7 +264,7 @@
     sp<Surface> mSurface;
     bool mRenderToSurface;
     sp<ACodec> mCodec;
-    sp<MediaSource> mSource;
+    sp<IMediaSource> mSource;
     bool mIsVorbis;
 
     Vector<sp<ABuffer> > mCSD;
diff --git a/cmds/stagefright/stagefright.cpp b/cmds/stagefright/stagefright.cpp
index a9c6eda..ca68722 100644
--- a/cmds/stagefright/stagefright.cpp
+++ b/cmds/stagefright/stagefright.cpp
@@ -31,20 +31,27 @@
 
 #include <binder/IServiceManager.h>
 #include <binder/ProcessState.h>
+#include <media/ICrypto.h>
 #include <media/IMediaHTTPService.h>
+#include <media/IMediaCodecService.h>
 #include <media/IMediaPlayerService.h>
+#include <media/stagefright/foundation/ABuffer.h>
 #include <media/stagefright/foundation/ALooper.h>
+#include <media/stagefright/foundation/AMessage.h>
+#include <media/stagefright/foundation/AUtils.h>
 #include "include/NuCachedSource2.h"
 #include <media/stagefright/AudioPlayer.h>
 #include <media/stagefright/DataSource.h>
 #include <media/stagefright/JPEGSource.h>
+#include <media/stagefright/MediaCodec.h>
+#include <media/stagefright/MediaCodecList.h>
 #include <media/stagefright/MediaDefs.h>
 #include <media/stagefright/MediaErrors.h>
 #include <media/stagefright/MediaExtractor.h>
 #include <media/stagefright/MediaSource.h>
 #include <media/stagefright/MetaData.h>
-#include <media/stagefright/OMXClient.h>
-#include <media/stagefright/OMXCodec.h>
+#include <media/stagefright/SimpleDecodingSource.h>
+#include <media/stagefright/Utils.h>
 #include <media/mediametadataretriever.h>
 
 #include <media/stagefright/foundation/hexdump.h>
@@ -67,6 +74,7 @@
 static bool gPlaybackAudio;
 static bool gWriteMP4;
 static bool gDisplayHistogram;
+static bool showProgress = true;
 static String8 gWriteMP4Filename;
 
 static sp<ANativeWindow> gSurface;
@@ -130,7 +138,7 @@
     }
 }
 
-static void dumpSource(const sp<MediaSource> &source, const String8 &filename) {
+static void dumpSource(const sp<IMediaSource> &source, const String8 &filename) {
     FILE *out = fopen(filename.string(), "wb");
 
     CHECK_EQ((status_t)OK, source->start());
@@ -163,32 +171,26 @@
     out = NULL;
 }
 
-static void playSource(OMXClient *client, sp<MediaSource> &source) {
+static void playSource(sp<IMediaSource> &source) {
     sp<MetaData> meta = source->getFormat();
 
     const char *mime;
     CHECK(meta->findCString(kKeyMIMEType, &mime));
 
-    sp<MediaSource> rawSource;
+    sp<IMediaSource> rawSource;
     if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_RAW, mime)) {
         rawSource = source;
     } else {
         int flags = 0;
         if (gPreferSoftwareCodec) {
-            flags |= OMXCodec::kPreferSoftwareCodecs;
+            flags |= MediaCodecList::kPreferSoftwareCodecs;
         }
         if (gForceToUseHardwareCodec) {
             CHECK(!gPreferSoftwareCodec);
-            flags |= OMXCodec::kHardwareCodecsOnly;
+            flags |= MediaCodecList::kHardwareCodecsOnly;
         }
-        rawSource = OMXCodec::Create(
-            client->interface(), meta, false /* createEncoder */, source,
-            NULL /* matchComponentName */,
-            flags,
-            gSurface);
-
+        rawSource = SimpleDecodingSource::Create(source, flags, gSurface);
         if (rawSource == NULL) {
-            fprintf(stderr, "Failed to instantiate decoder for '%s'.\n", mime);
             return;
         }
         displayAVCProfileLevelIfPossible(meta);
@@ -338,7 +340,7 @@
                     decodeTimesUs.push(delayDecodeUs);
                 }
 
-                if ((n++ % 16) == 0) {
+                if (showProgress && (n++ % 16) == 0) {
                     printf(".");
                     fflush(stdout);
                 }
@@ -364,8 +366,10 @@
             }
         }
 
-        printf("$");
-        fflush(stdout);
+        if (showProgress) {
+            printf("$");
+            fflush(stdout);
+        }
 
         options.setSeekTo(0);
     }
@@ -397,7 +401,7 @@
 ////////////////////////////////////////////////////////////////////////////////
 
 struct DetectSyncSource : public MediaSource {
-    DetectSyncSource(const sp<MediaSource> &source);
+    DetectSyncSource(const sp<IMediaSource> &source);
 
     virtual status_t start(MetaData *params = NULL);
     virtual status_t stop();
@@ -414,14 +418,14 @@
         OTHER,
     };
 
-    sp<MediaSource> mSource;
+    sp<IMediaSource> mSource;
     StreamType mStreamType;
     bool mSawFirstIDRFrame;
 
     DISALLOW_EVIL_CONSTRUCTORS(DetectSyncSource);
 };
 
-DetectSyncSource::DetectSyncSource(const sp<MediaSource> &source)
+DetectSyncSource::DetectSyncSource(const sp<IMediaSource> &source)
     : mSource(source),
       mStreamType(OTHER),
       mSawFirstIDRFrame(false) {
@@ -503,7 +507,7 @@
 ////////////////////////////////////////////////////////////////////////////////
 
 static void writeSourcesToMP4(
-        Vector<sp<MediaSource> > &sources, bool syncInfoPresent) {
+        Vector<sp<IMediaSource> > &sources, bool syncInfoPresent) {
 #if 0
     sp<MPEG4Writer> writer =
         new MPEG4Writer(gWriteMP4Filename.string());
@@ -521,7 +525,7 @@
     writer->setMaxFileDuration(60000000ll);
 
     for (size_t i = 0; i < sources.size(); ++i) {
-        sp<MediaSource> source = sources.editItemAt(i);
+        sp<IMediaSource> source = sources.editItemAt(i);
 
         CHECK_EQ(writer->addSource(
                     syncInfoPresent ? source : new DetectSyncSource(source)),
@@ -538,7 +542,7 @@
     writer->stop();
 }
 
-static void performSeekTest(const sp<MediaSource> &source) {
+static void performSeekTest(const sp<IMediaSource> &source) {
     CHECK_EQ((status_t)OK, source->start());
 
     int64_t durationUs;
@@ -612,49 +616,57 @@
     fprintf(stderr, "       -k seek test\n");
     fprintf(stderr, "       -x display a histogram of decoding times/fps "
                     "(video only)\n");
+    fprintf(stderr, "       -q don't show progress indicator\n");
     fprintf(stderr, "       -S allocate buffers from a surface\n");
     fprintf(stderr, "       -T allocate buffers from a surface texture\n");
     fprintf(stderr, "       -d(ump) output_filename (raw stream data to a file)\n");
     fprintf(stderr, "       -D(ump) output_filename (decoded PCM data to a file)\n");
 }
 
-static void dumpCodecProfiles(const sp<IOMX>& omx, bool queryDecoders) {
+static void dumpCodecProfiles(bool queryDecoders) {
     const char *kMimeTypes[] = {
         MEDIA_MIMETYPE_VIDEO_AVC, MEDIA_MIMETYPE_VIDEO_MPEG4,
         MEDIA_MIMETYPE_VIDEO_H263, MEDIA_MIMETYPE_AUDIO_AAC,
         MEDIA_MIMETYPE_AUDIO_AMR_NB, MEDIA_MIMETYPE_AUDIO_AMR_WB,
         MEDIA_MIMETYPE_AUDIO_MPEG, MEDIA_MIMETYPE_AUDIO_G711_MLAW,
         MEDIA_MIMETYPE_AUDIO_G711_ALAW, MEDIA_MIMETYPE_AUDIO_VORBIS,
-        MEDIA_MIMETYPE_VIDEO_VP8, MEDIA_MIMETYPE_VIDEO_VP9
+        MEDIA_MIMETYPE_VIDEO_VP8, MEDIA_MIMETYPE_VIDEO_VP9,
+        MEDIA_MIMETYPE_VIDEO_DOLBY_VISION
     };
 
     const char *codecType = queryDecoders? "decoder" : "encoder";
     printf("%s profiles:\n", codecType);
 
+    sp<IMediaCodecList> list = MediaCodecList::getInstance();
+    size_t numCodecs = list->countCodecs();
+
     for (size_t k = 0; k < sizeof(kMimeTypes) / sizeof(kMimeTypes[0]); ++k) {
         printf("type '%s':\n", kMimeTypes[k]);
 
-        Vector<CodecCapabilities> results;
-        // will retrieve hardware and software codecs
-        CHECK_EQ(QueryCodecs(omx, kMimeTypes[k],
-                             queryDecoders,
-                             &results), (status_t)OK);
-
-        for (size_t i = 0; i < results.size(); ++i) {
+        for (size_t index = 0; index < numCodecs; ++index) {
+            sp<MediaCodecInfo> info = list->getCodecInfo(index);
+            if (info == NULL || info->isEncoder() != !queryDecoders) {
+                continue;
+            }
+            sp<MediaCodecInfo::Capabilities> caps = info->getCapabilitiesFor(kMimeTypes[k]);
+            if (caps == NULL) {
+                continue;
+            }
             printf("  %s '%s' supports ",
-                       codecType, results[i].mComponentName.string());
+                       codecType, info->getCodecName());
 
-            if (results[i].mProfileLevels.size() == 0) {
-                    printf("NOTHING.\n");
-                    continue;
+            Vector<MediaCodecInfo::ProfileLevel> profileLevels;
+            caps->getSupportedProfileLevels(&profileLevels);
+            if (profileLevels.size() == 0) {
+                printf("NOTHING.\n");
+                continue;
             }
 
-            for (size_t j = 0; j < results[i].mProfileLevels.size(); ++j) {
-                const CodecProfileLevel &profileLevel =
-                     results[i].mProfileLevels[j];
+            for (size_t j = 0; j < profileLevels.size(); ++j) {
+                const MediaCodecInfo::ProfileLevel &profileLevel = profileLevels[j];
 
-                printf("%s%" PRIu32 "/%" PRIu32, j > 0 ? ", " : "",
-                    profileLevel.mProfile, profileLevel.mLevel);
+                printf("%s%u/%u", j > 0 ? ", " : "",
+                        profileLevel.mProfile, profileLevel.mLevel);
             }
 
             printf("\n");
@@ -687,7 +699,7 @@
     sp<ALooper> looper;
 
     int res;
-    while ((res = getopt(argc, argv, "han:lm:b:ptsrow:kxSTd:D:")) >= 0) {
+    while ((res = getopt(argc, argv, "haqn:lm:b:ptsrow:kxSTd:D:")) >= 0) {
         switch (res) {
             case 'a':
             {
@@ -695,6 +707,12 @@
                 break;
             }
 
+            case 'q':
+            {
+                showProgress = false;
+                break;
+            }
+
             case 'd':
             {
                 dumpStream = true;
@@ -881,23 +899,14 @@
     }
 
     if (dumpProfiles) {
-        sp<IServiceManager> sm = defaultServiceManager();
-        sp<IBinder> binder = sm->getService(String16("media.player"));
-        sp<IMediaPlayerService> service =
-            interface_cast<IMediaPlayerService>(binder);
-
-        CHECK(service.get() != NULL);
-
-        sp<IOMX> omx = service->getOMX();
-        CHECK(omx.get() != NULL);
-        dumpCodecProfiles(omx, true /* queryDecoders */);
-        dumpCodecProfiles(omx, false /* queryDecoders */);
+        dumpCodecProfiles(true /* queryDecoders */);
+        dumpCodecProfiles(false /* queryDecoders */);
     }
 
     if (listComponents) {
         sp<IServiceManager> sm = defaultServiceManager();
-        sp<IBinder> binder = sm->getService(String16("media.player"));
-        sp<IMediaPlayerService> service = interface_cast<IMediaPlayerService>(binder);
+        sp<IBinder> binder = sm->getService(String16("media.codec"));
+        sp<IMediaCodecService> service = interface_cast<IMediaCodecService>(binder);
 
         CHECK(service.get() != NULL);
 
@@ -954,16 +963,11 @@
                     false /* isControlledByApp */);
             gSurface = new Surface(producer);
         }
-
-        CHECK_EQ((status_t)OK,
-                 native_window_api_connect(
-                     gSurface.get(), NATIVE_WINDOW_API_MEDIA));
     }
 
     DataSource::RegisterDefaultSniffers();
 
-    OMXClient client;
-    status_t err = client.connect();
+    status_t err = OK;
 
     for (int k = 0; k < argc && err == OK; ++k) {
         bool syncInfoPresent = true;
@@ -985,8 +989,8 @@
             isJPEG = true;
         }
 
-        Vector<sp<MediaSource> > mediaSources;
-        sp<MediaSource> mediaSource;
+        Vector<sp<IMediaSource> > mediaSources;
+        sp<IMediaSource> mediaSource;
 
         if (isJPEG) {
             mediaSource = new JPEGSource(dataSource);
@@ -1005,7 +1009,7 @@
                 mediaSources.push(mediaSource);
             }
         } else {
-            sp<MediaExtractor> extractor = MediaExtractor::Create(dataSource);
+            sp<IMediaExtractor> extractor = MediaExtractor::Create(dataSource);
 
             if (extractor == NULL) {
                 fprintf(stderr, "could not create extractor.\n");
@@ -1016,7 +1020,10 @@
 
             if (meta != NULL) {
                 const char *mime;
-                CHECK(meta->findCString(kKeyMIMEType, &mime));
+                if (!meta->findCString(kKeyMIMEType, &mime)) {
+                    fprintf(stderr, "extractor did not provide MIME type.\n");
+                    return -1;
+                }
 
                 if (!strcasecmp(mime, MEDIA_MIMETYPE_CONTAINER_MPEG2TS)) {
                     syncInfoPresent = false;
@@ -1029,7 +1036,7 @@
                 bool haveAudio = false;
                 bool haveVideo = false;
                 for (size_t i = 0; i < numTracks; ++i) {
-                    sp<MediaSource> source = extractor->getTrack(i);
+                    sp<IMediaSource> source = extractor->getTrack(i);
 
                     const char *mime;
                     CHECK(source->getFormat()->findCString(
@@ -1059,6 +1066,9 @@
                     meta = extractor->getTrackMetaData(
                             i, MediaExtractor::kIncludeExtensiveMetaData);
 
+                    if (meta == NULL) {
+                        break;
+                    }
                     const char *mime;
                     meta->findCString(kKeyMIMEType, &mime);
 
@@ -1097,31 +1107,16 @@
         } else if (dumpStream) {
             dumpSource(mediaSource, dumpStreamFilename);
         } else if (dumpPCMStream) {
-            OMXClient client;
-            CHECK_EQ(client.connect(), (status_t)OK);
-
-            sp<MediaSource> decSource =
-                OMXCodec::Create(
-                        client.interface(),
-                        mediaSource->getFormat(),
-                        false,
-                        mediaSource,
-                        0,
-                        0);
-
+            sp<IMediaSource> decSource = SimpleDecodingSource::Create(mediaSource);
             dumpSource(decSource, dumpStreamFilename);
         } else if (seekTest) {
             performSeekTest(mediaSource);
         } else {
-            playSource(&client, mediaSource);
+            playSource(mediaSource);
         }
     }
 
     if ((useSurfaceAlloc || useSurfaceTexAlloc) && !audioOnly) {
-        CHECK_EQ((status_t)OK,
-                 native_window_api_disconnect(
-                     gSurface.get(), NATIVE_WINDOW_API_MEDIA));
-
         gSurface.clear();
 
         if (useSurfaceAlloc) {
@@ -1129,7 +1124,5 @@
         }
     }
 
-    client.disconnect();
-
     return 0;
 }
diff --git a/cmds/stagefright/stream.cpp b/cmds/stagefright/stream.cpp
index 1a40e53..bca3832 100644
--- a/cmds/stagefright/stream.cpp
+++ b/cmds/stagefright/stream.cpp
@@ -165,7 +165,7 @@
 
     CHECK(dataSource != NULL);
 
-    sp<MediaExtractor> extractor = MediaExtractor::Create(dataSource);
+    sp<IMediaExtractor> extractor = MediaExtractor::Create(dataSource);
     CHECK(extractor != NULL);
 
     mWriter = new MPEG2TSWriter(
diff --git a/drm/common/IDrmManagerService.cpp b/drm/common/IDrmManagerService.cpp
index f2e14b6..caae75f 100644
--- a/drm/common/IDrmManagerService.cpp
+++ b/drm/common/IDrmManagerService.cpp
@@ -303,7 +303,9 @@
         const String8 value = drmInforequest->get(key);
         if (key == String8("FileDescriptorKey")) {
             int fd = -1;
-            sscanf(value.string(), "FileDescriptor[%d]", &fd);
+            if (sscanf(value.string(), "FileDescriptor[%d]", &fd) != 1) {
+                sscanf(value.string(), "%d", &fd);
+            }
             data.writeFileDescriptor(fd);
         } else {
             data.writeString8((value == String8("")) ? String8("NULL") : value);
diff --git a/drm/drmserver/Android.mk b/drm/drmserver/Android.mk
index 48ea385..3b8bb04 100644
--- a/drm/drmserver/Android.mk
+++ b/drm/drmserver/Android.mk
@@ -36,10 +36,14 @@
     $(TOP)/frameworks/av/drm/libdrmframework/include \
     $(TOP)/frameworks/av/drm/libdrmframework/plugins/common/include
 
+LOCAL_CFLAGS += -Wall -Wextra -Werror
+
 LOCAL_MODULE:= drmserver
 
 LOCAL_MODULE_TAGS := optional
 
 LOCAL_32_BIT_ONLY := true
 
+LOCAL_INIT_RC := drmserver.rc
+
 include $(BUILD_EXECUTABLE)
diff --git a/drm/drmserver/DrmManager.cpp b/drm/drmserver/DrmManager.cpp
index d8aeb0c..e168ba2 100644
--- a/drm/drmserver/DrmManager.cpp
+++ b/drm/drmserver/DrmManager.cpp
@@ -370,7 +370,7 @@
 }
 
 status_t DrmManager::getAllSupportInfo(
-                    int uniqueId, int* length, DrmSupportInfo** drmSupportInfoArray) {
+                    int /* uniqueId */, int* length, DrmSupportInfo** drmSupportInfoArray) {
     Mutex::Autolock _l(mLock);
     Vector<String8> plugInPathList = mPlugInManager.getPlugInIdList();
     int size = plugInPathList.size();
diff --git a/drm/drmserver/DrmManagerService.cpp b/drm/drmserver/DrmManagerService.cpp
index 857d73e..dad599b 100644
--- a/drm/drmserver/DrmManagerService.cpp
+++ b/drm/drmserver/DrmManagerService.cpp
@@ -51,8 +51,7 @@
 const char *DrmManagerService::get_perm_label(drm_perm_t perm) {
     unsigned int index = perm;
 
-    if (index < 0 ||
-            index >= (sizeof(drm_perm_labels) / sizeof(drm_perm_labels[0]))) {
+    if (index >= (sizeof(drm_perm_labels) / sizeof(drm_perm_labels[0]))) {
         ALOGE("SELinux: Failed to retrieve permission label(perm=%d).\n", perm);
         abort();
     }
@@ -358,8 +357,12 @@
             }
         }
         if (dumpMem) {
-            dumpMemoryAddresses(fd);
+            result.append("\nDumping memory:\n");
+            std::string s = dumpMemoryAddresses(100 /* limit */);
+            result.append(s.c_str(), s.size());
         }
+#else
+        (void)args;
 #endif
     }
     write(fd, result.string(), result.size());
diff --git a/drm/drmserver/drmserver.rc b/drm/drmserver/drmserver.rc
new file mode 100644
index 0000000..de46fb9
--- /dev/null
+++ b/drm/drmserver/drmserver.rc
@@ -0,0 +1,5 @@
+service drm /system/bin/drmserver
+    class main
+    user drm
+    group drm system inet drmrpc readproc
+    writepid /dev/cpuset/foreground/tasks
diff --git a/drm/drmserver/main_drmserver.cpp b/drm/drmserver/main_drmserver.cpp
index 434d561..8f697a4 100644
--- a/drm/drmserver/main_drmserver.cpp
+++ b/drm/drmserver/main_drmserver.cpp
@@ -26,8 +26,10 @@
 
 using namespace android;
 
-int main(int argc, char** argv)
+int main()
 {
+    signal(SIGPIPE, SIG_IGN);
+
     sp<ProcessState> proc(ProcessState::self());
     sp<IServiceManager> sm = defaultServiceManager();
     ALOGV("ServiceManager: %p", sm.get());
diff --git a/drm/libdrmframework/Android.mk b/drm/libdrmframework/Android.mk
index 33f9d3b..cafcb94 100644
--- a/drm/libdrmframework/Android.mk
+++ b/drm/libdrmframework/Android.mk
@@ -38,6 +38,7 @@
     $(TOP)/frameworks/av/drm/libdrmframework/include \
     $(TOP)/frameworks/av/include
 
+LOCAL_CFLAGS += -Werror
 
 
 LOCAL_MODULE_TAGS := optional
diff --git a/drm/libdrmframework/DrmManagerClientImpl.cpp b/drm/libdrmframework/DrmManagerClientImpl.cpp
index 9457bb6..cbd013e 100644
--- a/drm/libdrmframework/DrmManagerClientImpl.cpp
+++ b/drm/libdrmframework/DrmManagerClientImpl.cpp
@@ -350,7 +350,8 @@
     }
 }
 
-void DrmManagerClientImpl::DeathNotifier::binderDied(const wp<IBinder>& who) {
+void DrmManagerClientImpl::DeathNotifier::binderDied(
+            const wp<IBinder>& /* who */) {
     Mutex::Autolock lock(sMutex);
     DrmManagerClientImpl::sDrmManagerService.clear();
     ALOGW("DrmManager server died!");
diff --git a/drm/libdrmframework/NoOpDrmManagerClientImpl.cpp b/drm/libdrmframework/NoOpDrmManagerClientImpl.cpp
index dab583d..1172e80 100644
--- a/drm/libdrmframework/NoOpDrmManagerClientImpl.cpp
+++ b/drm/libdrmframework/NoOpDrmManagerClientImpl.cpp
@@ -18,134 +18,209 @@
 
 namespace android {
 
-void NoOpDrmManagerClientImpl::remove(int uniqueId) {
+void NoOpDrmManagerClientImpl::remove(int /* uniqueId */) {
 }
 
-void NoOpDrmManagerClientImpl::addClient(int uniqueId) {
+void NoOpDrmManagerClientImpl::addClient(int /* uniqueId */) {
 }
 
-void NoOpDrmManagerClientImpl::removeClient(int uniqueId) {
+void NoOpDrmManagerClientImpl::removeClient(
+            int /* uniqueId */) {
 }
 
 status_t NoOpDrmManagerClientImpl::setOnInfoListener(
-            int uniqueId, const sp<DrmManagerClient::OnInfoListener>& infoListener) {
+            int /* uniqueId */,
+            const sp<DrmManagerClient::OnInfoListener>& /* infoListener */) {
     return UNKNOWN_ERROR;
 }
 
-DrmConstraints* NoOpDrmManagerClientImpl::getConstraints(int uniqueId, const String8* path, const int action) {
+DrmConstraints* NoOpDrmManagerClientImpl::getConstraints(
+            int /* uniqueId */,
+            const String8* /* path */,
+            const int /* action */) {
     return NULL;
 }
 
-DrmMetadata* NoOpDrmManagerClientImpl::getMetadata(int uniqueId, const String8* path) {
+DrmMetadata* NoOpDrmManagerClientImpl::getMetadata(
+            int /* uniqueId */,
+            const String8* /* path */) {
     return NULL;
 }
 
-bool NoOpDrmManagerClientImpl::canHandle(int uniqueId, const String8& path, const String8& mimeType) {
+bool NoOpDrmManagerClientImpl::canHandle(
+            int /* uniqueId */,
+            const String8& /* path */,
+            const String8& /* mimeType */) {
     return false;
 }
 
-DrmInfoStatus* NoOpDrmManagerClientImpl::processDrmInfo(int uniqueId, const DrmInfo* drmInfo) {
+DrmInfoStatus* NoOpDrmManagerClientImpl::processDrmInfo(
+            int /* uniqueId */,
+            const DrmInfo* /* drmInfo */) {
     return NULL;
 }
 
-DrmInfo* NoOpDrmManagerClientImpl::acquireDrmInfo(int uniqueId, const DrmInfoRequest* drmInfoRequest) {
+DrmInfo* NoOpDrmManagerClientImpl::acquireDrmInfo(
+            int /* uniqueId */,
+            const DrmInfoRequest* /* drmInfoRequest */) {
     return NULL;
 }
 
-status_t NoOpDrmManagerClientImpl::saveRights(int uniqueId, const DrmRights& drmRights,
-            const String8& rightsPath, const String8& contentPath) {
+status_t NoOpDrmManagerClientImpl::saveRights(
+            int /* uniqueId */,
+            const DrmRights& /* drmRights */,
+            const String8& /* rightsPath */,
+            const String8& /* contentPath */) {
     return UNKNOWN_ERROR;
 }
 
-String8 NoOpDrmManagerClientImpl::getOriginalMimeType(int uniqueId, const String8& path, int fd) {
+String8 NoOpDrmManagerClientImpl::getOriginalMimeType(
+            int /* uniqueId */,
+            const String8& /* path */,
+            int /* fd */) {
     return String8();
 }
 
-int NoOpDrmManagerClientImpl::getDrmObjectType(int uniqueId, const String8& path, const String8& mimeType) {
+int NoOpDrmManagerClientImpl::getDrmObjectType(
+            int /* uniqueId */,
+            const String8& /* path */,
+            const String8& /* mimeType */) {
     return -1;
 }
 
-int NoOpDrmManagerClientImpl::checkRightsStatus(int uniqueId, const String8& path, int action) {
+int NoOpDrmManagerClientImpl::checkRightsStatus(
+            int /* uniqueId */,
+            const String8& /* path */,
+            int /* action */) {
     return -1;
 }
 
-status_t NoOpDrmManagerClientImpl::consumeRights(int uniqueId, sp<DecryptHandle> &decryptHandle, int action, bool reserve) {
+status_t NoOpDrmManagerClientImpl::consumeRights(
+            int /* uniqueId */,
+            sp<DecryptHandle> &/* decryptHandle */,
+            int /* action */,
+            bool /* reserve */) {
     return UNKNOWN_ERROR;
 }
 
 status_t NoOpDrmManagerClientImpl::setPlaybackStatus(
-            int uniqueId, sp<DecryptHandle> &decryptHandle, int playbackStatus, int64_t position) {
+            int /* uniqueId */,
+            sp<DecryptHandle> &/* decryptHandle */,
+            int /* playbackStatus */,
+            int64_t /* position */) {
     return UNKNOWN_ERROR;
 }
 
 bool NoOpDrmManagerClientImpl::validateAction(
-        int uniqueId, const String8& path, int action, const ActionDescription& description) {
+            int /* uniqueId */,
+            const String8& /* path */,
+            int /* action */,
+            const ActionDescription& /* description */) {
     return false;
 }
 
-status_t NoOpDrmManagerClientImpl::removeRights(int uniqueId, const String8& path) {
+status_t NoOpDrmManagerClientImpl::removeRights(
+            int /* uniqueId */,
+            const String8& /* path */) {
     return UNKNOWN_ERROR;
 }
 
-status_t NoOpDrmManagerClientImpl::removeAllRights(int uniqueId) {
+status_t NoOpDrmManagerClientImpl::removeAllRights(
+            int /* uniqueId */) {
     return UNKNOWN_ERROR;
 }
 
-int NoOpDrmManagerClientImpl::openConvertSession(int uniqueId, const String8& mimeType) {
+int NoOpDrmManagerClientImpl::openConvertSession(
+            int /* uniqueId */,
+            const String8& /* mimeType */) {
     return -1;
 }
 
-DrmConvertedStatus* NoOpDrmManagerClientImpl::convertData(int uniqueId, int convertId, const DrmBuffer* inputData) {
+DrmConvertedStatus* NoOpDrmManagerClientImpl::convertData(
+            int /* uniqueId */,
+            int /* convertId */,
+            const DrmBuffer* /* inputData */) {
     return NULL;
 }
 
-DrmConvertedStatus* NoOpDrmManagerClientImpl::closeConvertSession(int uniqueId, int convertId) {
+DrmConvertedStatus* NoOpDrmManagerClientImpl::closeConvertSession(
+            int /* uniqueId */,
+            int /* convertId */) {
     return NULL;
 }
 
-status_t NoOpDrmManagerClientImpl::getAllSupportInfo(int uniqueId, int* length, DrmSupportInfo** drmSupportInfoArray) {
+status_t NoOpDrmManagerClientImpl::getAllSupportInfo(
+            int /* uniqueId */,
+            int* /* length */,
+            DrmSupportInfo** /* drmSupportInfoArray */) {
     return UNKNOWN_ERROR;
 }
 
 sp<DecryptHandle> NoOpDrmManagerClientImpl::openDecryptSession(
-            int uniqueId, int fd, off64_t offset, off64_t length, const char* mime) {
+            int /* uniqueId */,
+            int /* fd */,
+            off64_t /* offset */,
+            off64_t /* length */,
+            const char* /* mime */) {
     return NULL;
 }
 
 sp<DecryptHandle> NoOpDrmManagerClientImpl::openDecryptSession(
-            int uniqueId, const char* uri, const char* mime) {
+            int /* uniqueId */,
+            const char* /* uri */,
+            const char* /* mime */) {
     return NULL;
 }
 
-sp<DecryptHandle> NoOpDrmManagerClientImpl::openDecryptSession(int uniqueId, const DrmBuffer& buf,
-            const String8& mimeType) {
+sp<DecryptHandle> NoOpDrmManagerClientImpl::openDecryptSession(
+            int /* uniqueId */,
+            const DrmBuffer& /* buf */,
+            const String8& /* mimeType */) {
     return NULL;
 }
 
-status_t NoOpDrmManagerClientImpl::closeDecryptSession(int uniqueId, sp<DecryptHandle> &decryptHandle) {
+status_t NoOpDrmManagerClientImpl::closeDecryptSession(
+            int /* uniqueId */,
+            sp<DecryptHandle> &/* decryptHandle */) {
     return UNKNOWN_ERROR;
 }
 
-status_t NoOpDrmManagerClientImpl::initializeDecryptUnit(int uniqueId, sp<DecryptHandle> &decryptHandle,
-            int decryptUnitId, const DrmBuffer* headerInfo) {
+status_t NoOpDrmManagerClientImpl::initializeDecryptUnit(
+            int /* uniqueId */,
+            sp<DecryptHandle> &/* decryptHandle */,
+            int /* decryptUnitId */,
+            const DrmBuffer* /* headerInfo */) {
     return UNKNOWN_ERROR;
 }
 
-status_t NoOpDrmManagerClientImpl::decrypt(int uniqueId, sp<DecryptHandle> &decryptHandle, int decryptUnitId,
-            const DrmBuffer* encBuffer, DrmBuffer** decBuffer, DrmBuffer* IV) {
+status_t NoOpDrmManagerClientImpl::decrypt(
+            int /* uniqueId */,
+            sp<DecryptHandle> &/* decryptHandle */,
+            int /* decryptUnitId */,
+            const DrmBuffer* /* encBuffer */,
+            DrmBuffer** /* decBuffer */,
+            DrmBuffer* /* IV */) {
     return UNKNOWN_ERROR;
 }
 
-status_t NoOpDrmManagerClientImpl::finalizeDecryptUnit(int uniqueId, sp<DecryptHandle> &decryptHandle, int decryptUnitId) {
+status_t NoOpDrmManagerClientImpl::finalizeDecryptUnit(
+            int /* uniqueId */,
+            sp<DecryptHandle> &/* decryptHandle */,
+            int /* decryptUnitId */) {
     return UNKNOWN_ERROR;
 }
 
-ssize_t NoOpDrmManagerClientImpl::pread(int uniqueId, sp<DecryptHandle> &decryptHandle,
-            void* buffer, ssize_t numBytes, off64_t offset) {
+ssize_t NoOpDrmManagerClientImpl::pread(
+            int /* uniqueId */,
+            sp<DecryptHandle> &/* decryptHandle */,
+            void* /* buffer */,
+            ssize_t /* numBytes */,
+            off64_t /* offset */) {
     return -1;
 }
 
-status_t NoOpDrmManagerClientImpl::notify(const DrmInfoEvent& event) {
+status_t NoOpDrmManagerClientImpl::notify(
+            const DrmInfoEvent& /* event */) {
     return UNKNOWN_ERROR;
 }
 
diff --git a/drm/libdrmframework/plugins/common/include/DrmEngineBase.h b/drm/libdrmframework/plugins/common/include/DrmEngineBase.h
index fa51c13..417107f 100644
--- a/drm/libdrmframework/plugins/common/include/DrmEngineBase.h
+++ b/drm/libdrmframework/plugins/common/include/DrmEngineBase.h
@@ -398,9 +398,9 @@
      *     DRM_ERROR_CANNOT_HANDLE for failure and DRM_NO_ERROR for success
      */
     virtual status_t onOpenDecryptSession(
-            int uniqueId, DecryptHandle* decryptHandle,
-            int fd, off64_t offset, off64_t length,
-            const char* mime) {
+            int /* uniqueId */, DecryptHandle* /* decryptHandle */,
+            int /* fd */, off64_t /* offset */, off64_t /* length */,
+            const char* /* mime */) {
 
         return DRM_ERROR_CANNOT_HANDLE;
     }
@@ -430,8 +430,8 @@
      *     DRM_ERROR_CANNOT_HANDLE for failure and DRM_NO_ERROR for success
      */
     virtual status_t onOpenDecryptSession(
-            int uniqueId, DecryptHandle* decryptHandle,
-            const char* uri, const char* mime) {
+            int /* uniqueId */, DecryptHandle* /* decryptHandle */,
+            const char* /* uri */, const char* /* mime */) {
 
         return DRM_ERROR_CANNOT_HANDLE;
     }
@@ -446,8 +446,10 @@
      * @return
      *     DRM_ERROR_CANNOT_HANDLE for failure and DRM_NO_ERROR for success
      */
-    virtual status_t onOpenDecryptSession(int uniqueId, DecryptHandle* decryptHandle,
-            const DrmBuffer& buf, const String8& mimeType) {
+    virtual status_t onOpenDecryptSession(int /* uniqueId */,
+            DecryptHandle* /* decryptHandle */,
+            const DrmBuffer& /* buf */,
+            const String8& /* mimeType */) {
         return DRM_ERROR_CANNOT_HANDLE;
     }
 
diff --git a/drm/libdrmframework/plugins/common/util/src/MimeTypeUtil.cpp b/drm/libdrmframework/plugins/common/util/src/MimeTypeUtil.cpp
index 576ed15..4bd1adb 100644
--- a/drm/libdrmframework/plugins/common/util/src/MimeTypeUtil.cpp
+++ b/drm/libdrmframework/plugins/common/util/src/MimeTypeUtil.cpp
@@ -115,7 +115,7 @@
  * replacement mimetype otherwise the original mimetype
  * is returned.
  *
- * If the mimetype is of unsupported group i.e. application/*
+ * If the mimetype is of unsupported group i.e. application / *
  * then "unsupported/drm.mimetype" will be returned.
  *
  * @param mimeType - mimetype in lower case to convert.
diff --git a/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/src/FwdLockEngine.cpp b/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/src/FwdLockEngine.cpp
index f400732..a495616 100644
--- a/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/src/FwdLockEngine.cpp
+++ b/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/src/FwdLockEngine.cpp
@@ -119,7 +119,7 @@
     return drmConstraints;
 }
 
-DrmMetadata* FwdLockEngine::onGetMetadata(int uniqueId, const String8* path) {
+DrmMetadata* FwdLockEngine::onGetMetadata(int /* uniqueId */, const String8* path) {
     DrmMetadata* drmMetadata = NULL;
 
     LOG_VERBOSE("FwdLockEngine::onGetMetadata");
@@ -132,7 +132,7 @@
     return drmMetadata;
 }
 
-android::status_t FwdLockEngine::onInitialize(int uniqueId) {
+android::status_t FwdLockEngine::onInitialize(int /* uniqueId */) {
     LOG_VERBOSE("FwdLockEngine::onInitialize");
 
     if (FwdLockGlue_InitializeKeyEncryption()) {
@@ -146,14 +146,16 @@
 }
 
 android::status_t
-FwdLockEngine::onSetOnInfoListener(int uniqueId, const IDrmEngine::OnInfoListener* infoListener) {
+FwdLockEngine::onSetOnInfoListener(
+            int /* uniqueId */,
+            const IDrmEngine::OnInfoListener* /* infoListener */) {
     // Not used
     LOG_VERBOSE("FwdLockEngine::onSetOnInfoListener");
 
     return DRM_NO_ERROR;
 }
 
-android::status_t FwdLockEngine::onTerminate(int uniqueId) {
+android::status_t FwdLockEngine::onTerminate(int /* uniqueId */) {
     LOG_VERBOSE("FwdLockEngine::onTerminate");
 
     return DRM_NO_ERROR;
@@ -207,7 +209,7 @@
     return false;
 }
 
-DrmSupportInfo* FwdLockEngine::onGetSupportInfo(int uniqueId) {
+DrmSupportInfo* FwdLockEngine::onGetSupportInfo(int /* uniqueId */) {
     DrmSupportInfo* pSupportInfo = new DrmSupportInfo();
 
     LOG_VERBOSE("FwdLockEngine::onGetSupportInfo");
@@ -222,14 +224,14 @@
     return pSupportInfo;
 }
 
-bool FwdLockEngine::onCanHandle(int uniqueId, const String8& path) {
+bool FwdLockEngine::onCanHandle(int /* uniqueId */, const String8& path) {
     bool result = false;
 
     String8 extString = path.getPathExtension();
     return IsFileSuffixSupported(extString);
 }
 
-DrmInfoStatus* FwdLockEngine::onProcessDrmInfo(int uniqueId, const DrmInfo* drmInfo) {
+DrmInfoStatus* FwdLockEngine::onProcessDrmInfo(int /* uniqueId */, const DrmInfo* /* drmInfo */) {
     DrmInfoStatus *drmInfoStatus = NULL;
 
     // Nothing to process
@@ -242,16 +244,17 @@
 }
 
 status_t FwdLockEngine::onSaveRights(
-            int uniqueId,
-            const DrmRights& drmRights,
-            const String8& rightsPath,
-            const String8& contentPath) {
+            int /* uniqueId */,
+            const DrmRights& /* drmRights */,
+            const String8& /* rightsPath */,
+            const String8& /* contentPath */) {
     // No rights to save. Return
     LOG_VERBOSE("FwdLockEngine::onSaveRights");
     return DRM_ERROR_UNKNOWN;
 }
 
-DrmInfo* FwdLockEngine::onAcquireDrmInfo(int uniqueId, const DrmInfoRequest* drmInfoRequest) {
+DrmInfo* FwdLockEngine::onAcquireDrmInfo(
+            int /* uniqueId */, const DrmInfoRequest* /* drmInfoRequest */) {
     DrmInfo* drmInfo = NULL;
 
     // Nothing to be done for Forward Lock file
@@ -290,10 +293,10 @@
     return result;
 }
 
-status_t FwdLockEngine::onConsumeRights(int uniqueId,
-                                        DecryptHandle* decryptHandle,
-                                        int action,
-                                        bool reserve) {
+status_t FwdLockEngine::onConsumeRights(int /* uniqueId */,
+                                        DecryptHandle* /* decryptHandle */,
+                                        int /* action */,
+                                        bool /* reserve */) {
     // No rights consumption
     LOG_VERBOSE("FwdLockEngine::onConsumeRights");
     return DRM_NO_ERROR;
@@ -302,14 +305,16 @@
 bool FwdLockEngine::onValidateAction(int uniqueId,
                                      const String8& path,
                                      int action,
-                                     const ActionDescription& description) {
+                                     const ActionDescription& /* description */) {
     LOG_VERBOSE("FwdLockEngine::onValidateAction");
 
     // For the forwardlock engine checkRights and ValidateAction are the same.
     return (onCheckRightsStatus(uniqueId, path, action) == RightsStatus::RIGHTS_VALID);
 }
 
-String8 FwdLockEngine::onGetOriginalMimeType(int uniqueId, const String8& path, int fd) {
+String8 FwdLockEngine::onGetOriginalMimeType(int /* uniqueId */,
+                                             const String8& /* path */,
+                                             int fd) {
     LOG_VERBOSE("FwdLockEngine::onGetOriginalMimeType");
     String8 mimeString = String8("");
     int fileDesc = dup(fd);
@@ -354,32 +359,32 @@
     return DrmObjectType::UNKNOWN;
 }
 
-status_t FwdLockEngine::onRemoveRights(int uniqueId, const String8& path) {
+status_t FwdLockEngine::onRemoveRights(int /* uniqueId */, const String8& /* path */) {
     // No Rights to remove
     LOG_VERBOSE("FwdLockEngine::onRemoveRights");
     return DRM_NO_ERROR;
 }
 
-status_t FwdLockEngine::onRemoveAllRights(int uniqueId) {
+status_t FwdLockEngine::onRemoveAllRights(int /* uniqueId */) {
     // No rights to remove
     LOG_VERBOSE("FwdLockEngine::onRemoveAllRights");
     return DRM_NO_ERROR;
 }
 
 #ifdef USE_64BIT_DRM_API
-status_t FwdLockEngine::onSetPlaybackStatus(int uniqueId, DecryptHandle* decryptHandle,
-                                            int playbackStatus, int64_t position) {
+status_t FwdLockEngine::onSetPlaybackStatus(int /* uniqueId */, DecryptHandle* /* decryptHandle */,
+                                            int /* playbackStatus */, int64_t /* position */) {
 #else
-status_t FwdLockEngine::onSetPlaybackStatus(int uniqueId, DecryptHandle* decryptHandle,
-                                            int playbackStatus, int position) {
+status_t FwdLockEngine::onSetPlaybackStatus(int /* uniqueId */, DecryptHandle* /* decryptHandle */,
+                                            int /* playbackStatus */, int /* position */) {
 #endif
     // Not used
     LOG_VERBOSE("FwdLockEngine::onSetPlaybackStatus");
     return DRM_NO_ERROR;
 }
 
-status_t FwdLockEngine::onOpenConvertSession(int uniqueId,
-                                         int convertId) {
+status_t FwdLockEngine::onOpenConvertSession(
+            int /* uniqueId */, int convertId) {
     status_t result = DRM_ERROR_UNKNOWN;
     LOG_VERBOSE("FwdLockEngine::onOpenConvertSession");
     if (!convertSessionMap.isCreated(convertId)) {
@@ -396,7 +401,7 @@
     return result;
 }
 
-DrmConvertedStatus* FwdLockEngine::onConvertData(int uniqueId,
+DrmConvertedStatus* FwdLockEngine::onConvertData(int /* uniqueId */,
                                                  int convertId,
                                                  const DrmBuffer* inputData) {
     FwdLockConv_Status_t retStatus = FwdLockConv_Status_InvalidArgument;
@@ -432,7 +437,7 @@
     return new DrmConvertedStatus(getConvertedStatus(retStatus), convResult, offset);
 }
 
-DrmConvertedStatus* FwdLockEngine::onCloseConvertSession(int uniqueId,
+DrmConvertedStatus* FwdLockEngine::onCloseConvertSession(int /* uniqueId */,
                                                          int convertId) {
     FwdLockConv_Status_t retStatus = FwdLockConv_Status_InvalidArgument;
     DrmBuffer *convResult = new DrmBuffer(NULL, 0);
@@ -464,17 +469,17 @@
 }
 
 #ifdef USE_64BIT_DRM_API
-status_t FwdLockEngine::onOpenDecryptSession(int uniqueId,
+status_t FwdLockEngine::onOpenDecryptSession(int /* uniqueId */,
                                              DecryptHandle* decryptHandle,
                                              int fd,
                                              off64_t offset,
-                                             off64_t length) {
+                                             off64_t /* length */) {
 #else
-status_t FwdLockEngine::onOpenDecryptSession(int uniqueId,
+status_t FwdLockEngine::onOpenDecryptSession(int /* uniqueId */,
                                              DecryptHandle* decryptHandle,
                                              int fd,
                                              int offset,
-                                             int length) {
+                                             int /* length */) {
 #endif
     status_t result = DRM_ERROR_CANNOT_HANDLE;
     int fileDesc = -1;
@@ -552,7 +557,7 @@
     return result;
 }
 
-status_t FwdLockEngine::onCloseDecryptSession(int uniqueId,
+status_t FwdLockEngine::onCloseDecryptSession(int /* uniqueId */,
                                               DecryptHandle* decryptHandle) {
     status_t result = DRM_ERROR_UNKNOWN;
     LOG_VERBOSE("FwdLockEngine::onCloseDecryptSession");
@@ -584,37 +589,42 @@
     return result;
 }
 
-status_t FwdLockEngine::onInitializeDecryptUnit(int uniqueId,
-                                                DecryptHandle* decryptHandle,
-                                                int decryptUnitId,
-                                                const DrmBuffer* headerInfo) {
+status_t FwdLockEngine::onInitializeDecryptUnit(int /* uniqueId */,
+                                                DecryptHandle* /* decryptHandle */,
+                                                int /* decryptUnitId */,
+                                                const DrmBuffer* /* headerInfo */) {
     ALOGE("FwdLockEngine::onInitializeDecryptUnit is not supported for this DRM scheme");
     return DRM_ERROR_UNKNOWN;
 }
 
-status_t FwdLockEngine::onDecrypt(int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId,
-            const DrmBuffer* encBuffer, DrmBuffer** decBuffer, DrmBuffer* IV) {
+status_t FwdLockEngine::onDecrypt(
+            int /* uniqueId */,
+            DecryptHandle* /* decryptHandle */,
+            int /* decryptUnitId */,
+            const DrmBuffer* /* encBuffer */,
+            DrmBuffer** /* decBuffer */,
+            DrmBuffer* /* IV */) {
     ALOGE("FwdLockEngine::onDecrypt is not supported for this DRM scheme");
     return DRM_ERROR_UNKNOWN;
 }
 
-status_t FwdLockEngine::onDecrypt(int uniqueId,
-                                  DecryptHandle* decryptHandle,
-                                  int decryptUnitId,
-                                  const DrmBuffer* encBuffer,
-                                  DrmBuffer** decBuffer) {
+status_t FwdLockEngine::onDecrypt(int /* uniqueId */,
+                                  DecryptHandle* /* decryptHandle */,
+                                  int /* decryptUnitId */,
+                                  const DrmBuffer* /* encBuffer */,
+                                  DrmBuffer** /* decBuffer */) {
     ALOGE("FwdLockEngine::onDecrypt is not supported for this DRM scheme");
     return DRM_ERROR_UNKNOWN;
 }
 
-status_t FwdLockEngine::onFinalizeDecryptUnit(int uniqueId,
-                                              DecryptHandle* decryptHandle,
-                                              int decryptUnitId) {
+status_t FwdLockEngine::onFinalizeDecryptUnit(int /* uniqueId */,
+                                              DecryptHandle* /* decryptHandle */,
+                                              int /* decryptUnitId */) {
     ALOGE("FwdLockEngine::onFinalizeDecryptUnit is not supported for this DRM scheme");
     return DRM_ERROR_UNKNOWN;
 }
 
-ssize_t FwdLockEngine::onRead(int uniqueId,
+ssize_t FwdLockEngine::onRead(int /* uniqueId */,
                               DecryptHandle* decryptHandle,
                               void* buffer,
                               int numBytes) {
@@ -640,10 +650,10 @@
 }
 
 #ifdef USE_64BIT_DRM_API
-off64_t FwdLockEngine::onLseek(int uniqueId, DecryptHandle* decryptHandle,
+off64_t FwdLockEngine::onLseek(int /* uniqueId */, DecryptHandle* decryptHandle,
                                off64_t offset, int whence) {
 #else
-off_t FwdLockEngine::onLseek(int uniqueId, DecryptHandle* decryptHandle,
+off_t FwdLockEngine::onLseek(int /* uniqueId */, DecryptHandle* decryptHandle,
                              off_t offset, int whence) {
 #endif
     off_t offval = -1;
diff --git a/drm/libmediadrm/Android.mk b/drm/libmediadrm/Android.mk
new file mode 100644
index 0000000..6a2ed31
--- /dev/null
+++ b/drm/libmediadrm/Android.mk
@@ -0,0 +1,36 @@
+LOCAL_PATH:= $(call my-dir)
+
+#
+# libmediadrm
+#
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+	Crypto.cpp \
+	Drm.cpp \
+	DrmSessionManager.cpp \
+	SharedLibrary.cpp
+
+LOCAL_SHARED_LIBRARIES := \
+	libbinder \
+	libcrypto \
+	libcutils \
+	libdl \
+	liblog \
+	libmedia \
+	libstagefright \
+	libstagefright_foundation \
+	libutils
+
+LOCAL_C_INCLUDES := \
+    libcore/include
+
+LOCAL_CFLAGS += -Werror -Wno-error=deprecated-declarations -Wall
+LOCAL_CLANG := true
+
+LOCAL_MODULE:= libmediadrm
+
+include $(BUILD_SHARED_LIBRARY)
+
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/media/libmediaplayerservice/Crypto.cpp b/drm/libmediadrm/Crypto.cpp
similarity index 96%
rename from media/libmediaplayerservice/Crypto.cpp
rename to drm/libmediadrm/Crypto.cpp
index 147d35f..79633cb 100644
--- a/media/libmediaplayerservice/Crypto.cpp
+++ b/drm/libmediadrm/Crypto.cpp
@@ -20,9 +20,8 @@
 #include <dirent.h>
 #include <dlfcn.h>
 
-#include "Crypto.h"
-
 #include <binder/IMemory.h>
+#include <media/Crypto.h>
 #include <media/hardware/CryptoAPI.h>
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/foundation/AString.h>
@@ -235,10 +234,11 @@
 }
 
 ssize_t Crypto::decrypt(
-        bool secure,
+        DestinationType dstType,
         const uint8_t key[16],
         const uint8_t iv[16],
         CryptoPlugin::Mode mode,
+        const CryptoPlugin::Pattern &pattern,
         const sp<IMemory> &sharedBuffer, size_t offset,
         const CryptoPlugin::SubSample *subSamples, size_t numSubSamples,
         void *dstPtr,
@@ -256,7 +256,8 @@
     const void *srcPtr = static_cast<uint8_t *>(sharedBuffer->pointer()) + offset;
 
     return mPlugin->decrypt(
-            secure, key, iv, mode, srcPtr, subSamples, numSubSamples, dstPtr,
+            dstType != kDestinationTypeVmPointer,
+            key, iv, mode, pattern, srcPtr, subSamples, numSubSamples, dstPtr,
             errorDetailMsg);
 }
 
diff --git a/media/libmediaplayerservice/Drm.cpp b/drm/libmediadrm/Drm.cpp
similarity index 97%
rename from media/libmediaplayerservice/Drm.cpp
rename to drm/libmediadrm/Drm.cpp
index a7f6f8b..7c1f5c8 100644
--- a/media/libmediaplayerservice/Drm.cpp
+++ b/drm/libmediadrm/Drm.cpp
@@ -21,10 +21,9 @@
 #include <dirent.h>
 #include <dlfcn.h>
 
-#include "Drm.h"
-
-#include "DrmSessionClientInterface.h"
-#include "DrmSessionManager.h"
+#include <media/DrmSessionClientInterface.h>
+#include <media/DrmSessionManager.h>
+#include <media/Drm.h>
 #include <media/drm/DrmAPI.h>
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/foundation/AString.h>
@@ -40,9 +39,6 @@
 }
 
 static bool checkPermission(const char* permissionString) {
-#ifndef HAVE_ANDROID_OS
-    return true;
-#endif
     if (getpid() == IPCThreadState::self()->getCallingPid()) return true;
     bool ok = checkCallingPermission(String16(permissionString));
     if (!ok) ALOGE("Request requires %s", permissionString);
@@ -519,24 +515,6 @@
     return mPlugin->provideProvisionResponse(response, certificate, wrappedKey);
 }
 
-status_t Drm::unprovisionDevice() {
-    Mutex::Autolock autoLock(mLock);
-
-    if (mInitCheck != OK) {
-        return mInitCheck;
-    }
-
-    if (mPlugin == NULL) {
-        return -EINVAL;
-    }
-
-    if (!checkPermission("android.permission.REMOVE_DRM_CERTIFICATES")) {
-        return -EPERM;
-    }
-
-    return mPlugin->unprovisionDevice();
-}
-
 status_t Drm::getSecureStops(List<Vector<uint8_t> > &secureStops) {
     Mutex::Autolock autoLock(mLock);
 
diff --git a/media/libmediaplayerservice/DrmSessionManager.cpp b/drm/libmediadrm/DrmSessionManager.cpp
similarity index 98%
rename from media/libmediaplayerservice/DrmSessionManager.cpp
rename to drm/libmediadrm/DrmSessionManager.cpp
index 641f881..a87fb9d 100644
--- a/media/libmediaplayerservice/DrmSessionManager.cpp
+++ b/drm/libmediadrm/DrmSessionManager.cpp
@@ -18,12 +18,11 @@
 #define LOG_TAG "DrmSessionManager"
 #include <utils/Log.h>
 
-#include "DrmSessionManager.h"
-
-#include "DrmSessionClientInterface.h"
 #include <binder/IPCThreadState.h>
 #include <binder/IProcessInfoService.h>
 #include <binder/IServiceManager.h>
+#include <media/DrmSessionManager.h>
+#include <media/DrmSessionClientInterface.h>
 #include <media/stagefright/ProcessInfo.h>
 #include <unistd.h>
 #include <utils/String8.h>
diff --git a/media/libmediaplayerservice/SharedLibrary.cpp b/drm/libmediadrm/SharedLibrary.cpp
similarity index 97%
rename from media/libmediaplayerservice/SharedLibrary.cpp
rename to drm/libmediadrm/SharedLibrary.cpp
index 34db761..74b3a71 100644
--- a/media/libmediaplayerservice/SharedLibrary.cpp
+++ b/drm/libmediadrm/SharedLibrary.cpp
@@ -16,12 +16,11 @@
 
 //#define LOG_NDEBUG 0
 #define LOG_TAG "Drm"
-#include <utils/Log.h>
-#include <media/stagefright/foundation/ADebug.h>
 
 #include <dlfcn.h>
-
-#include "SharedLibrary.h"
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/SharedLibrary.h>
+#include <utils/Log.h>
 
 namespace android {
 
diff --git a/drm/mediadrm/plugins/clearkey/CryptoPlugin.cpp b/drm/mediadrm/plugins/clearkey/CryptoPlugin.cpp
index 53cbf80..ee97976 100644
--- a/drm/mediadrm/plugins/clearkey/CryptoPlugin.cpp
+++ b/drm/mediadrm/plugins/clearkey/CryptoPlugin.cpp
@@ -33,7 +33,7 @@
 // decrypted data.  In theory, the output size can be larger than the input
 // size, but in practice this will never happen for AES-CTR.
 ssize_t CryptoPlugin::decrypt(bool secure, const KeyId keyId, const Iv iv,
-                              Mode mode, const void* srcPtr,
+                              Mode mode, const Pattern &/* pattern */, const void* srcPtr,
                               const SubSample* subSamples, size_t numSubSamples,
                               void* dstPtr, AString* errorDetailMsg) {
     if (secure) {
diff --git a/drm/mediadrm/plugins/clearkey/CryptoPlugin.h b/drm/mediadrm/plugins/clearkey/CryptoPlugin.h
index fd38f28..de84c36 100644
--- a/drm/mediadrm/plugins/clearkey/CryptoPlugin.h
+++ b/drm/mediadrm/plugins/clearkey/CryptoPlugin.h
@@ -44,7 +44,7 @@
 
     virtual ssize_t decrypt(
             bool secure, const KeyId keyId, const Iv iv,
-            Mode mode, const void* srcPtr,
+            Mode mode, const Pattern &pattern, const void* srcPtr,
             const SubSample* subSamples, size_t numSubSamples,
             void* dstPtr, android::AString* errorDetailMsg);
 
diff --git a/drm/mediadrm/plugins/clearkey/DrmPlugin.h b/drm/mediadrm/plugins/clearkey/DrmPlugin.h
index ba4aefe..9095045 100644
--- a/drm/mediadrm/plugins/clearkey/DrmPlugin.h
+++ b/drm/mediadrm/plugins/clearkey/DrmPlugin.h
@@ -105,10 +105,6 @@
         return android::ERROR_DRM_CANNOT_HANDLE;
     }
 
-    virtual status_t unprovisionDevice() {
-        return android::ERROR_DRM_CANNOT_HANDLE;
-    }
-
     virtual status_t getSecureStops(List<Vector<uint8_t> >& secureStops) {
         UNUSED(secureStops);
         return android::ERROR_DRM_CANNOT_HANDLE;
diff --git a/drm/mediadrm/plugins/mock/MockDrmCryptoPlugin.cpp b/drm/mediadrm/plugins/mock/MockDrmCryptoPlugin.cpp
index 851ad2c..1e80f8e 100644
--- a/drm/mediadrm/plugins/mock/MockDrmCryptoPlugin.cpp
+++ b/drm/mediadrm/plugins/mock/MockDrmCryptoPlugin.cpp
@@ -312,12 +312,6 @@
         return OK;
     }
 
-    status_t MockDrmPlugin::unprovisionDevice()
-    {
-        ALOGD("MockDrmPlugin::unprovisionDevice()");
-        return OK;
-    }
-
     status_t MockDrmPlugin::getSecureStop(Vector<uint8_t> const & /* ssid */,
                                           Vector<uint8_t> & secureStop)
     {
@@ -798,15 +792,17 @@
 
     ssize_t
     MockCryptoPlugin::decrypt(bool secure, const uint8_t key[16], const uint8_t iv[16],
-                              Mode mode, const void *srcPtr, const SubSample *subSamples,
-                              size_t numSubSamples, void *dstPtr, AString * /* errorDetailMsg */)
+            Mode mode, const Pattern &pattern, const void *srcPtr,
+            const SubSample *subSamples, size_t numSubSamples,
+            void *dstPtr, AString * /* errorDetailMsg */)
     {
-        ALOGD("MockCryptoPlugin::decrypt(secure=%d, key=%s, iv=%s, mode=%d, src=%p, "
+        ALOGD("MockCryptoPlugin::decrypt(secure=%d, key=%s, iv=%s, mode=%d, "
+              "pattern:{encryptBlocks=%d, skipBlocks=%d} src=%p, "
               "subSamples=%s, dst=%p)",
               (int)secure,
               arrayToString(key, sizeof(key)).string(),
               arrayToString(iv, sizeof(iv)).string(),
-              (int)mode, srcPtr,
+              (int)mode, pattern.mEncryptBlocks, pattern.mSkipBlocks, srcPtr,
               subSamplesToString(subSamples, numSubSamples).string(),
               dstPtr);
         return OK;
diff --git a/drm/mediadrm/plugins/mock/MockDrmCryptoPlugin.h b/drm/mediadrm/plugins/mock/MockDrmCryptoPlugin.h
index d0f2ddb..40d4e84 100644
--- a/drm/mediadrm/plugins/mock/MockDrmCryptoPlugin.h
+++ b/drm/mediadrm/plugins/mock/MockDrmCryptoPlugin.h
@@ -86,8 +86,6 @@
                                           Vector<uint8_t> &certificate,
                                           Vector<uint8_t> &wrappedKey);
 
-        status_t unprovisionDevice();
-
         status_t getSecureStops(List<Vector<uint8_t> > &secureStops);
         status_t getSecureStop(Vector<uint8_t> const &ssid, Vector<uint8_t> &secureStop);
         status_t releaseSecureStops(Vector<uint8_t> const &ssRelease);
@@ -161,7 +159,7 @@
 
         ssize_t decrypt(bool secure,
             const uint8_t key[16], const uint8_t iv[16],
-            Mode mode, const void *srcPtr,
+            Mode mode, const Pattern &pattern, const void *srcPtr,
             const SubSample *subSamples, size_t numSubSamples,
             void *dstPtr, AString *errorDetailMsg);
     private:
diff --git a/include/camera/Camera.h b/include/camera/Camera.h
index 2b60842..be793a2 100644
--- a/include/camera/Camera.h
+++ b/include/camera/Camera.h
@@ -18,13 +18,15 @@
 #define ANDROID_HARDWARE_CAMERA_H
 
 #include <utils/Timers.h>
+
+#include <android/hardware/ICameraService.h>
+
 #include <gui/IGraphicBufferProducer.h>
 #include <system/camera.h>
-#include <camera/ICameraClient.h>
 #include <camera/ICameraRecordingProxy.h>
 #include <camera/ICameraRecordingProxyListener.h>
-#include <camera/ICameraService.h>
-#include <camera/ICamera.h>
+#include <camera/android/hardware/ICamera.h>
+#include <camera/android/hardware/ICameraClient.h>
 #include <camera/CameraBase.h>
 
 namespace android {
@@ -41,6 +43,7 @@
     virtual void postData(int32_t msgType, const sp<IMemory>& dataPtr,
                           camera_frame_metadata_t *metadata) = 0;
     virtual void postDataTimestamp(nsecs_t timestamp, int32_t msgType, const sp<IMemory>& dataPtr) = 0;
+    virtual void postRecordingFrameHandleTimestamp(nsecs_t timestamp, native_handle_t* handle) = 0;
 };
 
 class Camera;
@@ -48,31 +51,35 @@
 template <>
 struct CameraTraits<Camera>
 {
-    typedef CameraListener        TCamListener;
-    typedef ICamera               TCamUser;
-    typedef ICameraClient         TCamCallbacks;
-    typedef status_t (ICameraService::*TCamConnectService)(const sp<ICameraClient>&,
-                                                           int, const String16&, int,
-                                                           /*out*/
-                                                           sp<ICamera>&);
+    typedef CameraListener                     TCamListener;
+    typedef ::android::hardware::ICamera       TCamUser;
+    typedef ::android::hardware::ICameraClient TCamCallbacks;
+    typedef ::android::binder::Status(::android::hardware::ICameraService::*TCamConnectService)
+        (const sp<::android::hardware::ICameraClient>&,
+        int, const String16&, int, int,
+        /*out*/
+        sp<::android::hardware::ICamera>*);
     static TCamConnectService     fnConnectService;
 };
 
 
 class Camera :
     public CameraBase<Camera>,
-    public BnCameraClient
+    public ::android::hardware::BnCameraClient
 {
 public:
     enum {
-        USE_CALLING_UID = ICameraService::USE_CALLING_UID
+        USE_CALLING_UID = ::android::hardware::ICameraService::USE_CALLING_UID
+    };
+    enum {
+        USE_CALLING_PID = ::android::hardware::ICameraService::USE_CALLING_PID
     };
 
             // construct a camera client from an existing remote
-    static  sp<Camera>  create(const sp<ICamera>& camera);
+    static  sp<Camera>  create(const sp<::android::hardware::ICamera>& camera);
     static  sp<Camera>  connect(int cameraId,
                                 const String16& clientPackageName,
-                                int clientUid);
+                                int clientUid, int clientPid);
 
     static  status_t  connectLegacy(int cameraId, int halVersion,
                                      const String16& clientPackageName,
@@ -108,6 +115,9 @@
             // release a recording frame
             void        releaseRecordingFrame(const sp<IMemory>& mem);
 
+            // release a recording frame handle
+            void        releaseRecordingFrameHandle(native_handle_t *handle);
+
             // autoFocus - status returned from callback
             status_t    autoFocus();
 
@@ -126,8 +136,15 @@
             // send command to camera driver
             status_t    sendCommand(int32_t cmd, int32_t arg1, int32_t arg2);
 
-            // tell camera hal to store meta data or real YUV in video buffers.
-            status_t    storeMetaDataInBuffers(bool enabled);
+            // Tell camera how to pass video buffers. videoBufferMode is one of VIDEO_BUFFER_MODE_*.
+            // Returns OK if the specified video buffer mode is supported. If videoBufferMode is
+            // VIDEO_BUFFER_MODE_BUFFER_QUEUE, setVideoTarget() must be called before starting
+            // video recording.
+            status_t    setVideoBufferMode(int32_t videoBufferMode);
+
+            // Set the video buffer producer for camera to use in VIDEO_BUFFER_MODE_BUFFER_QUEUE
+            // mode.
+            status_t    setVideoTarget(const sp<IGraphicBufferProducer>& bufferProducer);
 
             void        setListener(const sp<CameraListener>& listener);
             void        setRecordingProxyListener(const sp<ICameraRecordingProxyListener>& listener);
@@ -148,6 +165,7 @@
     virtual void        dataCallback(int32_t msgType, const sp<IMemory>& dataPtr,
                                      camera_frame_metadata_t *metadata);
     virtual void        dataCallbackTimestamp(nsecs_t timestamp, int32_t msgType, const sp<IMemory>& dataPtr);
+    virtual void        recordingFrameHandleCallbackTimestamp(nsecs_t timestamp, native_handle_t* handle);
 
     class RecordingProxy : public BnCameraRecordingProxy
     {
@@ -158,6 +176,7 @@
         virtual status_t startRecording(const sp<ICameraRecordingProxyListener>& listener);
         virtual void stopRecording();
         virtual void releaseRecordingFrame(const sp<IMemory>& mem);
+        virtual void releaseRecordingFrameHandle(native_handle_t* handle);
 
     private:
         sp<Camera>         mCamera;
diff --git a/include/camera/CameraBase.h b/include/camera/CameraBase.h
index 1b93157..0692a27 100644
--- a/include/camera/CameraBase.h
+++ b/include/camera/CameraBase.h
@@ -18,13 +18,18 @@
 #define ANDROID_HARDWARE_CAMERA_BASE_H
 
 #include <utils/Mutex.h>
-#include <camera/ICameraService.h>
 
 struct camera_frame_metadata;
 
 namespace android {
 
-struct CameraInfo {
+namespace hardware {
+
+
+class ICameraService;
+class ICameraServiceListener;
+
+struct CameraInfo : public android::Parcelable {
     /**
      * The direction that the camera faces to. It should be CAMERA_FACING_BACK
      * or CAMERA_FACING_FRONT.
@@ -44,8 +49,17 @@
      * right of the screen, the value should be 270.
      */
     int orientation;
+
+    virtual status_t writeToParcel(Parcel* parcel) const;
+    virtual status_t readFromParcel(const Parcel* parcel);
+
 };
 
+} // namespace hardware
+
+using hardware::CameraInfo;
+
+
 template <typename TCam>
 struct CameraTraits {
 };
@@ -61,7 +75,7 @@
 
     static sp<TCam>      connect(int cameraId,
                                  const String16& clientPackageName,
-                                 int clientUid);
+                                 int clientUid, int clientPid);
     virtual void         disconnect();
 
     void                 setListener(const sp<TCamListener>& listener);
@@ -70,13 +84,13 @@
 
     static status_t      getCameraInfo(int cameraId,
                                        /*out*/
-                                       struct CameraInfo* cameraInfo);
+                                       struct hardware::CameraInfo* cameraInfo);
 
     static status_t      addServiceListener(
-                                    const sp<ICameraServiceListener>& listener);
+        const sp<::android::hardware::ICameraServiceListener>& listener);
 
     static status_t      removeServiceListener(
-                                    const sp<ICameraServiceListener>& listener);
+        const sp<::android::hardware::ICameraServiceListener>& listener);
 
     sp<TCamUser>         remote();
 
@@ -101,7 +115,7 @@
     virtual void                     binderDied(const wp<IBinder>& who);
 
     // helper function to obtain camera service handle
-    static const sp<ICameraService>& getCameraService();
+    static const sp<::android::hardware::ICameraService>& getCameraService();
 
     sp<TCamUser>                     mCamera;
     status_t                         mStatus;
diff --git a/include/camera/CameraMetadata.h b/include/camera/CameraMetadata.h
index 953d711..28f47a1 100644
--- a/include/camera/CameraMetadata.h
+++ b/include/camera/CameraMetadata.h
@@ -20,14 +20,14 @@
 #include "system/camera_metadata.h"
 #include <utils/String8.h>
 #include <utils/Vector.h>
+#include <binder/Parcelable.h>
 
 namespace android {
-class Parcel;
 
 /**
  * A convenience wrapper around the C-based camera_metadata_t library.
  */
-class CameraMetadata {
+class CameraMetadata: public Parcelable {
   public:
     /** Creates an empty object; best used when expecting to acquire contents
      * from elsewhere */
@@ -64,7 +64,7 @@
      * from getAndLock must be provided to guarantee that the right object is
      * being unlocked.
      */
-    status_t unlock(const camera_metadata_t *buffer);
+    status_t unlock(const camera_metadata_t *buffer) const;
 
     /**
      * Release a raw metadata buffer to the caller. After this call,
@@ -186,8 +186,8 @@
      */
 
     // Metadata object is unchanged when reading from parcel fails.
-    status_t readFromParcel(Parcel *parcel);
-    status_t writeToParcel(Parcel *parcel) const;
+    virtual status_t readFromParcel(const Parcel *parcel) override;
+    virtual status_t writeToParcel(Parcel *parcel) const override;
 
     /**
       * Caller becomes the owner of the new metadata
@@ -227,6 +227,15 @@
 
 };
 
-}; // namespace android
+namespace hardware {
+namespace camera2 {
+namespace impl {
+using ::android::CameraMetadata;
+typedef CameraMetadata CameraMetadataNative;
+}
+}
+}
+
+} // namespace android
 
 #endif
diff --git a/include/camera/CameraUtils.h b/include/camera/CameraUtils.h
index c06f05d..f596f80 100644
--- a/include/camera/CameraUtils.h
+++ b/include/camera/CameraUtils.h
@@ -17,8 +17,10 @@
 #ifndef ANDROID_CAMERA_CLIENT_CAMERAUTILS_H
 #define ANDROID_CAMERA_CLIENT_CAMERAUTILS_H
 
+#include <binder/IMemory.h>
 #include <camera/CameraMetadata.h>
 #include <utils/Errors.h>
+#include <utils/RefBase.h>
 
 #include <stdint.h>
 
@@ -39,6 +41,12 @@
          */
         static status_t getRotationTransform(const CameraMetadata& staticInfo,
                 /*out*/int32_t* transform);
+
+        /**
+         * Check if the image data is VideoNativeHandleMetadata, that contains a native handle.
+         */
+        static bool isNativeHandleMetadata(const sp<IMemory>& imageData);
+
     private:
         CameraUtils();
 };
diff --git a/include/camera/CaptureResult.h b/include/camera/CaptureResult.h
index 0be7d6f..45e4518 100644
--- a/include/camera/CaptureResult.h
+++ b/include/camera/CaptureResult.h
@@ -18,15 +18,21 @@
 #define ANDROID_HARDWARE_CAPTURERESULT_H
 
 #include <utils/RefBase.h>
+#include <binder/Parcelable.h>
 #include <camera/CameraMetadata.h>
 
+
 namespace android {
 
+namespace hardware {
+namespace camera2 {
+namespace impl {
+
 /**
  * CaptureResultExtras is a structure to encapsulate various indices for a capture result.
  * These indices are framework-internal and not sent to the HAL.
  */
-struct CaptureResultExtras {
+struct CaptureResultExtras : public android::Parcelable {
     /**
      * An integer to index the request sequence that this result belongs to.
      */
@@ -58,6 +64,12 @@
     int32_t partialResultCount;
 
     /**
+     * For buffer drop errors, the stream ID for the stream that lost a buffer.
+     * Otherwise -1.
+     */
+    int32_t errorStreamId;
+
+    /**
      * Constructor initializes object as invalid by setting requestId to be -1.
      */
     CaptureResultExtras()
@@ -66,7 +78,8 @@
           afTriggerId(0),
           precaptureTriggerId(0),
           frameNumber(0),
-          partialResultCount(0) {
+          partialResultCount(0),
+          errorStreamId(-1) {
     }
 
     /**
@@ -75,9 +88,14 @@
      */
     bool isValid();
 
-    status_t                readFromParcel(Parcel* parcel);
-    status_t                writeToParcel(Parcel* parcel) const;
+    virtual status_t                readFromParcel(const Parcel* parcel) override;
+    virtual status_t                writeToParcel(Parcel* parcel) const override;
 };
+} // namespace impl
+} // namespace camera2
+} // namespace hardware
+
+using hardware::camera2::impl::CaptureResultExtras;
 
 struct CaptureResult : public virtual LightRefBase<CaptureResult> {
     CameraMetadata          mMetadata;
diff --git a/include/camera/ICameraRecordingProxy.h b/include/camera/ICameraRecordingProxy.h
index 4edf9cd..cb6824a 100644
--- a/include/camera/ICameraRecordingProxy.h
+++ b/include/camera/ICameraRecordingProxy.h
@@ -18,6 +18,7 @@
 #define ANDROID_HARDWARE_ICAMERA_RECORDING_PROXY_H
 
 #include <binder/IInterface.h>
+#include <cutils/native_handle.h>
 #include <utils/RefBase.h>
 
 namespace android {
@@ -83,12 +84,7 @@
     virtual status_t        startRecording(const sp<ICameraRecordingProxyListener>& listener) = 0;
     virtual void            stopRecording() = 0;
     virtual void            releaseRecordingFrame(const sp<IMemory>& mem) = 0;
-
-    // b/28466701
-    static  size_t          getCommonBaseAddress();
-  private:
-
-    static  uint8_t         baseObject;
+    virtual void            releaseRecordingFrameHandle(native_handle_t *handle) = 0;
 };
 
 // ----------------------------------------------------------------------------
diff --git a/include/camera/ICameraRecordingProxyListener.h b/include/camera/ICameraRecordingProxyListener.h
index b6c0624..1fee5b9 100644
--- a/include/camera/ICameraRecordingProxyListener.h
+++ b/include/camera/ICameraRecordingProxyListener.h
@@ -18,6 +18,7 @@
 #define ANDROID_HARDWARE_ICAMERA_RECORDING_PROXY_LISTENER_H
 
 #include <binder/IInterface.h>
+#include <cutils/native_handle.h>
 #include <stdint.h>
 #include <utils/RefBase.h>
 #include <utils/Timers.h>
@@ -34,6 +35,9 @@
 
     virtual void dataCallbackTimestamp(nsecs_t timestamp, int32_t msgType,
                                        const sp<IMemory>& data) = 0;
+
+    virtual void recordingFrameHandleCallbackTimestamp(nsecs_t timestamp,
+                                                       native_handle_t* handle) = 0;
 };
 
 // ----------------------------------------------------------------------------
diff --git a/include/camera/ICameraService.h b/include/camera/ICameraService.h
deleted file mode 100644
index 1b68b5f..0000000
--- a/include/camera/ICameraService.h
+++ /dev/null
@@ -1,193 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_HARDWARE_ICAMERASERVICE_H
-#define ANDROID_HARDWARE_ICAMERASERVICE_H
-
-#include <utils/RefBase.h>
-#include <binder/IInterface.h>
-#include <binder/Parcel.h>
-
-namespace android {
-
-class ICamera;
-class ICameraClient;
-class ICameraServiceListener;
-class ICameraDeviceUser;
-class ICameraDeviceCallbacks;
-class CameraMetadata;
-class VendorTagDescriptor;
-class String16;
-
-class ICameraService : public IInterface
-{
-public:
-    /**
-     * Keep up-to-date with ICameraService.aidl in frameworks/base
-     */
-    enum {
-        GET_NUMBER_OF_CAMERAS = IBinder::FIRST_CALL_TRANSACTION,
-        GET_CAMERA_INFO,
-        CONNECT,
-        CONNECT_DEVICE,
-        ADD_LISTENER,
-        REMOVE_LISTENER,
-        GET_CAMERA_CHARACTERISTICS,
-        GET_CAMERA_VENDOR_TAG_DESCRIPTOR,
-        GET_LEGACY_PARAMETERS,
-        SUPPORTS_CAMERA_API,
-        CONNECT_LEGACY,
-        SET_TORCH_MODE,
-        NOTIFY_SYSTEM_EVENT,
-    };
-
-    enum {
-        USE_CALLING_UID = -1
-    };
-
-    enum {
-        API_VERSION_1 = 1,
-        API_VERSION_2 = 2,
-    };
-
-    enum {
-        CAMERA_TYPE_BACKWARD_COMPATIBLE = 0,
-        CAMERA_TYPE_ALL = 1,
-    };
-
-    enum {
-        CAMERA_HAL_API_VERSION_UNSPECIFIED = -1
-    };
-
-    /**
-     * Keep up-to-date with declarations in
-     * frameworks/base/services/core/java/com/android/server/camera/CameraService.java
-     *
-     * These event codes are intended to be used with the notifySystemEvent call.
-     */
-    enum {
-        NO_EVENT = 0,
-        USER_SWITCHED,
-    };
-
-public:
-    DECLARE_META_INTERFACE(CameraService);
-
-    // Get the number of cameras that support basic color camera operation
-    // (type CAMERA_TYPE_BACKWARD_COMPATIBLE)
-    virtual int32_t  getNumberOfCameras() = 0;
-    // Get the number of cameras of the specified type, one of CAMERA_TYPE_*
-    // enums
-    virtual int32_t  getNumberOfCameras(int cameraType) = 0;
-    virtual status_t getCameraInfo(int cameraId,
-            /*out*/
-            struct CameraInfo* cameraInfo) = 0;
-
-    virtual status_t getCameraCharacteristics(int cameraId,
-            /*out*/
-            CameraMetadata* cameraInfo) = 0;
-
-    virtual status_t getCameraVendorTagDescriptor(
-            /*out*/
-            sp<VendorTagDescriptor>& desc) = 0;
-
-    // Returns 'OK' if operation succeeded
-    // - Errors: ALREADY_EXISTS if the listener was already added
-    virtual status_t addListener(const sp<ICameraServiceListener>& listener)
-                                                                            = 0;
-    // Returns 'OK' if operation succeeded
-    // - Errors: BAD_VALUE if specified listener was not in the listener list
-    virtual status_t removeListener(const sp<ICameraServiceListener>& listener)
-                                                                            = 0;
-    /**
-     * clientPackageName and clientUid are used for permissions checking.  if
-     * clientUid == USE_CALLING_UID, then the calling UID is used instead. Only
-     * trusted callers can set a clientUid other than USE_CALLING_UID.
-     */
-    virtual status_t connect(const sp<ICameraClient>& cameraClient,
-            int cameraId,
-            const String16& clientPackageName,
-            int clientUid,
-            /*out*/
-            sp<ICamera>& device) = 0;
-
-    virtual status_t connectDevice(
-            const sp<ICameraDeviceCallbacks>& cameraCb,
-            int cameraId,
-            const String16& clientPackageName,
-            int clientUid,
-            /*out*/
-            sp<ICameraDeviceUser>& device) = 0;
-
-    virtual status_t getLegacyParameters(
-            int cameraId,
-            /*out*/
-            String16* parameters) = 0;
-
-    /**
-     * Returns OK if device supports camera2 api,
-     * returns -EOPNOTSUPP if it doesn't.
-     */
-    virtual status_t supportsCameraApi(
-            int cameraId, int apiVersion) = 0;
-
-    /**
-     * Connect the device as a legacy device for a given HAL version.
-     * For halVersion, use CAMERA_API_DEVICE_VERSION_* for a particular
-     * version, or CAMERA_HAL_API_VERSION_UNSPECIFIED for a service-selected version.
-     */
-    virtual status_t connectLegacy(const sp<ICameraClient>& cameraClient,
-            int cameraId, int halVersion,
-            const String16& clientPackageName,
-            int clientUid,
-            /*out*/
-            sp<ICamera>& device) = 0;
-
-    /**
-     * Turn on or off a camera's torch mode. Torch mode will be turned off by
-     * camera service if the lastest client binder that turns it on dies.
-     *
-     * return values:
-     * 0:       on a successful operation.
-     * -ENOSYS: the camera device doesn't support this operation. It it returned
-     *          if and only if android.flash.into.available is false.
-     * -EBUSY:  the camera device is opened.
-     * -EINVAL: camera_id is invalid or clientBinder is NULL when enabling a
-     *          torch mode.
-     */
-    virtual status_t setTorchMode(const String16& cameraId, bool enabled,
-            const sp<IBinder>& clientBinder) = 0;
-
-    /**
-     * Notify the camera service of a system event.  Should only be called from system_server.
-     */
-    virtual void notifySystemEvent(int32_t eventId, const int32_t* args, size_t length) = 0;
-};
-
-// ----------------------------------------------------------------------------
-
-class BnCameraService: public BnInterface<ICameraService>
-{
-public:
-    virtual status_t    onTransact( uint32_t code,
-                                    const Parcel& data,
-                                    Parcel* reply,
-                                    uint32_t flags = 0);
-};
-
-}; // namespace android
-
-#endif
diff --git a/include/camera/ICameraServiceListener.h b/include/camera/ICameraServiceListener.h
deleted file mode 100644
index 709ff31..0000000
--- a/include/camera/ICameraServiceListener.h
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_HARDWARE_ICAMERASERVICE_LISTENER_H
-#define ANDROID_HARDWARE_ICAMERASERVICE_LISTENER_H
-
-#include <utils/RefBase.h>
-#include <binder/IInterface.h>
-#include <binder/Parcel.h>
-#include <hardware/camera_common.h>
-
-namespace android {
-
-class ICameraServiceListener : public IInterface
-{
-    /**
-     * Keep up-to-date with ICameraServiceListener.aidl in frameworks/base
-     */
-public:
-
-    /**
-     * Initial status will be transmitted with onStatusChange immediately
-     * after this listener is added to the service listener list.
-     *
-     * Allowed transitions:
-     *
-     *     (Any)               -> NOT_PRESENT
-     *     NOT_PRESENT         -> PRESENT
-     *     NOT_PRESENT         -> ENUMERATING
-     *     ENUMERATING         -> PRESENT
-     *     PRESENT             -> NOT_AVAILABLE
-     *     NOT_AVAILABLE       -> PRESENT
-     *
-     * A state will never immediately transition back to itself.
-     */
-    enum Status {
-        // Device physically unplugged
-        STATUS_NOT_PRESENT      = CAMERA_DEVICE_STATUS_NOT_PRESENT,
-        // Device physically has been plugged in
-        //  and the camera can be used exlusively
-        STATUS_PRESENT          = CAMERA_DEVICE_STATUS_PRESENT,
-        // Device physically has been plugged in
-        //   but it will not be connect-able until enumeration is complete
-        STATUS_ENUMERATING      = CAMERA_DEVICE_STATUS_ENUMERATING,
-
-        // Camera can be used exclusively
-        STATUS_AVAILABLE        = STATUS_PRESENT, // deprecated, will be removed
-
-        // Camera is in use by another app and cannot be used exclusively
-        STATUS_NOT_AVAILABLE    = 0x80000000,
-
-        // Use to initialize variables only
-        STATUS_UNKNOWN          = 0xFFFFFFFF,
-    };
-
-    /**
-     * The torch mode status of a camera.
-     *
-     * Initial status will be transmitted with onTorchStatusChanged immediately
-     * after this listener is added to the service listener list.
-     *
-     * The enums should be set to values matching
-     * include/hardware/camera_common.h
-     */
-    enum TorchStatus {
-        // The camera's torch mode has become not available to use via
-        // setTorchMode().
-        TORCH_STATUS_NOT_AVAILABLE  = TORCH_MODE_STATUS_NOT_AVAILABLE,
-        // The camera's torch mode is off and available to be turned on via
-        // setTorchMode().
-        TORCH_STATUS_AVAILABLE_OFF  = TORCH_MODE_STATUS_AVAILABLE_OFF,
-        // The camera's torch mode is on and available to be turned off via
-        // setTorchMode().
-        TORCH_STATUS_AVAILABLE_ON   = TORCH_MODE_STATUS_AVAILABLE_ON,
-
-        // Use to initialize variables only
-        TORCH_STATUS_UNKNOWN        = 0xFFFFFFFF,
-    };
-
-    DECLARE_META_INTERFACE(CameraServiceListener);
-
-    virtual void onStatusChanged(Status status, int32_t cameraId) = 0;
-
-    virtual void onTorchStatusChanged(TorchStatus status, const String16& cameraId) = 0;
-};
-
-// ----------------------------------------------------------------------------
-
-class BnCameraServiceListener : public BnInterface<ICameraServiceListener>
-{
-public:
-    virtual status_t    onTransact( uint32_t code,
-                                    const Parcel& data,
-                                    Parcel* reply,
-                                    uint32_t flags = 0);
-};
-
-}; // namespace android
-
-#endif
diff --git a/include/camera/VendorTagDescriptor.h b/include/camera/VendorTagDescriptor.h
index 1758acf..4c1cab6 100644
--- a/include/camera/VendorTagDescriptor.h
+++ b/include/camera/VendorTagDescriptor.h
@@ -16,6 +16,7 @@
 
 #ifndef VENDOR_TAG_DESCRIPTOR_H
 
+#include <binder/Parcelable.h>
 #include <utils/Vector.h>
 #include <utils/KeyedVector.h>
 #include <utils/String8.h>
@@ -26,18 +27,27 @@
 
 namespace android {
 
-class Parcel;
+class VendorTagDescriptor;
+
+namespace hardware {
+namespace camera2 {
+namespace params {
 
 /**
  * VendorTagDescriptor objects are parcelable containers for the vendor tag
  * definitions provided, and are typically used to pass the vendor tag
  * information enumerated by the HAL to clients of the camera service.
  */
-class VendorTagDescriptor
-        : public LightRefBase<VendorTagDescriptor> {
+class VendorTagDescriptor : public Parcelable {
     public:
         virtual ~VendorTagDescriptor();
 
+        VendorTagDescriptor();
+        VendorTagDescriptor(const VendorTagDescriptor& src);
+        VendorTagDescriptor& operator=(const VendorTagDescriptor& rhs);
+
+        void copyFrom(const VendorTagDescriptor& src);
+
         /**
          * The following 'get*' methods implement the corresponding
          * functions defined in
@@ -64,9 +74,9 @@
          *
          * Returns OK on success, or a negative error code.
          */
-        status_t writeToParcel(
+        virtual status_t writeToParcel(
                 /*out*/
-                Parcel* parcel) const;
+                Parcel* parcel) const override;
 
         /**
          * Convenience method to get a vector containing all vendor tag
@@ -86,48 +96,14 @@
          */
         void dump(int fd, int verbosity, int indentation) const;
 
-        // Static methods:
-
         /**
-         * Create a VendorTagDescriptor object from the given parcel.
+         * Read values VendorTagDescriptor object from the given parcel.
          *
          * Returns OK on success, or a negative error code.
          */
-        static status_t createFromParcel(const Parcel* parcel,
-                /*out*/
-                sp<VendorTagDescriptor>& descriptor);
+        virtual status_t readFromParcel(const Parcel* parcel) override;
 
-        /**
-         * Create a VendorTagDescriptor object from the given vendor_tag_ops_t
-         * struct.
-         *
-         * Returns OK on success, or a negative error code.
-         */
-        static status_t createDescriptorFromOps(const vendor_tag_ops_t* vOps,
-                /*out*/
-                sp<VendorTagDescriptor>& descriptor);
-
-        /**
-         * Sets the global vendor tag descriptor to use for this process.
-         * Camera metadata operations that access vendor tags will use the
-         * vendor tag definitions set this way.
-         *
-         * Returns OK on success, or a negative error code.
-         */
-        static status_t setAsGlobalVendorTagDescriptor(const sp<VendorTagDescriptor>& desc);
-
-        /**
-         * Clears the global vendor tag descriptor used by this process.
-         */
-        static void clearGlobalVendorTagDescriptor();
-
-        /**
-         * Returns the global vendor tag descriptor used by this process.
-         * This will contain NULL if no vendor tags are defined.
-         */
-        static sp<VendorTagDescriptor> getGlobalVendorTagDescriptor();
     protected:
-        VendorTagDescriptor();
         KeyedVector<String8, KeyedVector<String8, uint32_t>*> mReverseMapping;
         KeyedVector<uint32_t, String8> mTagToNameMap;
         KeyedVector<uint32_t, uint32_t> mTagToSectionMap; // Value is offset in mSections
@@ -135,11 +111,61 @@
         SortedVector<String8> mSections;
         // must be int32_t to be compatible with Parcel::writeInt32
         int32_t mTagCount;
-    private:
+
         vendor_tag_ops mVendorOps;
 };
+} /* namespace params */
+} /* namespace camera2 */
+} /* namespace hardware */
+
+/**
+ * This version of VendorTagDescriptor must be stored in Android sp<>, and adds support for using it
+ * as a global tag descriptor.
+ *
+ * It's a child class of the basic hardware::camera2::params::VendorTagDescriptor since basic
+ * Parcelable objects cannot require being kept in an sp<> and still work with auto-generated AIDL
+ * interface implementations.
+ */
+class VendorTagDescriptor :
+            public ::android::hardware::camera2::params::VendorTagDescriptor,
+            public LightRefBase<VendorTagDescriptor> {
+
+  public:
+
+    /**
+     * Create a VendorTagDescriptor object from the given vendor_tag_ops_t
+     * struct.
+     *
+     * Returns OK on success, or a negative error code.
+     */
+    static status_t createDescriptorFromOps(const vendor_tag_ops_t* vOps,
+            /*out*/
+            sp<VendorTagDescriptor>& descriptor);
+
+    /**
+     * Sets the global vendor tag descriptor to use for this process.
+     * Camera metadata operations that access vendor tags will use the
+     * vendor tag definitions set this way.
+     *
+     * Returns OK on success, or a negative error code.
+     */
+    static status_t setAsGlobalVendorTagDescriptor(const sp<VendorTagDescriptor>& desc);
+
+    /**
+     * Returns the global vendor tag descriptor used by this process.
+     * This will contain NULL if no vendor tags are defined.
+     */
+    static sp<VendorTagDescriptor> getGlobalVendorTagDescriptor();
+
+    /**
+     * Clears the global vendor tag descriptor used by this process.
+     */
+    static void clearGlobalVendorTagDescriptor();
+
+};
 
 } /* namespace android */
 
+
 #define VENDOR_TAG_DESCRIPTOR_H
 #endif /* VENDOR_TAG_DESCRIPTOR_H */
diff --git a/include/camera/ICamera.h b/include/camera/android/hardware/ICamera.h
similarity index 73%
rename from include/camera/ICamera.h
rename to include/camera/android/hardware/ICamera.h
index b025735..3b12afe 100644
--- a/include/camera/ICamera.h
+++ b/include/camera/android/hardware/ICamera.h
@@ -21,24 +21,36 @@
 #include <binder/IInterface.h>
 #include <binder/Parcel.h>
 #include <binder/IMemory.h>
+#include <binder/Status.h>
 #include <utils/String8.h>
-#include <camera/Camera.h>
 
 namespace android {
 
-class ICameraClient;
 class IGraphicBufferProducer;
 class Surface;
 
+namespace hardware {
+
+class ICameraClient;
+
 class ICamera: public IInterface
 {
     /**
      * Keep up-to-date with ICamera.aidl in frameworks/base
      */
 public:
+    enum {
+        // Pass real YUV data in video buffers through ICameraClient.dataCallbackTimestamp().
+        VIDEO_BUFFER_MODE_DATA_CALLBACK_YUV = 0,
+        // Pass metadata in video buffers through ICameraClient.dataCallbackTimestamp().
+        VIDEO_BUFFER_MODE_DATA_CALLBACK_METADATA = 1,
+        // Pass video buffers through IGraphicBufferProducer set with setVideoTarget().
+        VIDEO_BUFFER_MODE_BUFFER_QUEUE = 2,
+    };
+
     DECLARE_META_INTERFACE(Camera);
 
-    virtual void            disconnect() = 0;
+    virtual binder::Status  disconnect() = 0;
 
     // connect new client with existing camera remote
     virtual status_t        connect(const sp<ICameraClient>& client) = 0;
@@ -82,9 +94,13 @@
     // get recording state
     virtual bool            recordingEnabled() = 0;
 
-    // release a recording frame
+    // Release a recording frame that was received via ICameraClient::dataCallbackTimestamp.
     virtual void            releaseRecordingFrame(const sp<IMemory>& mem) = 0;
 
+    // Release a recording frame handle that was received via
+    // ICameraClient::recordingFrameHandleCallbackTimestamp.
+    virtual void            releaseRecordingFrameHandle(native_handle_t *handle) = 0;
+
     // auto focus
     virtual status_t        autoFocus() = 0;
 
@@ -109,8 +125,16 @@
     // send command to camera driver
     virtual status_t        sendCommand(int32_t cmd, int32_t arg1, int32_t arg2) = 0;
 
-    // tell the camera hal to store meta data or real YUV data in video buffers.
-    virtual status_t        storeMetaDataInBuffers(bool enabled) = 0;
+
+    // Tell camera how to pass video buffers. videoBufferMode is one of VIDEO_BUFFER_MODE_*.
+    // Returns OK if the specified video buffer mode is supported. If videoBufferMode is
+    // VIDEO_BUFFER_MODE_BUFFER_QUEUE, setVideoTarget() must be called before starting video
+    // recording.
+    virtual status_t        setVideoBufferMode(int32_t videoBufferMode) = 0;
+
+    // Set the video buffer producer for camera to use in VIDEO_BUFFER_MODE_BUFFER_QUEUE mode.
+    virtual status_t        setVideoTarget(
+            const sp<IGraphicBufferProducer>& bufferProducer) = 0;
 };
 
 // ----------------------------------------------------------------------------
@@ -124,6 +148,7 @@
                                     uint32_t flags = 0);
 };
 
-}; // namespace android
+} // namespace hardware
+} // namespace android
 
 #endif
diff --git a/include/camera/ICameraClient.h b/include/camera/android/hardware/ICameraClient.h
similarity index 82%
rename from include/camera/ICameraClient.h
rename to include/camera/android/hardware/ICameraClient.h
index 1584dba..3f835a9 100644
--- a/include/camera/ICameraClient.h
+++ b/include/camera/android/hardware/ICameraClient.h
@@ -25,12 +25,10 @@
 #include <system/camera.h>
 
 namespace android {
+namespace hardware {
 
 class ICameraClient: public IInterface
 {
-    /**
-     * Keep up-to-date with ICameraClient.aidl in frameworks/base
-     */
 public:
     DECLARE_META_INTERFACE(CameraClient);
 
@@ -38,6 +36,11 @@
     virtual void            dataCallback(int32_t msgType, const sp<IMemory>& data,
                                          camera_frame_metadata_t *metadata) = 0;
     virtual void            dataCallbackTimestamp(nsecs_t timestamp, int32_t msgType, const sp<IMemory>& data) = 0;
+
+    // Invoked to send a recording frame handle with a timestamp. Call
+    // ICamera::releaseRecordingFrameHandle to release the frame handle.
+    virtual void            recordingFrameHandleCallbackTimestamp(nsecs_t timestamp,
+                                         native_handle_t* handle) = 0;
 };
 
 // ----------------------------------------------------------------------------
@@ -51,6 +54,7 @@
                                     uint32_t flags = 0);
 };
 
-}; // namespace android
+} // namespace hardware
+} // namespace android
 
 #endif
diff --git a/include/camera/camera2/CaptureRequest.h b/include/camera/camera2/CaptureRequest.h
index eeab217..c989f26 100644
--- a/include/camera/camera2/CaptureRequest.h
+++ b/include/camera/camera2/CaptureRequest.h
@@ -19,15 +19,17 @@
 
 #include <utils/RefBase.h>
 #include <utils/Vector.h>
+#include <binder/Parcelable.h>
 #include <camera/CameraMetadata.h>
 
 namespace android {
 
 class Surface;
 
-struct CaptureRequest : public virtual RefBase {
-public:
+namespace hardware {
+namespace camera2 {
 
+struct CaptureRequest : public Parcelable {
     CameraMetadata          mMetadata;
     Vector<sp<Surface> >    mSurfaceList;
     bool                    mIsReprocess;
@@ -35,9 +37,20 @@
     /**
      * Keep impl up-to-date with CaptureRequest.java in frameworks/base
      */
-    status_t                readFromParcel(Parcel* parcel);
-    status_t                writeToParcel(Parcel* parcel) const;
+    status_t                readFromParcel(const Parcel* parcel) override;
+    status_t                writeToParcel(Parcel* parcel) const override;
 };
-}; // namespace android
+
+} // namespace camera2
+} // namespace hardware
+
+struct CaptureRequest :
+        public RefBase, public hardware::camera2::CaptureRequest {
+  public:
+    // Same as android::hardware::camera2::CaptureRequest, except that you can
+    // put this in an sp<>
+};
+
+} // namespace android
 
 #endif
diff --git a/include/camera/camera2/ICameraDeviceCallbacks.h b/include/camera/camera2/ICameraDeviceCallbacks.h
deleted file mode 100644
index c57b39f..0000000
--- a/include/camera/camera2/ICameraDeviceCallbacks.h
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_HARDWARE_PHOTOGRAPHY_CALLBACKS_H
-#define ANDROID_HARDWARE_PHOTOGRAPHY_CALLBACKS_H
-
-#include <utils/RefBase.h>
-#include <binder/IInterface.h>
-#include <binder/Parcel.h>
-#include <binder/IMemory.h>
-#include <utils/Timers.h>
-#include <system/camera.h>
-
-#include <camera/CaptureResult.h>
-
-namespace android {
-class CameraMetadata;
-
-
-class ICameraDeviceCallbacks : public IInterface
-{
-    /**
-     * Keep up-to-date with ICameraDeviceCallbacks.aidl in frameworks/base
-     */
-public:
-    DECLARE_META_INTERFACE(CameraDeviceCallbacks);
-
-    /**
-     * Error codes for CAMERA_MSG_ERROR
-     */
-    enum CameraErrorCode {
-        ERROR_CAMERA_INVALID_ERROR = -1, // To indicate all invalid error codes
-        ERROR_CAMERA_DISCONNECTED = 0,
-        ERROR_CAMERA_DEVICE = 1,
-        ERROR_CAMERA_SERVICE = 2,
-        ERROR_CAMERA_REQUEST = 3,
-        ERROR_CAMERA_RESULT = 4,
-        ERROR_CAMERA_BUFFER = 5,
-    };
-
-    // One way
-    virtual void            onDeviceError(CameraErrorCode errorCode,
-                                          const CaptureResultExtras& resultExtras) = 0;
-
-    // One way
-    virtual void            onDeviceIdle() = 0;
-
-    // One way
-    virtual void            onCaptureStarted(const CaptureResultExtras& resultExtras,
-                                             int64_t timestamp) = 0;
-
-    // One way
-    virtual void            onResultReceived(const CameraMetadata& metadata,
-                                             const CaptureResultExtras& resultExtras) = 0;
-
-    // One way
-    virtual void            onPrepared(int streamId) = 0;
-};
-
-// ----------------------------------------------------------------------------
-
-class BnCameraDeviceCallbacks : public BnInterface<ICameraDeviceCallbacks>
-{
-public:
-    virtual status_t    onTransact( uint32_t code,
-                                    const Parcel& data,
-                                    Parcel* reply,
-                                    uint32_t flags = 0);
-};
-
-}; // namespace android
-
-#endif
diff --git a/include/camera/camera2/ICameraDeviceUser.h b/include/camera/camera2/ICameraDeviceUser.h
deleted file mode 100644
index 4d8eb53..0000000
--- a/include/camera/camera2/ICameraDeviceUser.h
+++ /dev/null
@@ -1,167 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_HARDWARE_PHOTOGRAPHY_ICAMERADEVICEUSER_H
-#define ANDROID_HARDWARE_PHOTOGRAPHY_ICAMERADEVICEUSER_H
-
-#include <binder/IInterface.h>
-#include <binder/Parcel.h>
-#include <utils/List.h>
-
-struct camera_metadata;
-
-namespace android {
-
-class ICameraDeviceUserClient;
-class IGraphicBufferProducer;
-class CaptureRequest;
-class CameraMetadata;
-class OutputConfiguration;
-
-enum {
-    NO_IN_FLIGHT_REPEATING_FRAMES = -1,
-};
-
-class ICameraDeviceUser : public IInterface
-{
-    /**
-     * Keep up-to-date with ICameraDeviceUser.aidl in frameworks/base
-     */
-public:
-    DECLARE_META_INTERFACE(CameraDeviceUser);
-
-    virtual void            disconnect() = 0;
-
-    /**
-     * Request Handling
-     **/
-
-    /**
-     * For streaming requests, output lastFrameNumber is the last frame number
-     * of the previous repeating request.
-     * For non-streaming requests, output lastFrameNumber is the expected last
-     * frame number of the current request.
-     */
-    virtual int             submitRequest(sp<CaptureRequest> request,
-                                          bool streaming = false,
-                                          /*out*/
-                                          int64_t* lastFrameNumber = NULL) = 0;
-
-    /**
-     * For streaming requests, output lastFrameNumber is the last frame number
-     * of the previous repeating request.
-     * For non-streaming requests, output lastFrameNumber is the expected last
-     * frame number of the current request.
-     */
-    virtual int             submitRequestList(List<sp<CaptureRequest> > requestList,
-                                              bool streaming = false,
-                                              /*out*/
-                                              int64_t* lastFrameNumber = NULL) = 0;
-
-    /**
-     * Output lastFrameNumber is the last frame number of the previous repeating request.
-     */
-    virtual status_t        cancelRequest(int requestId,
-                                          /*out*/
-                                          int64_t* lastFrameNumber = NULL) = 0;
-
-    /**
-     * Begin the device configuration.
-     *
-     * <p>
-     * beginConfigure must be called before any call to deleteStream, createStream,
-     * or endConfigure.  It is not valid to call this when the device is not idle.
-     * <p>
-     */
-    virtual status_t        beginConfigure() = 0;
-
-    /**
-     * End the device configuration.
-     *
-     * <p>
-     * endConfigure must be called after stream configuration is complete (i.e. after
-     * a call to beginConfigure and subsequent createStream/deleteStream calls).  This
-     * must be called before any requests can be submitted.
-     * <p>
-     */
-    virtual status_t        endConfigure(bool isConstrainedHighSpeed = false) = 0;
-
-    virtual status_t        deleteStream(int streamId) = 0;
-
-    virtual status_t        createStream(const OutputConfiguration& outputConfiguration) = 0;
-
-    /**
-     * Create an input stream of width, height, and format (one of
-     * HAL_PIXEL_FORMAT_*)
-     *
-     * Return stream ID if it's a non-negative value. status_t if it's a
-     * negative value.
-     */
-    virtual status_t        createInputStream(int width, int height, int format) = 0;
-
-    // get the buffer producer of the input stream
-    virtual status_t        getInputBufferProducer(
-            sp<IGraphicBufferProducer> *producer) = 0;
-
-    // Create a request object from a template.
-    virtual status_t        createDefaultRequest(int templateId,
-                                                 /*out*/
-                                                 CameraMetadata* request) = 0;
-    // Get static camera metadata
-    virtual status_t        getCameraInfo(/*out*/
-                                          CameraMetadata* info) = 0;
-
-    // Wait until all the submitted requests have finished processing
-    virtual status_t        waitUntilIdle() =  0;
-
-    /**
-     * Flush all pending and in-progress work as quickly as possible.
-     * Output lastFrameNumber is the last frame number of the previous repeating request.
-     */
-    virtual status_t        flush(/*out*/
-                                  int64_t* lastFrameNumber = NULL) = 0;
-
-    /**
-     * Preallocate buffers for a given output stream asynchronously.
-     */
-    virtual status_t        prepare(int streamId) = 0;
-
-    /**
-     * Preallocate up to maxCount buffers for a given output stream asynchronously.
-     */
-    virtual status_t        prepare2(int maxCount, int streamId) = 0;
-
-    /**
-     * Free all unused buffers for a given output stream.
-     */
-    virtual status_t        tearDown(int streamId) = 0;
-
-};
-
-// ----------------------------------------------------------------------------
-
-class BnCameraDeviceUser: public BnInterface<ICameraDeviceUser>
-{
-public:
-    virtual status_t    onTransact( uint32_t code,
-                                    const Parcel& data,
-                                    Parcel* reply,
-                                    uint32_t flags = 0);
-};
-
-}; // namespace android
-
-#endif
diff --git a/include/camera/camera2/OutputConfiguration.h b/include/camera/camera2/OutputConfiguration.h
index 5bcbe15..72a3753 100644
--- a/include/camera/camera2/OutputConfiguration.h
+++ b/include/camera/camera2/OutputConfiguration.h
@@ -17,37 +17,80 @@
 #ifndef ANDROID_HARDWARE_CAMERA2_OUTPUTCONFIGURATION_H
 #define ANDROID_HARDWARE_CAMERA2_OUTPUTCONFIGURATION_H
 
-#include <utils/RefBase.h>
 #include <gui/IGraphicBufferProducer.h>
+#include <binder/Parcelable.h>
 
 namespace android {
 
 class Surface;
 
-class OutputConfiguration : public virtual RefBase {
+namespace hardware {
+namespace camera2 {
+namespace params {
+
+class OutputConfiguration : public android::Parcelable {
 public:
 
     static const int INVALID_ROTATION;
+    static const int INVALID_SET_ID;
     sp<IGraphicBufferProducer> getGraphicBufferProducer() const;
     int                        getRotation() const;
+    int                        getSurfaceSetID() const;
 
     /**
      * Keep impl up-to-date with OutputConfiguration.java in frameworks/base
      */
-    status_t                   writeToParcel(Parcel& parcel) const;
+    virtual status_t           writeToParcel(Parcel* parcel) const override;
+
+    virtual status_t           readFromParcel(const Parcel* parcel) override;
+
+    // getGraphicBufferProducer will be NULL
+    // getRotation will be INVALID_ROTATION
+    // getSurfaceSetID will be INVALID_SET_ID
+    OutputConfiguration();
+
     // getGraphicBufferProducer will be NULL if error occurred
     // getRotation will be INVALID_ROTATION if error occurred
+    // getSurfaceSetID will be INVALID_SET_ID if error occurred
     OutputConfiguration(const Parcel& parcel);
 
-    OutputConfiguration(sp<IGraphicBufferProducer>& gbp, int rotation);
+    OutputConfiguration(sp<IGraphicBufferProducer>& gbp, int rotation,
+            int surfaceSetID = INVALID_SET_ID);
+
+    bool operator == (const OutputConfiguration& other) const {
+        return (mGbp == other.mGbp &&
+                mRotation == other.mRotation &&
+                mSurfaceSetID == other.mSurfaceSetID);
+    }
+    bool operator != (const OutputConfiguration& other) const {
+        return !(*this == other);
+    }
+    bool operator < (const OutputConfiguration& other) const {
+        if (*this == other) return false;
+        if (mGbp != other.mGbp) return mGbp < other.mGbp;
+        if (mSurfaceSetID != other.mSurfaceSetID) {
+            return mSurfaceSetID < other.mSurfaceSetID;
+        }
+        return mRotation < other.mRotation;
+    }
+    bool operator > (const OutputConfiguration& other) const {
+        return (*this != other && !(*this < other));
+    }
 
 private:
     sp<IGraphicBufferProducer> mGbp;
     int                        mRotation;
-
+    int                        mSurfaceSetID;
     // helper function
-    static String16 readMaybeEmptyString16(const Parcel& parcel);
+    static String16 readMaybeEmptyString16(const Parcel* parcel);
 };
+} // namespace params
+} // namespace camera2
+} // namespace hardware
+
+
+using hardware::camera2::params::OutputConfiguration;
+
 }; // namespace android
 
 #endif
diff --git a/include/camera/camera2/SubmitInfo.h b/include/camera/camera2/SubmitInfo.h
new file mode 100644
index 0000000..3b47b32
--- /dev/null
+++ b/include/camera/camera2/SubmitInfo.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_CAMERA2_UTIL_SUBMITINFO_H
+#define ANDROID_HARDWARE_CAMERA2_UTIL_SUBMITINFO_H
+
+#include <binder/Parcel.h>
+#include <binder/Parcelable.h>
+
+namespace android {
+namespace hardware {
+namespace camera2 {
+namespace utils {
+
+struct SubmitInfo : public android::Parcelable {
+public:
+
+    int32_t mRequestId;
+    int64_t mLastFrameNumber;
+
+    virtual status_t writeToParcel(Parcel *parcel) const override;
+    virtual status_t readFromParcel(const Parcel* parcel) override;
+
+};
+
+} // namespace utils
+} // namespace camera2
+} // namespace hardware
+} // namespace android
+
+#endif
diff --git a/include/camera/ndk/NdkCameraCaptureSession.h b/include/camera/ndk/NdkCameraCaptureSession.h
new file mode 100644
index 0000000..7b314e9
--- /dev/null
+++ b/include/camera/ndk/NdkCameraCaptureSession.h
@@ -0,0 +1,597 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @addtogroup Camera
+ * @{
+ */
+
+/**
+ * @file NdkCameraCaptureSession.h
+ */
+
+/*
+ * This file defines an NDK API.
+ * Do not remove methods.
+ * Do not change method signatures.
+ * Do not change the value of constants.
+ * Do not change the size of any of the classes defined in here.
+ * Do not reference types that are not part of the NDK.
+ * Do not #include files that aren't part of the NDK.
+ */
+#include <android/native_window.h>
+#include "NdkCameraError.h"
+#include "NdkCameraMetadata.h"
+
+#ifndef _NDK_CAMERA_CAPTURE_SESSION_H
+#define _NDK_CAMERA_CAPTURE_SESSION_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * ACameraCaptureSession is an opaque type that manages frame captures of a camera device.
+ *
+ * A pointer can be obtained using {@link ACameraDevice_createCaptureSession} method.
+ */
+typedef struct ACameraCaptureSession ACameraCaptureSession;
+
+/**
+ * The definition of camera capture session state callback.
+ *
+ * @param context The optional application context provided by user in
+ *                {@link ACameraCaptureSession_stateCallbacks}.
+ * @param session The camera capture session whose state is changing.
+ */
+typedef void (*ACameraCaptureSession_stateCallback)(void* context, ACameraCaptureSession *session);
+
+typedef struct ACameraCaptureSession_stateCallbacks {
+    /// optional application context.
+    void*                               context;
+
+    /**
+     * This callback is called when the session is closed and deleted from memory.
+     *
+     * <p>A session is closed when {@link ACameraCaptureSession_close} is called, a new session
+     * is created by the parent camera device,
+     * or when the parent camera device is closed (either by the user closing the device,
+     * or due to a camera device disconnection or fatal error).</p>
+     *
+     * <p>Once this callback is called, all access to this ACameraCaptureSession object will cause
+     * a crash.</p>
+     */
+    ACameraCaptureSession_stateCallback onClosed;
+
+    /**
+     * This callback is called every time the session has no more capture requests to process.
+     *
+     * <p>This callback will be invoked any time the session finishes processing
+     * all of its active capture requests, and no repeating request or burst is set up.</p>
+     */
+    ACameraCaptureSession_stateCallback onReady;
+
+    /**
+     * This callback is called when the session starts actively processing capture requests.
+     *
+     * <p>If the session runs out of capture requests to process and calls {@link onReady},
+     * then this callback will be invoked again once new requests are submitted for capture.</p>
+     */
+    ACameraCaptureSession_stateCallback onActive;
+} ACameraCaptureSession_stateCallbacks;
+
+/// Enum for describing error reason in {@link ACameraCaptureFailure}
+enum {
+    /**
+     * The capture session has dropped this frame due to an
+     * {@link ACameraCaptureSession_abortCaptures} call.
+     */
+    CAPTURE_FAILURE_REASON_FLUSHED = 0,
+
+    /**
+     * The capture session has dropped this frame due to an error in the framework.
+     */
+    CAPTURE_FAILURE_REASON_ERROR
+};
+
+/// Struct to describe a capture failure
+typedef struct ACameraCaptureFailure {
+    /**
+     * The frame number associated with this failed capture.
+     *
+     * <p>Whenever a request has been processed, regardless of failed capture or success,
+     * it gets a unique frame number assigned to its future result/failed capture.</p>
+     *
+     * <p>This value monotonically increments, starting with 0,
+     * for every new result or failure; and the scope is the lifetime of the
+     * {@link ACameraDevice}.</p>
+     */
+    int64_t frameNumber;
+
+    /**
+     * Determine why the request was dropped, whether due to an error or to a user
+     * action.
+     *
+     * @see CAPTURE_FAILURE_REASON_ERROR
+     * @see CAPTURE_FAILURE_REASON_FLUSHED
+     */
+    int     reason;
+
+    /**
+     * The sequence ID for this failed capture that was returned by the
+     * {@link ACameraCaptureSession_capture} or {@link ACameraCaptureSession_setRepeatingRequest}.
+     *
+     * <p>The sequence ID is a unique monotonically increasing value starting from 0,
+     * incremented every time a new group of requests is submitted to the ACameraDevice.</p>
+     */
+    int     sequenceId;
+
+    /**
+     * Determine if the image was captured from the camera.
+     *
+     * <p>If the image was not captured, no image buffers will be available.
+     * If the image was captured, then image buffers may be available.</p>
+     *
+     */
+    bool    wasImageCaptured;
+} ACameraCaptureFailure;
+
+/**
+ * The definition of camera capture start callback.
+ *
+ * @param context The optional application context provided by user in
+ *                {@link ACameraCaptureSession_captureCallbacks}.
+ * @param session The camera capture session of interest.
+ * @param request The capture request that is starting. Note that this pointer points to a copy of
+ *                capture request sent by application, so the address is different to what
+ *                application sent but the content will match. This request will be freed by
+ *                framework immediately after this callback returns.
+ * @param timestamp The timestamp when the capture is started. This timestmap will match
+ *                  {@link ACAMERA_SENSOR_TIMESTAMP} of the {@link ACameraMetadata} in
+ *                  {@link ACameraCaptureSession_captureCallbacks#onCaptureCompleted} callback.
+ */
+typedef void (*ACameraCaptureSession_captureCallback_start)(
+        void* context, ACameraCaptureSession* session,
+        const ACaptureRequest* request, int64_t timestamp);
+
+/**
+ * The definition of camera capture progress/result callback.
+ *
+ * @param context The optional application context provided by user in
+ *                {@link ACameraCaptureSession_captureCallbacks}.
+ * @param session The camera capture session of interest.
+ * @param request The capture request of interest. Note that this pointer points to a copy of
+ *                capture request sent by application, so the address is different to what
+ *                application sent but the content will match. This request will be freed by
+ *                framework immediately after this callback returns.
+ * @param result The capture result metadata reported by camera device. The memory is managed by
+ *                camera framework. Do not access this pointer after this callback returns.
+ */
+typedef void (*ACameraCaptureSession_captureCallback_result)(
+        void* context, ACameraCaptureSession* session,
+        ACaptureRequest* request, const ACameraMetadata* result);
+
+/**
+ * The definition of camera capture failure callback.
+ *
+ * @param context The optional application context provided by user in
+ *                {@link ACameraCaptureSession_captureCallbacks}.
+ * @param session The camera capture session of interest.
+ * @param request The capture request of interest. Note that this pointer points to a copy of
+ *                capture request sent by application, so the address is different to what
+ *                application sent but the content will match. This request will be freed by
+ *                framework immediately after this callback returns.
+ * @param failure The {@link ACameraCaptureFailure} desribes the capture failure. The memory is
+ *                managed by camera framework. Do not access this pointer after this callback
+ *                returns.
+ */
+typedef void (*ACameraCaptureSession_captureCallback_failed)(
+        void* context, ACameraCaptureSession* session,
+        ACaptureRequest* request, ACameraCaptureFailure* failure);
+
+/**
+ * The definition of camera sequence end callback.
+ *
+ * @param context The optional application context provided by user in
+ *                {@link ACameraCaptureSession_captureCallbacks}.
+ * @param session The camera capture session of interest.
+ * @param sequenceId The capture sequence ID of the finished sequence.
+ * @param frameNumber The frame number of the last frame of this sequence.
+ */
+typedef void (*ACameraCaptureSession_captureCallback_sequenceEnd)(
+        void* context, ACameraCaptureSession* session,
+        int sequenceId, int64_t frameNumber);
+
+/**
+ * The definition of camera sequence aborted callback.
+ *
+ * @param context The optional application context provided by user in
+ *                {@link ACameraCaptureSession_captureCallbacks}.
+ * @param session The camera capture session of interest.
+ * @param sequenceId The capture sequence ID of the aborted sequence.
+ */
+typedef void (*ACameraCaptureSession_captureCallback_sequenceAbort)(
+        void* context, ACameraCaptureSession* session,
+        int sequenceId);
+
+/**
+ * The definition of camera buffer lost callback.
+ *
+ * @param context The optional application context provided by user in
+ *                {@link ACameraCaptureSession_captureCallbacks}.
+ * @param session The camera capture session of interest.
+ * @param request The capture request of interest. Note that this pointer points to a copy of
+ *                capture request sent by application, so the address is different to what
+ *                application sent but the content will match. This request will be freed by
+ *                framework immediately after this callback returns.
+ * @param window The {@link ANativeWindow} that the lost buffer would have been sent to.
+ * @param frameNumber The frame number of the lost buffer.
+ */
+typedef void (*ACameraCaptureSession_captureCallback_bufferLost)(
+        void* context, ACameraCaptureSession* session,
+        ACaptureRequest* request, ANativeWindow* window, int64_t frameNumber);
+
+typedef struct ACameraCaptureSession_captureCallbacks {
+    /// optional application context.
+    void*                                               context;
+
+    /**
+     * This callback is called when the camera device has started capturing
+     * the output image for the request, at the beginning of image exposure.
+     *
+     * <p>This callback is invoked right as
+     * the capture of a frame begins, so it is the most appropriate time
+     * for playing a shutter sound, or triggering UI indicators of capture.</p>
+     *
+     * <p>The request that is being used for this capture is provided, along
+     * with the actual timestamp for the start of exposure.
+     * This timestamp matches the timestamps that will be
+     * included in {@link ACAMERA_SENSOR_TIMESTAMP} of the {@link ACameraMetadata} in
+     * {@link onCaptureCompleted} callback,
+     * and in the buffers sent to each output ANativeWindow. These buffer
+     * timestamps are accessible through, for example,
+     * {@link AImage_getTimestamp} or
+     * <a href="http://developer.android.com/reference/android/graphics/SurfaceTexture.html#getTimestamp()">
+     * android.graphics.SurfaceTexture#getTimestamp()</a>.</p>
+     *
+     * <p>Note that the ACaptureRequest pointer in the callback will not match what application has
+     * submitted, but the contents the ACaptureRequest will match what application submitted.</p>
+     *
+     */
+    ACameraCaptureSession_captureCallback_start         onCaptureStarted;
+
+    /**
+     * This callback is called when an image capture makes partial forward progress; some
+     * (but not all) results from an image capture are available.
+     *
+     * <p>The result provided here will contain some subset of the fields of
+     * a full result. Multiple {@link onCaptureProgressed} calls may happen per
+     * capture; a given result field will only be present in one partial
+     * capture at most. The final {@link onCaptureCompleted} call will always
+     * contain all the fields (in particular, the union of all the fields of all
+     * the partial results composing the total result).</p>
+     *
+     * <p>For each request, some result data might be available earlier than others. The typical
+     * delay between each partial result (per request) is a single frame interval.
+     * For performance-oriented use-cases, applications should query the metadata they need
+     * to make forward progress from the partial results and avoid waiting for the completed
+     * result.</p>
+     *
+     * <p>For a particular request, {@link onCaptureProgressed} may happen before or after
+     * {@link onCaptureStarted}.</p>
+     *
+     * <p>Each request will generate at least `1` partial results, and at most
+     * {@link ACAMERA_REQUEST_PARTIAL_RESULT_COUNT} partial results.</p>
+     *
+     * <p>Depending on the request settings, the number of partial results per request
+     * will vary, although typically the partial count could be the same as long as the
+     * camera device subsystems enabled stay the same.</p>
+     *
+     * <p>Note that the ACaptureRequest pointer in the callback will not match what application has
+     * submitted, but the contents the ACaptureRequest will match what application submitted.</p>
+     */
+    ACameraCaptureSession_captureCallback_result        onCaptureProgressed;
+
+    /**
+     * This callback is called when an image capture has fully completed and all the
+     * result metadata is available.
+     *
+     * <p>This callback will always fire after the last {@link onCaptureProgressed};
+     * in other words, no more partial results will be delivered once the completed result
+     * is available.</p>
+     *
+     * <p>For performance-intensive use-cases where latency is a factor, consider
+     * using {@link onCaptureProgressed} instead.</p>
+     *
+     * <p>Note that the ACaptureRequest pointer in the callback will not match what application has
+     * submitted, but the contents the ACaptureRequest will match what application submitted.</p>
+     */
+    ACameraCaptureSession_captureCallback_result        onCaptureCompleted;
+
+    /**
+     * This callback is called instead of {@link onCaptureCompleted} when the
+     * camera device failed to produce a capture result for the
+     * request.
+     *
+     * <p>Other requests are unaffected, and some or all image buffers from
+     * the capture may have been pushed to their respective output
+     * streams.</p>
+     *
+     * <p>Note that the ACaptureRequest pointer in the callback will not match what application has
+     * submitted, but the contents the ACaptureRequest will match what application submitted.</p>
+     *
+     * @see ACameraCaptureFailure
+     */
+    ACameraCaptureSession_captureCallback_failed        onCaptureFailed;
+
+    /**
+     * This callback is called independently of the others in {@link ACameraCaptureSession_captureCallbacks},
+     * when a capture sequence finishes and all capture result
+     * or capture failure for it have been returned via this {@link ACameraCaptureSession_captureCallbacks}.
+     *
+     * <p>In total, there will be at least one result/failure returned by this listener
+     * before this callback is invoked. If the capture sequence is aborted before any
+     * requests have been processed, {@link onCaptureSequenceAborted} is invoked instead.</p>
+     */
+    ACameraCaptureSession_captureCallback_sequenceEnd   onCaptureSequenceCompleted;
+
+    /**
+     * This callback is called independently of the others in {@link ACameraCaptureSession_captureCallbacks},
+     * when a capture sequence aborts before any capture result
+     * or capture failure for it have been returned via this {@link ACameraCaptureSession_captureCallbacks}.
+     *
+     * <p>Due to the asynchronous nature of the camera device, not all submitted captures
+     * are immediately processed. It is possible to clear out the pending requests
+     * by a variety of operations such as {@link ACameraCaptureSession_stopRepeating} or
+     * {@link ACameraCaptureSession_abortCaptures}. When such an event happens,
+     * {@link onCaptureSequenceCompleted} will not be called.</p>
+     */
+    ACameraCaptureSession_captureCallback_sequenceAbort onCaptureSequenceAborted;
+
+    /**
+     * This callback is called if a single buffer for a capture could not be sent to its
+     * destination ANativeWindow.
+     *
+     * <p>If the whole capture failed, then {@link onCaptureFailed} will be called instead. If
+     * some but not all buffers were captured but the result metadata will not be available,
+     * then onCaptureFailed will be invoked with {@link ACameraCaptureFailure#wasImageCaptured}
+     * returning true, along with one or more calls to {@link onCaptureBufferLost} for the
+     * failed outputs.</p>
+     *
+     * <p>Note that the ACaptureRequest pointer in the callback will not match what application has
+     * submitted, but the contents the ACaptureRequest will match what application submitted.
+     * The ANativeWindow pointer will always match what application submitted in
+     * {@link ACameraDevice_createCaptureSession}</p>
+     *
+     */
+    ACameraCaptureSession_captureCallback_bufferLost    onCaptureBufferLost;
+} ACameraCaptureSession_captureCallbacks;
+
+enum {
+    CAPTURE_SEQUENCE_ID_NONE = -1
+};
+
+/**
+ * Close this capture session.
+ *
+ * <p>Closing a session frees up the target output Surfaces of the session for reuse with either
+ * a new session, or to other APIs that can draw to Surfaces.</p>
+ *
+ * <p>Note that creating a new capture session with {@link ACameraDevice_createCaptureSession}
+ * will close any existing capture session automatically, and call the older session listener's
+ * {@link ACameraCaptureSession_stateCallbacks#onClosed} callback. Using
+ * {@link ACameraDevice_createCaptureSession} directly without closing is the recommended approach
+ * for quickly switching to a new session, since unchanged target outputs can be reused more
+ * efficiently.</p>
+ *
+ * <p>After a session is closed and before {@link ACameraCaptureSession_stateCallbacks#onClosed}
+ * is called, all methods invoked on the session will return {@link ACAMERA_ERROR_SESSION_CLOSED},
+ * and any repeating requests are stopped (as if {@link ACameraCaptureSession_stopRepeating} was
+ * called). However, any in-progress capture requests submitted to the session will be completed as
+ * normal; once all captures have completed and the session has been torn down,
+ * {@link ACameraCaptureSession_stateCallbacks#onClosed} callback will be called and the seesion
+ * will be removed from memory.</p>
+ *
+ * <p>Closing a session is idempotent; closing more than once has no effect.</p>
+ *
+ * @param session the capture session of interest
+ */
+void ACameraCaptureSession_close(ACameraCaptureSession* session);
+
+struct ACameraDevice;
+typedef struct ACameraDevice ACameraDevice;
+
+/**
+ * Get the ACameraDevice pointer associated with this capture session in the device argument
+ * if the method succeeds.
+ *
+ * @param session the capture session of interest
+ * @param device the {@link ACameraDevice} associated with session. Will be set to NULL
+ *        if the session is closed or this method fails.
+ * @return <ul><li>
+ *             {@link ACAMERA_OK} if the method call succeeds. The {@link ACameraDevice}
+ *                                will be stored in device argument</li>
+ *         <li>{@link ACAMERA_ERROR_INVALID_PARAMETER} if session or device is NULL</li>
+ *         <li>{@link ACAMERA_ERROR_SESSION_CLOSED} if the capture session has been closed</li>
+ *         <li>{@link ACAMERA_ERROR_UNKNOWN} if the method fails for some other reasons</li></ul>
+ *
+ */
+camera_status_t ACameraCaptureSession_getDevice(
+        ACameraCaptureSession* session, /*out*/ACameraDevice** device);
+
+/**
+ * Submit an array of requests to be captured in sequence as a burst in the minimum of time possible.
+ *
+ * <p>The burst will be captured in the minimum amount of time possible, and will not be
+ * interleaved with requests submitted by other capture or repeat calls.</p>
+ *
+ * <p>Each capture produces one {@link ACameraMetadata} as a capture result and image buffers for
+ * one or more target {@link ANativeWindow}s. The target ANativeWindows (set with
+ * {@link ACaptureRequest_addTarget}) must be a subset of the ANativeWindow provided when
+ * this capture session was created.</p>
+ *
+ * @param session the capture session of interest
+ * @param callbacks the {@link ACameraCaptureSession_captureCallbacks} to be associated this capture
+ *        sequence. No capture callback will be fired if this is set to NULL.
+ * @param numRequests number of requests in requests argument. Must be at least 1.
+ * @param requests an array of {@link ACaptureRequest} to be captured. Length must be at least
+ *        numRequests.
+ * @param captureSequenceId the capture sequence ID associated with this capture method invocation
+ *        will be stored here if this argument is not NULL and the method call succeeds.
+ *        When this argument is set to NULL, the capture sequence ID will not be returned.
+ *
+ * @return <ul><li>
+ *             {@link ACAMERA_OK} if the method succeeds. captureSequenceId will be filled
+ *             if it is not NULL.</li>
+ *         <li>{@link ACAMERA_ERROR_INVALID_PARAMETER} if session or requests is NULL, or
+ *             if numRequests < 1</li>
+ *         <li>{@link ACAMERA_ERROR_SESSION_CLOSED} if the capture session has been closed</li>
+ *         <li>{@link ACAMERA_ERROR_CAMERA_DISCONNECTED} if the camera device is closed</li>
+ *         <li>{@link ACAMERA_ERROR_CAMERA_DEVICE} if the camera device encounters fatal error</li>
+ *         <li>{@link ACAMERA_ERROR_CAMERA_SERVICE} if the camera service encounters fatal error</li>
+ *         <li>{@link ACAMERA_ERROR_UNKNOWN} if the method fails for some other reasons</li></ul>
+ */
+camera_status_t ACameraCaptureSession_capture(
+        ACameraCaptureSession* session,
+        /*optional*/ACameraCaptureSession_captureCallbacks* callbacks,
+        int numRequests, ACaptureRequest** requests,
+        /*optional*/int* captureSequenceId);
+
+/**
+ * Request endlessly repeating capture of a sequence of images by this capture session.
+ *
+ * <p>With this method, the camera device will continually capture images,
+ * cycling through the settings in the provided list of
+ * {@link ACaptureRequest}, at the maximum rate possible.</p>
+ *
+ * <p>If a request is submitted through {@link ACameraCaptureSession_capture},
+ * the current repetition of the request list will be
+ * completed before the higher-priority request is handled. This guarantees
+ * that the application always receives a complete repeat burst captured in
+ * minimal time, instead of bursts interleaved with higher-priority
+ * captures, or incomplete captures.</p>
+ *
+ * <p>Repeating burst requests are a simple way for an application to
+ * maintain a preview or other continuous stream of frames where each
+ * request is different in a predicatable way, without having to continually
+ * submit requests through {@link ACameraCaptureSession_capture}.</p>
+ *
+ * <p>To stop the repeating capture, call {@link ACameraCaptureSession_stopRepeating}. Any
+ * ongoing burst will still be completed, however. Calling
+ * {@link ACameraCaptureSession_abortCaptures} will also clear the request.</p>
+ *
+ * <p>Calling this method will replace a previously-set repeating requests
+ * set up by this method, although any in-progress burst will be completed before the new repeat
+ * burst will be used.</p>
+ *
+ * @param session the capture session of interest
+ * @param callbacks the {@link ACameraCaptureSession_captureCallbacks} to be associated with this
+ *        capture sequence. No capture callback will be fired if callbacks is set to NULL.
+ * @param numRequests number of requests in requests array. Must be at least 1.
+ * @param requests an array of {@link ACaptureRequest} to be captured. Length must be at least
+ *        numRequests.
+ * @param captureSequenceId the capture sequence ID associated with this capture method invocation
+ *        will be stored here if this argument is not NULL and the method call succeeds.
+ *        When this argument is set to NULL, the capture sequence ID will not be returned.
+ *
+ * @return <ul><li>
+ *             {@link ACAMERA_OK} if the method succeeds. captureSequenceId will be filled
+ *             if it is not NULL.</li>
+ *         <li>{@link ACAMERA_ERROR_INVALID_PARAMETER} if session or requests is NULL, or
+ *             if numRequests < 1</li>
+ *         <li>{@link ACAMERA_ERROR_SESSION_CLOSED} if the capture session has been closed</li>
+ *         <li>{@link ACAMERA_ERROR_CAMERA_DISCONNECTED} if the camera device is closed</li>
+ *         <li>{@link ACAMERA_ERROR_CAMERA_DEVICE} if the camera device encounters fatal error</li>
+ *         <li>{@link ACAMERA_ERROR_CAMERA_SERVICE} if the camera service encounters fatal error</li>
+ *         <li>{@link ACAMERA_ERROR_UNKNOWN} if the method fails for  some other reasons</li></ul>
+ */
+camera_status_t ACameraCaptureSession_setRepeatingRequest(
+        ACameraCaptureSession* session,
+        /*optional*/ACameraCaptureSession_captureCallbacks* callbacks,
+        int numRequests, ACaptureRequest** requests,
+        /*optional*/int* captureSequenceId);
+
+/**
+ * Cancel any ongoing repeating capture set by {@link ACameraCaptureSession_setRepeatingRequest}.
+ * Has no effect on requests submitted through {@link ACameraCaptureSession_capture}.
+ *
+ * <p>Any currently in-flight captures will still complete, as will any burst that is
+ * mid-capture. To ensure that the device has finished processing all of its capture requests
+ * and is in ready state, wait for the {@link ACameraCaptureSession_stateCallbacks#onReady} callback
+ * after calling this method.</p>
+ *
+ * @param session the capture session of interest
+ *
+ * @return <ul><li>
+ *             {@link ACAMERA_OK} if the method succeeds. captureSequenceId will be filled
+ *             if it is not NULL.</li>
+ *         <li>{@link ACAMERA_ERROR_INVALID_PARAMETER} if session is NULL.</li>
+ *         <li>{@link ACAMERA_ERROR_SESSION_CLOSED} if the capture session has been closed</li>
+ *         <li>{@link ACAMERA_ERROR_CAMERA_DISCONNECTED} if the camera device is closed</li>
+ *         <li>{@link ACAMERA_ERROR_CAMERA_DEVICE} if the camera device encounters fatal error</li>
+ *         <li>{@link ACAMERA_ERROR_CAMERA_SERVICE} if the camera service encounters fatal error</li>
+ *         <li>{@link ACAMERA_ERROR_UNKNOWN} if the method fails for some other reasons</li></ul>
+ */
+camera_status_t ACameraCaptureSession_stopRepeating(ACameraCaptureSession* session);
+
+/**
+ * Discard all captures currently pending and in-progress as fast as possible.
+ *
+ * <p>The camera device will discard all of its current work as fast as possible. Some in-flight
+ * captures may complete successfully and call
+ * {@link ACameraCaptureSession_captureCallbacks#onCaptureCompleted},
+ * while others will trigger their {@link ACameraCaptureSession_captureCallbacks#onCaptureFailed}
+ * callbacks. If a repeating request list is set, it will be cleared.</p>
+ *
+ * <p>This method is the fastest way to switch the camera device to a new session with
+ * {@link ACameraDevice_createCaptureSession}, at the cost of discarding in-progress
+ * work. It must be called before the new session is created. Once all pending requests are
+ * either completed or thrown away, the {@link ACameraCaptureSession_stateCallbacks#onReady}
+ * callback will be called, if the session has not been closed. Otherwise, the
+ * {@link ACameraCaptureSession_stateCallbacks#onClosed}
+ * callback will be fired when a new session is created by the camera device and the previous
+ * session is being removed from memory.</p>
+ *
+ * <p>Cancelling will introduce at least a brief pause in the stream of data from the camera
+ * device, since once the camera device is emptied, the first new request has to make it through
+ * the entire camera pipeline before new output buffers are produced.</p>
+ *
+ * <p>This means that using ACameraCaptureSession_abortCaptures to simply remove pending requests is
+ * not recommended; it's best used for quickly switching output configurations, or for cancelling
+ * long in-progress requests (such as a multi-second capture).</p>
+ *
+ * @param session the capture session of interest
+ *
+ * @return <ul><li>
+ *             {@link ACAMERA_OK} if the method succeeds. captureSequenceId will be filled
+ *             if it is not NULL.</li>
+ *         <li>{@link ACAMERA_ERROR_INVALID_PARAMETER} if session is NULL.</li>
+ *         <li>{@link ACAMERA_ERROR_SESSION_CLOSED} if the capture session has been closed</li>
+ *         <li>{@link ACAMERA_ERROR_CAMERA_DISCONNECTED} if the camera device is closed</li>
+ *         <li>{@link ACAMERA_ERROR_CAMERA_DEVICE} if the camera device encounters fatal error</li>
+ *         <li>{@link ACAMERA_ERROR_CAMERA_SERVICE} if the camera service encounters fatal error</li>
+ *         <li>{@link ACAMERA_ERROR_UNKNOWN} if the method fails for some other reasons</li></ul>
+ */
+camera_status_t ACameraCaptureSession_abortCaptures(ACameraCaptureSession* session);
+
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _NDK_CAMERA_CAPTURE_SESSION_H
+
+/** @} */
diff --git a/include/camera/ndk/NdkCameraDevice.h b/include/camera/ndk/NdkCameraDevice.h
new file mode 100644
index 0000000..9011cb6
--- /dev/null
+++ b/include/camera/ndk/NdkCameraDevice.h
@@ -0,0 +1,668 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @addtogroup Camera
+ * @{
+ */
+
+/**
+ * @file NdkCameraDevice.h
+ */
+
+/*
+ * This file defines an NDK API.
+ * Do not remove methods.
+ * Do not change method signatures.
+ * Do not change the value of constants.
+ * Do not change the size of any of the classes defined in here.
+ * Do not reference types that are not part of the NDK.
+ * Do not #include files that aren't part of the NDK.
+ */
+
+#include <android/native_window.h>
+#include "NdkCameraError.h"
+#include "NdkCaptureRequest.h"
+#include "NdkCameraCaptureSession.h"
+
+#ifndef _NDK_CAMERA_DEVICE_H
+#define _NDK_CAMERA_DEVICE_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * ACameraDevice is opaque type that provides access to a camera device.
+ *
+ * A pointer can be obtained using {@link ACameraManager_openCamera} method.
+ */
+typedef struct ACameraDevice ACameraDevice;
+
+/// Enum for ACameraDevice_ErrorStateCallback error code
+enum {
+    /**
+     * The camera device is in use already.
+     */
+    ERROR_CAMERA_IN_USE = 1,
+
+    /**
+     * The system-wide limit for number of open cameras or camera resources has
+     * been reached, and more camera devices cannot be opened until previous
+     * instances are closed.
+     */
+    ERROR_MAX_CAMERAS_IN_USE = 2,
+
+    /**
+     * The camera is disabled due to a device policy, and cannot be opened.
+     */
+    ERROR_CAMERA_DISABLED = 3,
+
+    /**
+     * The camera device has encountered a fatal error.
+     * <p>The camera device needs to be re-opened to be used again.</p>
+     */
+    ERROR_CAMERA_DEVICE = 4,
+
+    /**
+     * The camera service has encountered a fatal error.
+     * <p>The Android device may need to be shut down and restarted to restore
+     * camera function, or there may be a persistent hardware problem.
+     * An attempt at recovery may be possible by closing the
+     * CameraDevice and the CameraManager, and trying to acquire all resources
+     * again from scratch.</p>
+     */
+    ERROR_CAMERA_SERVICE = 5
+};
+
+/**
+ * Camera device state callbacks to be used in {@link ACameraDevice_stateCallbacks}.
+ *
+ * @param context The optional context in {@link ACameraDevice_stateCallbacks} will be
+ *                passed to this callback.
+ * @param device The {@link ACameraDevice} that is being disconnected.
+ */
+typedef void (*ACameraDevice_StateCallback)(void* context, ACameraDevice* device);
+
+/**
+ * Camera device error state callbacks to be used in {@link ACameraDevice_stateCallbacks}.
+ *
+ * @param context The optional context in {@link ACameraDevice_stateCallbacks} will be
+ *                passed to this callback.
+ * @param device The {@link ACameraDevice} that is being disconnected.
+ * @param error The error code describes the cause of this error callback. See the folowing
+ *              links for more detail.
+ *
+ * @see ERROR_CAMERA_IN_USE
+ * @see ERROR_MAX_CAMERAS_IN_USE
+ * @see ERROR_CAMERA_DISABLED
+ * @see ERROR_CAMERA_DEVICE
+ * @see ERROR_CAMERA_SERVICE
+ */
+typedef void (*ACameraDevice_ErrorStateCallback)(void* context, ACameraDevice* device, int error);
+
+typedef struct ACameraDevice_StateCallbacks {
+    /// optional application context.
+    void*                             context;
+
+    /**
+     * The function is  called when a camera device is no longer available for use.
+     *
+     * <p>Any attempt to call API methods on this ACameraDevice will return
+     * {@link ACAMERA_ERROR_CAMERA_DISCONNECTED}. The disconnection could be due to a
+     * change in security policy or permissions; the physical disconnection
+     * of a removable camera device; or the camera being needed for a
+     * higher-priority camera API client.</p>
+     *
+     * <p>Application should clean up the camera with {@link ACameraDevice_close} after
+     * this happens, as it is not recoverable until the camera can be opened
+     * again.</p>
+     *
+     */
+    ACameraDevice_StateCallback       onDisconnected;
+
+    /**
+     * The function called when a camera device has encountered a serious error.
+     *
+     * <p>This indicates a failure of the camera device or camera service in some way.
+     * Any attempt to call API methods on this ACameraDevice in the future will return
+     * {@link ACAMERA_ERROR_CAMERA_DISCONNECTED}.</p>
+     *
+     * <p>There may still be capture completion or camera stream callbacks that will be called
+     * after this error is received.</p>
+     *
+     * <p>Application should clean up the camera with {@link ACameraDevice_close} after this
+     * happens. Further attempts at recovery are error-code specific.</p>
+     *
+     */
+    ACameraDevice_ErrorStateCallback  onError;
+} ACameraDevice_stateCallbacks;
+
+/**
+ * Close the connection and free this ACameraDevice synchronously. Access to the ACameraDevice
+ * after calling this method will cause a crash.
+ *
+ * <p>After this call, all calls to the active ACameraCaptureSession associated to this
+ * ACameraDevice will return {@link ACAMERA_ERROR_SESSION_CLOSED} except for calls to
+ * {@link ACameraCaptureSession_close}.</p>
+ *
+ * <p>This method will stop all repeating captures sent via
+ * {@link ACameraCaptureSession_setRepeatingRequest} and block until all capture requests sent via
+ * {@link ACameraCaptureSession_capture} is complete. Once the method returns, the camera device
+ * will be removed from memory and access to the closed camera device pointer will cause a crash.</p>
+ *
+ * @param device the camera device to be closed
+ *
+ * @return <ul>
+ *         <li>{@link ACAMERA_OK} if the method call succeeds.</li>
+ *         <li>{@link ACAMERA_ERROR_INVALID_PARAMETER} if device is NULL.</li></ul>
+ */
+camera_status_t ACameraDevice_close(ACameraDevice* device);
+
+/**
+ * Return the camera id associated with this camera device.
+ *
+ * @param device the camera device to be closed
+ *
+ * @return camera ID string. The returned string is managed by framework and should not be
+ * delete/free by the application. Also the returned string must not be used after the device
+ * has been closed.
+ */
+const char* ACameraDevice_getId(const ACameraDevice* device);
+
+typedef enum {
+    /**
+     * Create a request suitable for a camera preview window. Specifically, this
+     * means that high frame rate is given priority over the highest-quality
+     * post-processing. These requests would normally be used with the
+     * {@link ACameraCaptureSession_setRepeatingRequest} method.
+     * This template is guaranteed to be supported on all camera devices.
+     *
+     * @see ACameraDevice_createCaptureRequest
+     */
+    TEMPLATE_PREVIEW = 1,
+
+    /**
+     * Create a request suitable for still image capture. Specifically, this
+     * means prioritizing image quality over frame rate. These requests would
+     * commonly be used with the {@link ACameraCaptureSession_capture} method.
+     * This template is guaranteed to be supported on all camera devices.
+     *
+     * @see ACameraDevice_createCaptureRequest
+     */
+    TEMPLATE_STILL_CAPTURE = 2,
+
+    /**
+     * Create a request suitable for video recording. Specifically, this means
+     * that a stable frame rate is used, and post-processing is set for
+     * recording quality. These requests would commonly be used with the
+     * {@link ACameraCaptureSession_setRepeatingRequest} method.
+     * This template is guaranteed to be supported on all camera devices.
+     *
+     * @see ACameraDevice_createCaptureRequest
+     */
+    TEMPLATE_RECORD = 3,
+
+    /**
+     * Create a request suitable for still image capture while recording
+     * video. Specifically, this means maximizing image quality without
+     * disrupting the ongoing recording. These requests would commonly be used
+     * with the {@link ACameraCaptureSession_capture} method while a request based on
+     * {@link TEMPLATE_RECORD} is is in use with {@link ACameraCaptureSession_setRepeatingRequest}.
+     * This template is guaranteed to be supported on all camera devices.
+     *
+     * @see ACameraDevice_createCaptureRequest
+     */
+    TEMPLATE_VIDEO_SNAPSHOT = 4,
+
+    /**
+     * Create a request suitable for zero shutter lag still capture. This means
+     * means maximizing image quality without compromising preview frame rate.
+     * AE/AWB/AF should be on auto mode.
+     *
+     * @see ACameraDevice_createCaptureRequest
+     */
+    TEMPLATE_ZERO_SHUTTER_LAG = 5,
+
+    /**
+     * A basic template for direct application control of capture
+     * parameters. All automatic control is disabled (auto-exposure, auto-white
+     * balance, auto-focus), and post-processing parameters are set to preview
+     * quality. The manual capture parameters (exposure, sensitivity, and so on)
+     * are set to reasonable defaults, but should be overriden by the
+     * application depending on the intended use case.
+     * This template is guaranteed to be supported on camera devices that support the
+     * {@link ACAMERA_REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR} capability.
+     *
+     * @see ACameraDevice_createCaptureRequest
+     */
+    TEMPLATE_MANUAL = 6,
+} ACameraDevice_request_template;
+
+/**
+ * Create a ACaptureRequest for capturing images, initialized with template
+ * for a target use case.
+ *
+ * <p>The settings are chosen to be the best options for this camera device,
+ * so it is not recommended to reuse the same request for a different camera device.</p>
+ *
+ * @param device the camera device of interest
+ * @param templateId the type of capture request to be created.
+ *        See {@link ACameraDevice_request_template}.
+ * @param request the output request will be stored here if the method call succeeds.
+ *
+ * @return <ul>
+ *         <li>{@link ACAMERA_OK} if the method call succeeds. The created capture request will be
+ *                                filled in request argument.</li>
+ *         <li>{@link ACAMERA_ERROR_INVALID_PARAMETER} if device or request is NULL, templateId
+ *                                is undefined or camera device does not support requested template.
+ *                                </li>
+ *         <li>{@link ACAMERA_ERROR_CAMERA_DISCONNECTED} if the camera device is closed.</li>
+ *         <li>{@link ACAMERA_ERROR_CAMERA_DEVICE} if the camera device encounters fatal error.</li>
+ *         <li>{@link ACAMERA_ERROR_CAMERA_SERVICE} if the camera service encounters fatal error.</li>
+ *         <li>{@link ACAMERA_ERROR_UNKNOWN} if the method fails for some other reasons.</li></ul>
+ *
+ * @see TEMPLATE_PREVIEW
+ * @see TEMPLATE_RECORD
+ * @see TEMPLATE_STILL_CAPTURE
+ * @see TEMPLATE_VIDEO_SNAPSHOT
+ * @see TEMPLATE_MANUAL
+ */
+camera_status_t ACameraDevice_createCaptureRequest(
+        const ACameraDevice* device, ACameraDevice_request_template templateId,
+        /*out*/ACaptureRequest** request);
+
+
+typedef struct ACaptureSessionOutputContainer ACaptureSessionOutputContainer;
+
+typedef struct ACaptureSessionOutput ACaptureSessionOutput;
+
+/**
+ * Create a capture session output container.
+ *
+ * <p>The container is used in {@link ACameraDevice_createCaptureSession} method to create a capture
+ * session. Use {@link ACaptureSessionOutputContainer_free} to free the container and its memory
+ * after application no longer needs the ACaptureSessionOutputContainer.</p>
+ *
+ * @param container the output {@link ACaptureSessionOutputContainer} will be stored here if the
+ *                  method call succeeds.
+ *
+ * @return <ul>
+ *         <li>{@link ACAMERA_OK} if the method call succeeds. The created container will be
+ *                                filled in container argument.</li>
+ *         <li>{@link ACAMERA_ERROR_INVALID_PARAMETER} if container is NULL.</li></ul>
+ */
+camera_status_t ACaptureSessionOutputContainer_create(
+        /*out*/ACaptureSessionOutputContainer** container);
+
+/**
+ * Free a capture session output container.
+ *
+ * @param container the {@link ACaptureSessionOutputContainer} to be freed.
+ *
+ * @see ACaptureSessionOutputContainer_create
+ */
+void            ACaptureSessionOutputContainer_free(ACaptureSessionOutputContainer* container);
+
+/**
+ * Create a ACaptureSessionOutput object.
+ *
+ * <p>The ACaptureSessionOutput is used in {@link ACaptureSessionOutputContainer_add} method to add
+ * an output {@link ANativeWindow} to ACaptureSessionOutputContainer. Use
+ * {@link ACaptureSessionOutput_free} to free the object and its memory after application no longer
+ * needs the {@link ACaptureSessionOutput}.</p>
+ *
+ * @param anw the {@link ANativeWindow} to be associated with the {@link ACaptureSessionOutput}
+ * @param output the output {@link ACaptureSessionOutput} will be stored here if the
+ *                  method call succeeds.
+ *
+ * @return <ul>
+ *         <li>{@link ACAMERA_OK} if the method call succeeds. The created container will be
+ *                                filled in the output argument.</li>
+ *         <li>{@link ACAMERA_ERROR_INVALID_PARAMETER} if anw or output is NULL.</li></ul>
+ *
+ * @see ACaptureSessionOutputContainer_add
+ */
+camera_status_t ACaptureSessionOutput_create(
+        ANativeWindow* anw, /*out*/ACaptureSessionOutput** output);
+
+/**
+ * Free a ACaptureSessionOutput object.
+ *
+ * @param output the {@link ACaptureSessionOutput} to be freed.
+ *
+ * @see ACaptureSessionOutput_create
+ */
+void            ACaptureSessionOutput_free(ACaptureSessionOutput* output);
+
+/**
+ * Add an {@link ACaptureSessionOutput} object to {@link ACaptureSessionOutputContainer}.
+ *
+ * @param container the {@link ACaptureSessionOutputContainer} of interest.
+ * @param output the output {@link ACaptureSessionOutput} to be added to container.
+ *
+ * @return <ul>
+ *         <li>{@link ACAMERA_OK} if the method call succeeds.</li>
+ *         <li>{@link ACAMERA_ERROR_INVALID_PARAMETER} if container or output is NULL.</li></ul>
+ */
+camera_status_t ACaptureSessionOutputContainer_add(
+        ACaptureSessionOutputContainer* container, const ACaptureSessionOutput* output);
+
+/**
+ * Remove an {@link ACaptureSessionOutput} object from {@link ACaptureSessionOutputContainer}.
+ *
+ * <p>This method has no effect if the ACaptureSessionOutput does not exist in
+ * ACaptureSessionOutputContainer.</p>
+ *
+ * @param container the {@link ACaptureSessionOutputContainer} of interest.
+ * @param output the output {@link ACaptureSessionOutput} to be removed from container.
+ *
+ * @return <ul>
+ *         <li>{@link ACAMERA_OK} if the method call succeeds.</li>
+ *         <li>{@link ACAMERA_ERROR_INVALID_PARAMETER} if container or output is NULL.</li></ul>
+ */
+camera_status_t ACaptureSessionOutputContainer_remove(
+        ACaptureSessionOutputContainer* container, const ACaptureSessionOutput* output);
+
+/**
+ * Create a new camera capture session by providing the target output set of {@link ANativeWindow}
+ * to the camera device.
+ *
+ * <p>If there is a preexisting session, the previous session will be closed
+ * automatically. However, app still needs to call {@link ACameraCaptureSession_close} on previous
+ * session. Otherwise the resources held by previous session will NOT be freed.</p>
+ *
+ * <p>The active capture session determines the set of potential output {@link ANativeWindow}s for
+ * the camera device for each capture request. A given request may use all
+ * or only some of the outputs. Once the ACameraCaptureSession is created, requests can be
+ * submitted with {@link ACameraCaptureSession_capture} or
+ * {@link ACameraCaptureSession_setRepeatingRequest}.</p>
+ *
+ * <p>Often the {@link ANativeWindow} used with this method can be obtained from a <a href=
+ * "http://developer.android.com/reference/android/view/Surface.html">Surface</a> java object by
+ * {@link ANativeWindow_fromSurface} NDK method. Surfaces or ANativeWindow suitable for inclusion as a camera
+ * output can be created for various use cases and targets:</p>
+ *
+ * <ul>
+ *
+ * <li>For drawing to a
+ *   <a href="http://developer.android.com/reference/android/view/SurfaceView.html">SurfaceView</a>:
+ *   Once the SurfaceView's Surface is created, set the size
+ *   of the Surface with
+ *   <a href="http://developer.android.com/reference/android/view/SurfaceHolder.html#setFixedSize(int, int)">
+ *    android.view.SurfaceHolder\#setFixedSize</a> to be one of the PRIVATE output sizes
+ *   returned by {@link ACAMERA_SCALER_AVAILABLE_STREAM_CONFIGURATIONS}
+ *   and then obtain the Surface by calling <a href=
+ *   "http://developer.android.com/reference/android/view/SurfaceHolder.html#getSurface()">
+ *   android.view.SurfaceHolder\#getSurface</a>. If the size is not set by the application, it will
+ *   be rounded to the nearest supported size less than 1080p, by the camera device.</li>
+ *
+ * <li>For accessing through an OpenGL texture via a <a href=
+ *   "http://developer.android.com/reference/android/graphics/SurfaceTexture.html">SurfaceTexture</a>:
+ *   Set the size of the SurfaceTexture with <a href=
+ *   "http://developer.android.com/reference/android/graphics/SurfaceTexture.html#setDefaultBufferSize(int, int)">
+ *   setDefaultBufferSize</a> to be one of the PRIVATE output sizes
+ *   returned by {@link ACAMERA_SCALER_AVAILABLE_STREAM_CONFIGURATIONS}
+ *   before creating a Surface from the SurfaceTexture with <a href=
+ *   "http://developer.android.com/reference/android/view/Surface.html#Surface(android.graphics.SurfaceTexture)">
+ *   Surface\#Surface(SurfaceTextrue)</a>. If the size is not set by the application, it will be set to be the
+ *   smallest supported size less than 1080p, by the camera device.</li>
+ *
+ * <li>For recording with <a href=
+ *     "http://developer.android.com/reference/android/media/MediaCodec.html">
+ *     MediaCodec</a>: Call
+ *   <a href=
+ *     "http://developer.android.com/reference/android/media/MediaCodec.html#createInputSurface()">
+ *     android.media.MediaCodec\#createInputSurface</a> after configuring
+ *   the media codec to use one of the PRIVATE output sizes
+ *   returned by {@link ACAMERA_SCALER_AVAILABLE_STREAM_CONFIGURATIONS}.
+ *   </li>
+ *
+ * <li>For recording with <a href=
+ *    "http://developer.android.com/reference/android/media/MediaRecorder.html">
+ *    MediaRecorder</a>: Call
+ *   <a href="http://developer.android.com/reference/android/media/MediaRecorder.html#getSurface()">
+ *    android.media.MediaRecorder\#getSurface</a> after configuring the media recorder to use
+ *   one of the PRIVATE output sizes returned by
+ *   {@link ACAMERA_SCALER_AVAILABLE_STREAM_CONFIGURATIONS}, or configuring it to use one of the supported
+ *   <a href="http://developer.android.com/reference/android/media/CamcorderProfile.html">
+ *    CamcorderProfiles</a>.</li>
+ *
+ * <li>For efficient YUV processing with <a href=
+ *   "http://developer.android.com/reference/android/renderscript/package-summary.html">
+ *   RenderScript</a>:
+ *   Create a RenderScript
+ *   <a href="http://developer.android.com/reference/android/renderscript/Allocation.html">
+ *   Allocation</a> with a supported YUV
+ *   type, the IO_INPUT flag, and one of the YUV output sizes returned by
+ *   {@link ACAMERA_SCALER_AVAILABLE_STREAM_CONFIGURATIONS},
+ *   Then obtain the Surface with
+ *   <a href="http://developer.android.com/reference/android/renderscript/Allocation.html#getSurface()">
+ *   Allocation#getSurface}</a>.</li>
+ *
+ * <li>For access to RAW, uncompressed YUV, or compressed JPEG data in the application: Create an
+ *   {@link AImageReader} object using the {@link AImageReader_new} method with one of the supported
+ *   output formats given by {@link ACAMERA_SCALER_AVAILABLE_STREAM_CONFIGURATIONS}. Then obtain a
+ *   ANativeWindow from it with {@link AImageReader_getWindow}.
+ *   If the AImageReader size is not set to a supported size, it will be rounded to a supported
+ *   size less than 1080p by the camera device.
+ *   </li>
+ *
+ * </ul>
+ *
+ * <p>The camera device will query each ANativeWindow's size and formats upon this
+ * call, so they must be set to a valid setting at this time.</p>
+ *
+ * <p>It can take several hundred milliseconds for the session's configuration to complete,
+ * since camera hardware may need to be powered on or reconfigured.</p>
+ *
+ * <p>If a prior ACameraCaptureSession already exists when this method is called, the previous
+ * session will no longer be able to accept new capture requests and will be closed. Any
+ * in-progress capture requests made on the prior session will be completed before it's closed.
+ * To minimize the transition time,
+ * the ACameraCaptureSession_abortCaptures method can be used to discard the remaining
+ * requests for the prior capture session before a new one is created. Note that once the new
+ * session is created, the old one can no longer have its captures aborted.</p>
+ *
+ * <p>Using larger resolution outputs, or more outputs, can result in slower
+ * output rate from the device.</p>
+ *
+ * <p>Configuring a session with an empty list will close the current session, if
+ * any. This can be used to release the current session's target surfaces for another use.</p>
+ *
+ * <p>While any of the sizes from {@link ACAMERA_SCALER_AVAILABLE_STREAM_CONFIGURATIONS} can be used when
+ * a single output stream is configured, a given camera device may not be able to support all
+ * combination of sizes, formats, and targets when multiple outputs are configured at once.  The
+ * tables below list the maximum guaranteed resolutions for combinations of streams and targets,
+ * given the capabilities of the camera device.</p>
+ *
+ * <p>If an application tries to create a session using a set of targets that exceed the limits
+ * described in the below tables, one of three possibilities may occur. First, the session may
+ * be successfully created and work normally. Second, the session may be successfully created,
+ * but the camera device won't meet the frame rate guarantees as described in
+ * {@link ACAMERA_SCALER_AVAILABLE_MIN_FRAME_DURATIONS}. Or third, if the output set
+ * cannot be used at all, session creation will fail entirely, with
+ * {@link ACAMERA_ERROR_STREAM_CONFIGURE_FAIL} being returned.</p>
+ *
+ * <p>For the type column `PRIV` refers to output format {@link AIMAGE_FORMAT_PRIVATE},
+ * `YUV` refers to output format {@link AIMAGE_FORMAT_YUV_420_888},
+ * `JPEG` refers to output format {@link AIMAGE_FORMAT_JPEG},
+ * and `RAW` refers to output format {@link AIMAGE_FORMAT_RAW16}
+ *
+ *
+ * <p>For the maximum size column, `PREVIEW` refers to the best size match to the
+ * device's screen resolution, or to 1080p `(1920x1080)`, whichever is
+ * smaller. `RECORD` refers to the camera device's maximum supported recording resolution,
+ * as determined by <a href="http://developer.android.com/reference/android/media/CamcorderProfile.html">
+ * android.media.CamcorderProfiles</a>. And `MAXIMUM` refers to the
+ * camera device's maximum output resolution for that format or target from
+ * {@link ACAMERA_SCALER_AVAILABLE_STREAM_CONFIGURATIONS}.</p>
+ *
+ * <p>To use these tables, determine the number and the formats/targets of outputs needed, and
+ * find the row(s) of the table with those targets. The sizes indicate the maximum set of sizes
+ * that can be used; it is guaranteed that for those targets, the listed sizes and anything
+ * smaller from the list given by {@link ACAMERA_SCALER_AVAILABLE_STREAM_CONFIGURATIONS} can be
+ * successfully used to create a session.  For example, if a row indicates that a 8 megapixel
+ * (MP) YUV_420_888 output can be used together with a 2 MP `PRIV` output, then a session
+ * can be created with targets `[8 MP YUV, 2 MP PRIV]` or targets `[2 MP YUV, 2 MP PRIV]`;
+ * but a session with targets `[8 MP YUV, 4 MP PRIV]`, targets `[4 MP YUV, 4 MP PRIV]`,
+ * or targets `[8 MP PRIV, 2 MP YUV]` would not be guaranteed to work, unless
+ * some other row of the table lists such a combination.</p>
+ *
+ * <p>Legacy devices ({@link ACAMERA_INFO_SUPPORTED_HARDWARE_LEVEL}
+ * `== `{@link ACAMERA_INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY LEGACY}) support at
+ * least the following stream combinations:
+ *
+ * <table>
+ * <tr><th colspan="7">LEGACY-level guaranteed configurations</th></tr>
+ * <tr> <th colspan="2" id="rb">Target 1</th> <th colspan="2" id="rb">Target 2</th>  <th colspan="2" id="rb">Target 3</th> <th rowspan="2">Sample use case(s)</th> </tr>
+ * <tr> <th>Type</th><th id="rb">Max size</th> <th>Type</th><th id="rb">Max size</th> <th>Type</th><th id="rb">Max size</th></tr>
+ * <tr> <td>`PRIV`</td><td id="rb">`MAXIMUM`</td> <td colspan="2" id="rb"></td> <td colspan="2" id="rb"></td> <td>Simple preview, GPU video processing, or no-preview video recording.</td> </tr>
+ * <tr> <td>`JPEG`</td><td id="rb">`MAXIMUM`</td> <td colspan="2" id="rb"></td> <td colspan="2" id="rb"></td> <td>No-viewfinder still image capture.</td> </tr>
+ * <tr> <td>`YUV `</td><td id="rb">`MAXIMUM`</td> <td colspan="2" id="rb"></td> <td colspan="2" id="rb"></td> <td>In-application video/image processing.</td> </tr>
+ * <tr> <td>`PRIV`</td><td id="rb">`PREVIEW`</td> <td>`JPEG`</td><td id="rb">`MAXIMUM`</td> <td colspan="2" id="rb"></td> <td>Standard still imaging.</td> </tr>
+ * <tr> <td>`YUV `</td><td id="rb">`PREVIEW`</td> <td>`JPEG`</td><td id="rb">`MAXIMUM`</td> <td colspan="2" id="rb"></td> <td>In-app processing plus still capture.</td> </tr>
+ * <tr> <td>`PRIV`</td><td id="rb">`PREVIEW`</td> <td>`PRIV`</td><td id="rb">`PREVIEW`</td> <td colspan="2" id="rb"></td> <td>Standard recording.</td> </tr>
+ * <tr> <td>`PRIV`</td><td id="rb">`PREVIEW`</td> <td>`YUV `</td><td id="rb">`PREVIEW`</td> <td colspan="2" id="rb"></td> <td>Preview plus in-app processing.</td> </tr>
+ * <tr> <td>`PRIV`</td><td id="rb">`PREVIEW`</td> <td>`YUV `</td><td id="rb">`PREVIEW`</td> <td>`JPEG`</td><td id="rb">`MAXIMUM`</td> <td>Still capture plus in-app processing.</td> </tr>
+ * </table><br>
+ * </p>
+ *
+ * <p>Limited-level ({@link ACAMERA_INFO_SUPPORTED_HARDWARE_LEVEL}
+ * `== `{@link ACAMERA_INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED LIMITED}) devices
+ * support at least the following stream combinations in addition to those for
+ * {@link ACAMERA_INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY LEGACY} devices:
+ *
+ * <table>
+ * <tr><th colspan="7">LIMITED-level additional guaranteed configurations</th></tr>
+ * <tr><th colspan="2" id="rb">Target 1</th><th colspan="2" id="rb">Target 2</th><th colspan="2" id="rb">Target 3</th> <th rowspan="2">Sample use case(s)</th> </tr>
+ * <tr><th>Type</th><th id="rb">Max size</th><th>Type</th><th id="rb">Max size</th><th>Type</th><th id="rb">Max size</th></tr>
+ * <tr> <td>`PRIV`</td><td id="rb">`PREVIEW`</td> <td>`PRIV`</td><td id="rb">`RECORD `</td> <td colspan="2" id="rb"></td> <td>High-resolution video recording with preview.</td> </tr>
+ * <tr> <td>`PRIV`</td><td id="rb">`PREVIEW`</td> <td>`YUV `</td><td id="rb">`RECORD `</td> <td colspan="2" id="rb"></td> <td>High-resolution in-app video processing with preview.</td> </tr>
+ * <tr> <td>`YUV `</td><td id="rb">`PREVIEW`</td> <td>`YUV `</td><td id="rb">`RECORD `</td> <td colspan="2" id="rb"></td> <td>Two-input in-app video processing.</td> </tr>
+ * <tr> <td>`PRIV`</td><td id="rb">`PREVIEW`</td> <td>`PRIV`</td><td id="rb">`RECORD `</td> <td>`JPEG`</td><td id="rb">`RECORD `</td> <td>High-resolution recording with video snapshot.</td> </tr>
+ * <tr> <td>`PRIV`</td><td id="rb">`PREVIEW`</td> <td>`YUV `</td><td id="rb">`RECORD `</td> <td>`JPEG`</td><td id="rb">`RECORD `</td> <td>High-resolution in-app processing with video snapshot.</td> </tr>
+ * <tr> <td>`YUV `</td><td id="rb">`PREVIEW`</td> <td>`YUV `</td><td id="rb">`PREVIEW`</td> <td>`JPEG`</td><td id="rb">`MAXIMUM`</td> <td>Two-input in-app processing with still capture.</td> </tr>
+ * </table><br>
+ * </p>
+ *
+ * <p>FULL-level ({@link ACAMERA_INFO_SUPPORTED_HARDWARE_LEVEL}
+ * `== `{@link ACAMERA_INFO_SUPPORTED_HARDWARE_LEVEL_FULL FULL}) devices
+ * support at least the following stream combinations in addition to those for
+ * {@link ACAMERA_INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED LIMITED} devices:
+ *
+ * <table>
+ * <tr><th colspan="7">FULL-level additional guaranteed configurations</th></tr>
+ * <tr><th colspan="2" id="rb">Target 1</th><th colspan="2" id="rb">Target 2</th><th colspan="2" id="rb">Target 3</th> <th rowspan="2">Sample use case(s)</th> </tr>
+ * <tr><th>Type</th><th id="rb">Max size</th><th>Type</th><th id="rb">Max size</th><th>Type</th><th id="rb">Max size</th> </tr>
+ * <tr> <td>`PRIV`</td><td id="rb">`PREVIEW`</td> <td>`PRIV`</td><td id="rb">`MAXIMUM`</td> <td colspan="2" id="rb"></td> <td>Maximum-resolution GPU processing with preview.</td> </tr>
+ * <tr> <td>`PRIV`</td><td id="rb">`PREVIEW`</td> <td>`YUV `</td><td id="rb">`MAXIMUM`</td> <td colspan="2" id="rb"></td> <td>Maximum-resolution in-app processing with preview.</td> </tr>
+ * <tr> <td>`YUV `</td><td id="rb">`PREVIEW`</td> <td>`YUV `</td><td id="rb">`MAXIMUM`</td> <td colspan="2" id="rb"></td> <td>Maximum-resolution two-input in-app processsing.</td> </tr>
+ * <tr> <td>`PRIV`</td><td id="rb">`PREVIEW`</td> <td>`PRIV`</td><td id="rb">`PREVIEW`</td> <td>`JPEG`</td><td id="rb">`MAXIMUM`</td> <td>Video recording with maximum-size video snapshot</td> </tr>
+ * <tr> <td>`YUV `</td><td id="rb">`640x480`</td> <td>`PRIV`</td><td id="rb">`PREVIEW`</td> <td>`YUV `</td><td id="rb">`MAXIMUM`</td> <td>Standard video recording plus maximum-resolution in-app processing.</td> </tr>
+ * <tr> <td>`YUV `</td><td id="rb">`640x480`</td> <td>`YUV `</td><td id="rb">`PREVIEW`</td> <td>`YUV `</td><td id="rb">`MAXIMUM`</td> <td>Preview plus two-input maximum-resolution in-app processing.</td> </tr>
+ * </table><br>
+ * </p>
+ *
+ * <p>RAW-capability ({@link ACAMERA_REQUEST_AVAILABLE_CAPABILITIES} includes
+ * {@link ACAMERA_REQUEST_AVAILABLE_CAPABILITIES_RAW RAW}) devices additionally support
+ * at least the following stream combinations on both
+ * {@link ACAMERA_INFO_SUPPORTED_HARDWARE_LEVEL_FULL FULL} and
+ * {@link ACAMERA_INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED LIMITED} devices:
+ *
+ * <table>
+ * <tr><th colspan="7">RAW-capability additional guaranteed configurations</th></tr>
+ * <tr><th colspan="2" id="rb">Target 1</th><th colspan="2" id="rb">Target 2</th><th colspan="2" id="rb">Target 3</th> <th rowspan="2">Sample use case(s)</th> </tr>
+ * <tr><th>Type</th><th id="rb">Max size</th><th>Type</th><th id="rb">Max size</th><th>Type</th><th id="rb">Max size</th> </tr>
+ * <tr> <td>`RAW `</td><td id="rb">`MAXIMUM`</td> <td colspan="2" id="rb"></td> <td colspan="2" id="rb"></td> <td>No-preview DNG capture.</td> </tr>
+ * <tr> <td>`PRIV`</td><td id="rb">`PREVIEW`</td> <td>`RAW `</td><td id="rb">`MAXIMUM`</td> <td colspan="2" id="rb"></td> <td>Standard DNG capture.</td> </tr>
+ * <tr> <td>`YUV `</td><td id="rb">`PREVIEW`</td> <td>`RAW `</td><td id="rb">`MAXIMUM`</td> <td colspan="2" id="rb"></td> <td>In-app processing plus DNG capture.</td> </tr>
+ * <tr> <td>`PRIV`</td><td id="rb">`PREVIEW`</td> <td>`PRIV`</td><td id="rb">`PREVIEW`</td> <td>`RAW `</td><td id="rb">`MAXIMUM`</td> <td>Video recording with DNG capture.</td> </tr>
+ * <tr> <td>`PRIV`</td><td id="rb">`PREVIEW`</td> <td>`YUV `</td><td id="rb">`PREVIEW`</td> <td>`RAW `</td><td id="rb">`MAXIMUM`</td> <td>Preview with in-app processing and DNG capture.</td> </tr>
+ * <tr> <td>`YUV `</td><td id="rb">`PREVIEW`</td> <td>`YUV `</td><td id="rb">`PREVIEW`</td> <td>`RAW `</td><td id="rb">`MAXIMUM`</td> <td>Two-input in-app processing plus DNG capture.</td> </tr>
+ * <tr> <td>`PRIV`</td><td id="rb">`PREVIEW`</td> <td>`JPEG`</td><td id="rb">`MAXIMUM`</td> <td>`RAW `</td><td id="rb">`MAXIMUM`</td> <td>Still capture with simultaneous JPEG and DNG.</td> </tr>
+ * <tr> <td>`YUV `</td><td id="rb">`PREVIEW`</td> <td>`JPEG`</td><td id="rb">`MAXIMUM`</td> <td>`RAW `</td><td id="rb">`MAXIMUM`</td> <td>In-app processing with simultaneous JPEG and DNG.</td> </tr>
+ * </table><br>
+ * </p>
+ *
+ * <p>BURST-capability ({@link ACAMERA_REQUEST_AVAILABLE_CAPABILITIES} includes
+ * {@link ACAMERA_REQUEST_AVAILABLE_CAPABILITIES_BURST_CAPTURE BURST_CAPTURE}) devices
+ * support at least the below stream combinations in addition to those for
+ * {@link ACAMERA_INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED LIMITED} devices. Note that all
+ * FULL-level devices support the BURST capability, and the below list is a strict subset of the
+ * list for FULL-level devices, so this table is only relevant for LIMITED-level devices that
+ * support the BURST_CAPTURE capability.
+ *
+ * <table>
+ * <tr><th colspan="5">BURST-capability additional guaranteed configurations</th></tr>
+ * <tr><th colspan="2" id="rb">Target 1</th><th colspan="2" id="rb">Target 2</th><th rowspan="2">Sample use case(s)</th> </tr>
+ * <tr><th>Type</th><th id="rb">Max size</th><th>Type</th><th id="rb">Max size</th> </tr>
+ * <tr> <td>`PRIV`</td><td id="rb">`PREVIEW`</td> <td>`PRIV`</td><td id="rb">`MAXIMUM`</td> <td>Maximum-resolution GPU processing with preview.</td> </tr>
+ * <tr> <td>`PRIV`</td><td id="rb">`PREVIEW`</td> <td>`YUV `</td><td id="rb">`MAXIMUM`</td> <td>Maximum-resolution in-app processing with preview.</td> </tr>
+ * <tr> <td>`YUV `</td><td id="rb">`PREVIEW`</td> <td>`YUV `</td><td id="rb">`MAXIMUM`</td> <td>Maximum-resolution two-input in-app processsing.</td> </tr>
+ * </table><br>
+ * </p>
+ *
+ * <p>LEVEL-3 ({@link ACAMERA_INFO_SUPPORTED_HARDWARE_LEVEL}
+ * `== `{@link ACAMERA_INFO_SUPPORTED_HARDWARE_LEVEL_3 LEVEL_3})
+ * support at least the following stream combinations in addition to the combinations for
+ * {@link ACAMERA_INFO_SUPPORTED_HARDWARE_LEVEL_FULL FULL} and for
+ * RAW capability ({@link ACAMERA_REQUEST_AVAILABLE_CAPABILITIES} includes
+ * {@link ACAMERA_REQUEST_AVAILABLE_CAPABILITIES_RAW RAW}):
+ *
+ * <table>
+ * <tr><th colspan="11">LEVEL-3 additional guaranteed configurations</th></tr>
+ * <tr><th colspan="2" id="rb">Target 1</th><th colspan="2" id="rb">Target 2</th><th colspan="2" id="rb">Target 3</th><th colspan="2" id="rb">Target 4</th><th rowspan="2">Sample use case(s)</th> </tr>
+ * <tr><th>Type</th><th id="rb">Max size</th><th>Type</th><th id="rb">Max size</th><th>Type</th><th id="rb">Max size</th><th>Type</th><th id="rb">Max size</th> </tr>
+ * <tr> <td>`PRIV`</td><td id="rb">`PREVIEW`</td> <td>`PRIV`</td><td id="rb">`640x480`</td> <td>`YUV`</td><td id="rb">`MAXIMUM`</td> <td>`RAW`</td><td id="rb">`MAXIMUM`</td> <td>In-app viewfinder analysis with dynamic selection of output format.</td> </tr>
+ * <tr> <td>`PRIV`</td><td id="rb">`PREVIEW`</td> <td>`PRIV`</td><td id="rb">`640x480`</td> <td>`JPEG`</td><td id="rb">`MAXIMUM`</td> <td>`RAW`</td><td id="rb">`MAXIMUM`</td> <td>In-app viewfinder analysis with dynamic selection of output format.</td> </tr>
+ * </table><br>
+ * </p>
+ *
+ * <p>Since the capabilities of camera devices vary greatly, a given camera device may support
+ * target combinations with sizes outside of these guarantees, but this can only be tested for
+ * by attempting to create a session with such targets.</p>
+ *
+ * @param device the camera device of interest.
+ * @param outputs the {@link ACaptureSessionOutputContainer} describes all output streams.
+ * @param callbacks the {@link ACameraCaptureSession_stateCallbacks capture session state callbacks}.
+ * @param session the created {@link ACameraCaptureSession} will be filled here if the method call
+ *        succeeds.
+ *
+ * @return <ul>
+ *         <li>{@link ACAMERA_OK} if the method call succeeds. The created capture session will be
+ *                                filled in session argument.</li>
+ *         <li>{@link ACAMERA_ERROR_INVALID_PARAMETER} if any of device, outputs, callbacks or
+ *                                session is NULL.</li>
+ *         <li>{@link ACAMERA_ERROR_CAMERA_DISCONNECTED} if the camera device is closed.</li>
+ *         <li>{@link ACAMERA_ERROR_CAMERA_DEVICE} if the camera device encounters fatal error.</li>
+ *         <li>{@link ACAMERA_ERROR_CAMERA_SERVICE} if the camera service encounters fatal error.</li>
+ *         <li>{@link ACAMERA_ERROR_UNKNOWN} if the method fails for some other reasons.</li></ul>
+ */
+camera_status_t ACameraDevice_createCaptureSession(
+        ACameraDevice* device,
+        const ACaptureSessionOutputContainer*       outputs,
+        const ACameraCaptureSession_stateCallbacks* callbacks,
+        /*out*/ACameraCaptureSession** session);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _NDK_CAMERA_DEVICE_H
+
+/** @} */
+
diff --git a/include/camera/ndk/NdkCameraError.h b/include/camera/ndk/NdkCameraError.h
new file mode 100644
index 0000000..36251fc
--- /dev/null
+++ b/include/camera/ndk/NdkCameraError.h
@@ -0,0 +1,140 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @addtogroup Camera
+ * @{
+ */
+
+/**
+ * @file NdkCameraError.h
+ */
+
+/*
+ * This file defines an NDK API.
+ * Do not remove methods.
+ * Do not change method signatures.
+ * Do not change the value of constants.
+ * Do not change the size of any of the classes defined in here.
+ * Do not reference types that are not part of the NDK.
+ * Do not #include files that aren't part of the NDK.
+ */
+
+#ifndef _NDK_CAMERA_ERROR_H
+#define _NDK_CAMERA_ERROR_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef enum {
+    ACAMERA_OK = 0,
+
+    ACAMERA_ERROR_BASE                  = -10000,
+
+    /**
+     * Camera operation has failed due to an unspecified cause.
+     */
+    ACAMERA_ERROR_UNKNOWN               = ACAMERA_ERROR_BASE,
+
+    /**
+     * Camera operation has failed due to an invalid parameter being passed to the method.
+     */
+    ACAMERA_ERROR_INVALID_PARAMETER     = ACAMERA_ERROR_BASE - 1,
+
+    /**
+     * Camera operation has failed because the camera device has been closed, possibly because a
+     * higher-priority client has taken ownership of the camera device.
+     */
+    ACAMERA_ERROR_CAMERA_DISCONNECTED   = ACAMERA_ERROR_BASE - 2,
+
+    /**
+     * Camera operation has failed due to insufficient memory.
+     */
+    ACAMERA_ERROR_NOT_ENOUGH_MEMORY     = ACAMERA_ERROR_BASE - 3,
+
+    /**
+     * Camera operation has failed due to the requested metadata tag cannot be found in input
+     * {@link ACameraMetadata} or {@link ACaptureRequest}.
+     */
+    ACAMERA_ERROR_METADATA_NOT_FOUND    = ACAMERA_ERROR_BASE - 4,
+
+    /**
+     * Camera operation has failed and the camera device has encountered a fatal error and needs to
+     * be re-opened before it can be used again.
+     */
+    ACAMERA_ERROR_CAMERA_DEVICE         = ACAMERA_ERROR_BASE - 5,
+
+    /**
+     * Camera operation has failed and the camera service has encountered a fatal error.
+     *
+     * <p>The Android device may need to be shut down and restarted to restore
+     * camera function, or there may be a persistent hardware problem.</p>
+     *
+     * <p>An attempt at recovery may be possible by closing the
+     * ACameraDevice and the ACameraManager, and trying to acquire all resources
+     * again from scratch.</p>
+     */
+    ACAMERA_ERROR_CAMERA_SERVICE        = ACAMERA_ERROR_BASE - 6,
+
+    /**
+     * The {@link ACameraCaptureSession} has been closed and cannnot perform any operation other
+     * than {@link ACameraCaptureSession_close}.
+     */
+    ACAMERA_ERROR_SESSION_CLOSED        = ACAMERA_ERROR_BASE - 7,
+
+    /**
+     * Camera operation has failed due to an invalid internal operation. Usually this is due to a
+     * low-level problem that may resolve itself on retry
+     */
+    ACAMERA_ERROR_INVALID_OPERATION     = ACAMERA_ERROR_BASE - 8,
+
+    /**
+     * Camera device does not support the stream configuration provided by application in
+     * {@link ACameraDevice_createCaptureSession}.
+     */
+    ACAMERA_ERROR_STREAM_CONFIGURE_FAIL = ACAMERA_ERROR_BASE - 9,
+
+    /**
+     * Camera device is being used by another higher priority camera API client.
+     */
+    ACAMERA_ERROR_CAMERA_IN_USE         = ACAMERA_ERROR_BASE - 10,
+
+    /**
+     * The system-wide limit for number of open cameras or camera resources has been reached, and
+     * more camera devices cannot be opened until previous instances are closed.
+     */
+    ACAMERA_ERROR_MAX_CAMERA_IN_USE     = ACAMERA_ERROR_BASE - 11,
+
+    /**
+     * The camera is disabled due to a device policy, and cannot be opened.
+     */
+    ACAMERA_ERROR_CAMERA_DISABLED       = ACAMERA_ERROR_BASE - 12,
+
+    /**
+     * The application does not have permission to open camera.
+     */
+    ACAMERA_ERROR_PERMISSION_DENIED     = ACAMERA_ERROR_BASE - 13,
+} camera_status_t;
+
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _NDK_CAMERA_ERROR_H
+
+/** @} */
diff --git a/include/camera/ndk/NdkCameraManager.h b/include/camera/ndk/NdkCameraManager.h
new file mode 100644
index 0000000..9188e94
--- /dev/null
+++ b/include/camera/ndk/NdkCameraManager.h
@@ -0,0 +1,280 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @addtogroup Camera
+ * @{
+ */
+
+/**
+ * @file NdkCameraManager.h
+ */
+
+/*
+ * This file defines an NDK API.
+ * Do not remove methods.
+ * Do not change method signatures.
+ * Do not change the value of constants.
+ * Do not change the size of any of the classes defined in here.
+ * Do not reference types that are not part of the NDK.
+ * Do not #include files that aren't part of the NDK.
+ */
+
+#ifndef _NDK_CAMERA_MANAGER_H
+#define _NDK_CAMERA_MANAGER_H
+
+#include "NdkCameraError.h"
+#include "NdkCameraMetadata.h"
+#include "NdkCameraDevice.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * ACameraManager is opaque type that provides access to camera service.
+ *
+ * A pointer can be obtained using {@link ACameraManager_create} method.
+ */
+typedef struct ACameraManager ACameraManager;
+
+/**
+ * Create ACameraManager instance.
+ *
+ * <p>The ACameraManager is responsible for
+ * detecting, characterizing, and connecting to {@link ACameraDevice}s.</p>
+ *
+ * <p>The caller must call {@link ACameraManager_delete} to free the resources once it is done
+ * using the ACameraManager instance.</p>
+ *
+ * @return a {@link ACameraManager} instance.
+ *
+ */
+ACameraManager* ACameraManager_create();
+
+/**
+ * <p>Delete the {@link ACameraManager} instance and free its resources. </p>
+ *
+ * @param manager the {@link ACameraManager} instance to be deleted.
+ */
+void ACameraManager_delete(ACameraManager* manager);
+
+/// Struct to hold list of camera devices
+typedef struct ACameraIdList {
+    int numCameras;          ///< Number of connected camera devices
+    const char** cameraIds;  ///< list of identifier of connected camera devices
+} ACameraIdList;
+
+/**
+ * Create a list of currently connected camera devices, including
+ * cameras that may be in use by other camera API clients.
+ *
+ * <p>Non-removable cameras use integers starting at 0 for their
+ * identifiers, while removable cameras have a unique identifier for each
+ * individual device, even if they are the same model.</p>
+ *
+ * <p>ACameraManager_getCameraIdList will allocate and return an {@link ACameraIdList}.
+ * The caller must call {@link ACameraManager_deleteCameraIdList} to free the memory</p>
+ *
+ * @param manager the {@link ACameraManager} of interest
+ * @param cameraIdList the output {@link ACameraIdList} will be filled in here if the method call
+ *        succeeds.
+ *
+ * @return <ul>
+ *         <li>{@link ACAMERA_OK} if the method call succeeds.</li>
+ *         <li>{@link ACAMERA_ERROR_INVALID_PARAMETER} if manager or cameraIdList is NULL.</li>
+ *         <li>{@link ACAMERA_ERROR_CAMERA_DISCONNECTED} if connection to camera service fails.</li>
+ *         <li>{@link ACAMERA_ERROR_NOT_ENOUGH_MEMORY} if allocating memory fails.</li></ul>
+ */
+camera_status_t ACameraManager_getCameraIdList(ACameraManager* manager,
+                                              /*out*/ACameraIdList** cameraIdList);
+
+/**
+ * Delete a list of camera devices allocated via {@link ACameraManager_getCameraIdList}.
+ *
+ * @param cameraIdList the {@link ACameraIdList} to be deleted.
+ */
+void ACameraManager_deleteCameraIdList(ACameraIdList* cameraIdList);
+
+/**
+ * Definition of camera availability callbacks.
+ *
+ * @param context The optional application context provided by user in
+ *                {@link ACameraManager_AvailabilityCallbacks}.
+ * @param cameraId The ID of the camera device whose availability is changing. The memory of this
+ *                 argument is owned by camera framework and will become invalid immediately after
+ *                 this callback returns.
+ */
+typedef void (*ACameraManager_AvailabilityCallback)(void* context, const char* cameraId);
+
+/**
+ * A listener for camera devices becoming available or unavailable to open.
+ *
+ * <p>Cameras become available when they are no longer in use, or when a new
+ * removable camera is connected. They become unavailable when some
+ * application or service starts using a camera, or when a removable camera
+ * is disconnected.</p>
+ *
+ * @see ACameraManager_registerAvailabilityCallback
+ */
+typedef struct ACameraManager_AvailabilityListener {
+    /// Optional application context.
+    void*                               context;
+    /// Called when a camera becomes available
+    ACameraManager_AvailabilityCallback onCameraAvailable;
+    /// Called when a camera becomes unavailable
+    ACameraManager_AvailabilityCallback onCameraUnavailable;
+} ACameraManager_AvailabilityCallbacks;
+
+/**
+ * Register camera availability callbacks.
+ *
+ * <p>onCameraUnavailable will be called whenever a camera device is opened by any camera API client.
+ * Other camera API clients may still be able to open such a camera device, evicting the existing
+ * client if they have higher priority than the existing client of a camera device.
+ * See {@link ACameraManager_openCamera} for more details.</p>
+ *
+ * <p>The callbacks will be called on a dedicated thread shared among all ACameraManager
+ * instances.</p>
+ *
+ * <p>Since this callback will be registered with the camera service, remember to unregister it
+ * once it is no longer needed; otherwise the callback will continue to receive events
+ * indefinitely and it may prevent other resources from being released. Specifically, the
+ * callbacks will be invoked independently of the general activity lifecycle and independently
+ * of the state of individual ACameraManager instances.</p>
+ *
+ * @param manager the {@link ACameraManager} of interest.
+ * @param callback the {@link ACameraManager_AvailabilityCallbacks} to be registered.
+ *
+ * @return <ul>
+ *         <li>{@link ACAMERA_OK} if the method call succeeds.</li>
+ *         <li>{@link ACAMERA_ERROR_INVALID_PARAMETER} if manager or callback is NULL, or
+ *                  {ACameraManager_AvailabilityCallbacks#onCameraAvailable} or
+ *                  {ACameraManager_AvailabilityCallbacks#onCameraUnavailable} is NULL.</li></ul>
+ */
+camera_status_t ACameraManager_registerAvailabilityCallback(
+        ACameraManager* manager, const ACameraManager_AvailabilityCallbacks* callback);
+
+/**
+ * Unregister camera availability callbacks.
+ *
+ * <p>Removing a callback that isn't registered has no effect.</p>
+ *
+ * @param manager the {@link ACameraManager} of interest.
+ * @param callback the {@link ACameraManager_AvailabilityCallbacks} to be unregistered.
+ *
+ * @return <ul>
+ *         <li>{@link ACAMERA_OK} if the method call succeeds.</li>
+ *         <li>{@link ACAMERA_ERROR_INVALID_PARAMETER} if callback,
+ *                  {ACameraManager_AvailabilityCallbacks#onCameraAvailable} or
+ *                  {ACameraManager_AvailabilityCallbacks#onCameraUnavailable} is NULL.</li></ul>
+ */
+camera_status_t ACameraManager_unregisterAvailabilityCallback(
+        ACameraManager* manager, const ACameraManager_AvailabilityCallbacks* callback);
+
+/**
+ * Query the capabilities of a camera device. These capabilities are
+ * immutable for a given camera.
+ *
+ * <p>See {@link ACameraMetadata} document and {@link NdkCameraMetadataTags.h} for more details.</p>
+ *
+ * <p>The caller must call {@link ACameraMetadata_free} to free the memory of the output
+ * characteristics.</p>
+ *
+ * @param manager the {@link ACameraManager} of interest.
+ * @param cameraId the ID string of the camera device of interest.
+ * @param characteristics the output {@link ACameraMetadata} will be filled here if the method call
+ *        succeeeds.
+ *
+ * @return <ul>
+ *         <li>{@link ACAMERA_OK} if the method call succeeds.</li>
+ *         <li>{@link ACAMERA_ERROR_INVALID_PARAMETER} if manager, cameraId, or characteristics
+ *                  is NULL, or cameraId does not match any camera devices connected.</li>
+ *         <li>{@link ACAMERA_ERROR_CAMERA_DISCONNECTED} if connection to camera service fails.</li>
+ *         <li>{@link ACAMERA_ERROR_NOT_ENOUGH_MEMORY} if allocating memory fails.</li>
+ *         <li>{@link ACAMERA_ERROR_UNKNOWN} if the method fails for some other reasons.</li></ul>
+ */
+camera_status_t ACameraManager_getCameraCharacteristics(
+        ACameraManager* manager, const char* cameraId,
+        /*out*/ACameraMetadata** characteristics);
+
+/**
+ * Open a connection to a camera with the given ID. The opened camera device will be
+ * returned in the `device` parameter.
+ *
+ * <p>Use {@link ACameraManager_getCameraIdList} to get the list of available camera
+ * devices. Note that even if an id is listed, open may fail if the device
+ * is disconnected between the calls to {@link ACameraManager_getCameraIdList} and
+ * {@link ACameraManager_openCamera}, or if a higher-priority camera API client begins using the
+ * camera device.</p>
+ *
+ * <p>Devices for which the
+ * {@link ACameraManager_AvailabilityCallbacks#onCameraUnavailable} callback has been called due to
+ * the device being in use by a lower-priority, background camera API client can still potentially
+ * be opened by calling this method when the calling camera API client has a higher priority
+ * than the current camera API client using this device.  In general, if the top, foreground
+ * activity is running within your application process, your process will be given the highest
+ * priority when accessing the camera, and this method will succeed even if the camera device is
+ * in use by another camera API client. Any lower-priority application that loses control of the
+ * camera in this way will receive an
+ * {@link ACameraDevice_stateCallbacks#onDisconnected} callback.</p>
+ *
+ * <p>Once the camera is successfully opened,the ACameraDevice can then be set up
+ * for operation by calling {@link ACameraDevice_createCaptureSession} and
+ * {@link ACameraDevice_createCaptureRequest}.</p>
+ *
+ * <p>If the camera becomes disconnected after this function call returns,
+ * {@link ACameraDevice_stateCallbacks#onDisconnected} with a
+ * ACameraDevice in the disconnected state will be called.</p>
+ *
+ * <p>If the camera runs into error after this function call returns,
+ * {@link ACameraDevice_stateCallbacks#onError} with a
+ * ACameraDevice in the error state will be called.</p>
+ *
+ * @param manager the {@link ACameraManager} of interest.
+ * @param cameraId the ID string of the camera device to be opened.
+ * @param callback the {@link ACameraDevice_StateCallbacks} associated with the opened camera device.
+ * @param device the opened {@link ACameraDevice} will be filled here if the method call succeeds.
+ *
+ * @return <ul>
+ *         <li>{@link ACAMERA_OK} if the method call succeeds.</li>
+ *         <li>{@link ACAMERA_ERROR_INVALID_PARAMETER} if manager, cameraId, callback, or device
+ *                  is NULL, or cameraId does not match any camera devices connected.</li>
+ *         <li>{@link ACAMERA_ERROR_CAMERA_DISCONNECTED} if connection to camera service fails.</li>
+ *         <li>{@link ACAMERA_ERROR_NOT_ENOUGH_MEMORY} if allocating memory fails.</li>
+ *         <li>{@link ACAMERA_ERROR_CAMERA_IN_USE} if camera device is being used by a higher
+ *                   priority camera API client.</li>
+ *         <li>{@link ACAMERA_ERROR_MAX_CAMERA_IN_USE} if the system-wide limit for number of open
+ *                   cameras or camera resources has been reached, and more camera devices cannot be
+ *                   opened until previous instances are closed.</li>
+ *         <li>{@link ACAMERA_ERROR_CAMERA_DISABLED} if the camera is disabled due to a device
+ *                   policy, and cannot be opened.</li>
+ *         <li>{@link ACAMERA_ERROR_PERMISSION_DENIED} if the application does not have permission
+ *                   to open camera.</li>
+ *         <li>{@link ACAMERA_ERROR_UNKNOWN} if the method fails for some other reasons.</li></ul>
+ */
+camera_status_t ACameraManager_openCamera(
+        ACameraManager* manager, const char* cameraId,
+        ACameraDevice_StateCallbacks* callback,
+        /*out*/ACameraDevice** device);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif //_NDK_CAMERA_MANAGER_H
+
+/** @} */
diff --git a/include/camera/ndk/NdkCameraMetadata.h b/include/camera/ndk/NdkCameraMetadata.h
new file mode 100644
index 0000000..d929854
--- /dev/null
+++ b/include/camera/ndk/NdkCameraMetadata.h
@@ -0,0 +1,235 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @addtogroup Camera
+ * @{
+ */
+
+/**
+ * @file NdkCameraMetadata.h
+ */
+
+/*
+ * This file defines an NDK API.
+ * Do not remove methods.
+ * Do not change method signatures.
+ * Do not change the value of constants.
+ * Do not change the size of any of the classes defined in here.
+ * Do not reference types that are not part of the NDK.
+ * Do not #include files that aren't part of the NDK.
+ */
+
+#ifndef _NDK_CAMERA_METADATA_H
+#define _NDK_CAMERA_METADATA_H
+
+#include "NdkCameraError.h"
+#include "NdkCameraMetadataTags.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * ACameraMetadata is opaque type that provides access to read-only camera metadata like camera
+ * characteristics (via {@link ACameraManager_getCameraCharacteristics}) or capture results (via
+ * {@link ACameraCaptureSession_captureCallback_result}).
+ */
+typedef struct ACameraMetadata ACameraMetadata;
+
+/**
+ * Possible data types of a metadata entry.
+ *
+ * Keep in sync with system/media/include/system/camera_metadata.h
+ */
+enum {
+    /// Unsigned 8-bit integer (uint8_t)
+    ACAMERA_TYPE_BYTE = 0,
+    /// Signed 32-bit integer (int32_t)
+    ACAMERA_TYPE_INT32 = 1,
+    /// 32-bit float (float)
+    ACAMERA_TYPE_FLOAT = 2,
+    /// Signed 64-bit integer (int64_t)
+    ACAMERA_TYPE_INT64 = 3,
+    /// 64-bit float (double)
+    ACAMERA_TYPE_DOUBLE = 4,
+    /// A 64-bit fraction (ACameraMetadata_rational)
+    ACAMERA_TYPE_RATIONAL = 5,
+    /// Number of type fields
+    ACAMERA_NUM_TYPES
+};
+
+/**
+ * Definition of rational data type in {@link ACameraMetadata}.
+ */
+typedef struct ACameraMetadata_rational {
+    int32_t numerator;
+    int32_t denominator;
+} ACameraMetadata_rational;
+
+/**
+ * A single camera metadata entry.
+ *
+ * <p>Each entry is an array of values, though many metadata fields may only have 1 entry in the
+ * array.</p>
+ */
+typedef struct ACameraMetadata_entry {
+    /**
+     * The tag identifying the entry.
+     *
+     * <p> It is one of the values defined in {@link NdkCameraMetadataTags.h}, and defines how the
+     * entry should be interpreted and which parts of the API provide it.
+     * See {@link NdkCameraMetadataTags.h} for more details. </p>
+     */
+    uint32_t tag;
+
+    /**
+     * The data type of this metadata entry.
+     *
+     * <p>Must be one of ACAMERA_TYPE_* enum values defined above. A particular tag always has the
+     * same type.</p>
+     */
+    uint8_t  type;
+
+    /**
+     * Count of elements (NOT count of bytes) in this metadata entry.
+     */
+    uint32_t count;
+
+    /**
+     * Pointer to the data held in this metadata entry.
+     *
+     * <p>The type field above defines which union member pointer is valid. The count field above
+     * defines the length of the data in number of elements.</p>
+     */
+    union {
+        uint8_t *u8;
+        int32_t *i32;
+        float   *f;
+        int64_t *i64;
+        double  *d;
+        ACameraMetadata_rational* r;
+    } data;
+} ACameraMetadata_entry;
+
+/**
+ * A single read-only camera metadata entry.
+ *
+ * <p>Each entry is an array of values, though many metadata fields may only have 1 entry in the
+ * array.</p>
+ */
+typedef struct ACameraMetadata_const_entry {
+    /**
+     * The tag identifying the entry.
+     *
+     * <p> It is one of the values defined in {@link NdkCameraMetadataTags.h}, and defines how the
+     * entry should be interpreted and which parts of the API provide it.
+     * See {@link NdkCameraMetadataTags.h} for more details. </p>
+     */
+    uint32_t tag;
+
+    /**
+     * The data type of this metadata entry.
+     *
+     * <p>Must be one of ACAMERA_TYPE_* enum values defined above. A particular tag always has the
+     * same type.</p>
+     */
+    uint8_t  type;
+
+    /**
+     * Count of elements (NOT count of bytes) in this metadata entry.
+     */
+    uint32_t count;
+
+    /**
+     * Pointer to the data held in this metadata entry.
+     *
+     * <p>The type field above defines which union member pointer is valid. The count field above
+     * defines the length of the data in number of elements.</p>
+     */
+    union {
+        const uint8_t *u8;
+        const int32_t *i32;
+        const float   *f;
+        const int64_t *i64;
+        const double  *d;
+        const ACameraMetadata_rational* r;
+    } data;
+} ACameraMetadata_const_entry;
+
+/**
+ * Get a metadata entry from an input {@link ACameraMetadata}.
+ *
+ * <p>The memory of the data field in the returned entry is managed by camera framework. Do not
+ * attempt to free it.</p>
+ *
+ * @param metadata the {@link ACameraMetadata} of interest.
+ * @param tag the tag value of the camera metadata entry to be get.
+ * @param entry the output {@link ACameraMetadata_const_entry} will be filled here if the method
+ *        call succeeeds.
+ *
+ * @return <ul>
+ *         <li>{@link ACAMERA_OK} if the method call succeeds.</li>
+ *         <li>{@link ACAMERA_ERROR_INVALID_PARAMETER} if metadata or entry is NULL.</li>
+ *         <li>{@link ACAMERA_ERROR_METADATA_NOT_FOUND} if input metadata does not contain an entry
+ *             of input tag value.</li></ul>
+ */
+camera_status_t ACameraMetadata_getConstEntry(
+        const ACameraMetadata* metadata, uint32_t tag, /*out*/ACameraMetadata_const_entry* entry);
+
+/**
+ * List all the entry tags in input {@link ACameraMetadata}.
+ *
+ * @param metadata the {@link ACameraMetadata} of interest.
+ * @param numEntries number of metadata entries in input {@link ACameraMetadata}
+ * @param tags the tag values of the metadata entries. Length of tags is returned in numEntries
+ *             argument. The memory is managed by ACameraMetadata itself and must NOT be free/delete
+ *             by application. Do NOT access tags after calling ACameraMetadata_free.
+ *
+ * @return <ul>
+ *         <li>{@link ACAMERA_OK} if the method call succeeds.</li>
+ *         <li>{@link ACAMERA_ERROR_INVALID_PARAMETER} if metadata, numEntries or tags is NULL.</li>
+ *         <li>{@link ACAMERA_ERROR_UNKNOWN} if the method fails for some other reasons.</li></ul>
+ */
+camera_status_t ACameraMetadata_getAllTags(
+        const ACameraMetadata* metadata, /*out*/int32_t* numEntries, /*out*/const uint32_t** tags);
+
+/**
+ * Create a copy of input {@link ACameraMetadata}.
+ *
+ * <p>The returned ACameraMetadata must be freed by the application by {@link ACameraMetadata_free}
+ * after application is done using it.</p>
+ *
+ * @param src the input {@link ACameraMetadata} to be copied.
+ *
+ * @return a valid ACameraMetadata pointer or NULL if the input metadata cannot be copied.
+ */
+ACameraMetadata* ACameraMetadata_copy(const ACameraMetadata* src);
+
+/**
+ * Free a {@link ACameraMetadata} structure.
+ *
+ * @param metadata the {@link ACameraMetadata} to be freed.
+ */
+void ACameraMetadata_free(ACameraMetadata* metadata);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif //_NDK_CAMERA_METADATA_H
+
+/** @} */
diff --git a/include/camera/ndk/NdkCameraMetadataTags.h b/include/camera/ndk/NdkCameraMetadataTags.h
new file mode 100644
index 0000000..e7f6989
--- /dev/null
+++ b/include/camera/ndk/NdkCameraMetadataTags.h
@@ -0,0 +1,6908 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @addtogroup Camera
+ * @{
+ */
+
+/**
+ * @file NdkCameraMetadataTags.h
+ */
+
+/*
+ * This file defines an NDK API.
+ * Do not remove methods.
+ * Do not change method signatures.
+ * Do not change the value of constants.
+ * Do not change the size of any of the classes defined in here.
+ * Do not reference types that are not part of the NDK.
+ * Do not #include files that aren't part of the NDK.
+ */
+
+#ifndef _NDK_CAMERA_METADATA_TAGS_H
+#define _NDK_CAMERA_METADATA_TAGS_H
+
+typedef enum acamera_metadata_section {
+    ACAMERA_COLOR_CORRECTION,
+    ACAMERA_CONTROL,
+    ACAMERA_DEMOSAIC,
+    ACAMERA_EDGE,
+    ACAMERA_FLASH,
+    ACAMERA_FLASH_INFO,
+    ACAMERA_HOT_PIXEL,
+    ACAMERA_JPEG,
+    ACAMERA_LENS,
+    ACAMERA_LENS_INFO,
+    ACAMERA_NOISE_REDUCTION,
+    ACAMERA_QUIRKS,
+    ACAMERA_REQUEST,
+    ACAMERA_SCALER,
+    ACAMERA_SENSOR,
+    ACAMERA_SENSOR_INFO,
+    ACAMERA_SHADING,
+    ACAMERA_STATISTICS,
+    ACAMERA_STATISTICS_INFO,
+    ACAMERA_TONEMAP,
+    ACAMERA_LED,
+    ACAMERA_INFO,
+    ACAMERA_BLACK_LEVEL,
+    ACAMERA_SYNC,
+    ACAMERA_REPROCESS,
+    ACAMERA_DEPTH,
+    ACAMERA_SECTION_COUNT,
+
+    ACAMERA_VENDOR = 0x8000
+} acamera_metadata_section_t;
+
+/**
+ * Hierarchy positions in enum space.
+ */
+typedef enum acamera_metadata_section_start {
+    ACAMERA_COLOR_CORRECTION_START = ACAMERA_COLOR_CORRECTION  << 16,
+    ACAMERA_CONTROL_START          = ACAMERA_CONTROL           << 16,
+    ACAMERA_DEMOSAIC_START         = ACAMERA_DEMOSAIC          << 16,
+    ACAMERA_EDGE_START             = ACAMERA_EDGE              << 16,
+    ACAMERA_FLASH_START            = ACAMERA_FLASH             << 16,
+    ACAMERA_FLASH_INFO_START       = ACAMERA_FLASH_INFO        << 16,
+    ACAMERA_HOT_PIXEL_START        = ACAMERA_HOT_PIXEL         << 16,
+    ACAMERA_JPEG_START             = ACAMERA_JPEG              << 16,
+    ACAMERA_LENS_START             = ACAMERA_LENS              << 16,
+    ACAMERA_LENS_INFO_START        = ACAMERA_LENS_INFO         << 16,
+    ACAMERA_NOISE_REDUCTION_START  = ACAMERA_NOISE_REDUCTION   << 16,
+    ACAMERA_QUIRKS_START           = ACAMERA_QUIRKS            << 16,
+    ACAMERA_REQUEST_START          = ACAMERA_REQUEST           << 16,
+    ACAMERA_SCALER_START           = ACAMERA_SCALER            << 16,
+    ACAMERA_SENSOR_START           = ACAMERA_SENSOR            << 16,
+    ACAMERA_SENSOR_INFO_START      = ACAMERA_SENSOR_INFO       << 16,
+    ACAMERA_SHADING_START          = ACAMERA_SHADING           << 16,
+    ACAMERA_STATISTICS_START       = ACAMERA_STATISTICS        << 16,
+    ACAMERA_STATISTICS_INFO_START  = ACAMERA_STATISTICS_INFO   << 16,
+    ACAMERA_TONEMAP_START          = ACAMERA_TONEMAP           << 16,
+    ACAMERA_LED_START              = ACAMERA_LED               << 16,
+    ACAMERA_INFO_START             = ACAMERA_INFO              << 16,
+    ACAMERA_BLACK_LEVEL_START      = ACAMERA_BLACK_LEVEL       << 16,
+    ACAMERA_SYNC_START             = ACAMERA_SYNC              << 16,
+    ACAMERA_REPROCESS_START        = ACAMERA_REPROCESS         << 16,
+    ACAMERA_DEPTH_START            = ACAMERA_DEPTH             << 16,
+    ACAMERA_VENDOR_START           = ACAMERA_VENDOR            << 16
+} acamera_metadata_section_start_t;
+
+/**
+ * Main enum for camera metadata tags.
+ */
+typedef enum acamera_metadata_tag {
+    /**
+     * <p>The mode control selects how the image data is converted from the
+     * sensor's native color into linear sRGB color.</p>
+     *
+     * <p>This tag may appear in:</p>
+     * <ul>
+     *   <li>ACameraMetadata from ACameraCaptureSession_captureCallback_result callbacks</li>
+     *   <li>ACaptureRequest</li>
+     * </ul>
+     *
+     * <p>When auto-white balance (AWB) is enabled with ACAMERA_CONTROL_AWB_MODE, this
+     * control is overridden by the AWB routine. When AWB is disabled, the
+     * application controls how the color mapping is performed.</p>
+     * <p>We define the expected processing pipeline below. For consistency
+     * across devices, this is always the case with TRANSFORM_MATRIX.</p>
+     * <p>When either FULL or HIGH_QUALITY is used, the camera device may
+     * do additional processing but ACAMERA_COLOR_CORRECTION_GAINS and
+     * ACAMERA_COLOR_CORRECTION_TRANSFORM will still be provided by the
+     * camera device (in the results) and be roughly correct.</p>
+     * <p>Switching to TRANSFORM_MATRIX and using the data provided from
+     * FAST or HIGH_QUALITY will yield a picture with the same white point
+     * as what was produced by the camera device in the earlier frame.</p>
+     * <p>The expected processing pipeline is as follows:</p>
+     * <p><img alt="White balance processing pipeline" src="../images/camera2/metadata/android.colorCorrection.mode/processing_pipeline.png" /></p>
+     * <p>The white balance is encoded by two values, a 4-channel white-balance
+     * gain vector (applied in the Bayer domain), and a 3x3 color transform
+     * matrix (applied after demosaic).</p>
+     * <p>The 4-channel white-balance gains are defined as:</p>
+     * <pre><code>ACAMERA_COLOR_CORRECTION_GAINS = [ R G_even G_odd B ]
+     * </code></pre>
+     * <p>where <code>G_even</code> is the gain for green pixels on even rows of the
+     * output, and <code>G_odd</code> is the gain for green pixels on the odd rows.
+     * These may be identical for a given camera device implementation; if
+     * the camera device does not support a separate gain for even/odd green
+     * channels, it will use the <code>G_even</code> value, and write <code>G_odd</code> equal to
+     * <code>G_even</code> in the output result metadata.</p>
+     * <p>The matrices for color transforms are defined as a 9-entry vector:</p>
+     * <pre><code>ACAMERA_COLOR_CORRECTION_TRANSFORM = [ I0 I1 I2 I3 I4 I5 I6 I7 I8 ]
+     * </code></pre>
+     * <p>which define a transform from input sensor colors, <code>P_in = [ r g b ]</code>,
+     * to output linear sRGB, <code>P_out = [ r' g' b' ]</code>,</p>
+     * <p>with colors as follows:</p>
+     * <pre><code>r' = I0r + I1g + I2b
+     * g' = I3r + I4g + I5b
+     * b' = I6r + I7g + I8b
+     * </code></pre>
+     * <p>Both the input and output value ranges must match. Overflow/underflow
+     * values are clipped to fit within the range.</p>
+     *
+     * @see ACAMERA_COLOR_CORRECTION_GAINS
+     * @see ACAMERA_COLOR_CORRECTION_TRANSFORM
+     * @see ACAMERA_CONTROL_AWB_MODE
+     */
+    ACAMERA_COLOR_CORRECTION_MODE =                             // byte (enum)
+            ACAMERA_COLOR_CORRECTION_START,
+    /**
+     * <p>A color transform matrix to use to transform
+     * from sensor RGB color space to output linear sRGB color space.</p>
+     *
+     * <p>This tag may appear in:</p>
+     * <ul>
+     *   <li>ACameraMetadata from ACameraCaptureSession_captureCallback_result callbacks</li>
+     *   <li>ACaptureRequest</li>
+     * </ul>
+     *
+     * <p>This matrix is either set by the camera device when the request
+     * ACAMERA_COLOR_CORRECTION_MODE is not TRANSFORM_MATRIX, or
+     * directly by the application in the request when the
+     * ACAMERA_COLOR_CORRECTION_MODE is TRANSFORM_MATRIX.</p>
+     * <p>In the latter case, the camera device may round the matrix to account
+     * for precision issues; the final rounded matrix should be reported back
+     * in this matrix result metadata. The transform should keep the magnitude
+     * of the output color values within <code>[0, 1.0]</code> (assuming input color
+     * values is within the normalized range <code>[0, 1.0]</code>), or clipping may occur.</p>
+     * <p>The valid range of each matrix element varies on different devices, but
+     * values within [-1.5, 3.0] are guaranteed not to be clipped.</p>
+     *
+     * @see ACAMERA_COLOR_CORRECTION_MODE
+     */
+    ACAMERA_COLOR_CORRECTION_TRANSFORM =                        // rational[3*