cameraserver: Implement HIDL ICameraDeviceUser and ICameraDeviceCallbacks.

Bug: 110364143

Test: (build) mm -j64

Change-Id: I2164b9ffacb3c00404a5a6506a4b6631663ee4c7
Signed-off-by: Jayant Chowdhary <jchowdhary@google.com>
diff --git a/services/camera/libcameraservice/Android.bp b/services/camera/libcameraservice/Android.bp
index c912f63..9f2515e 100644
--- a/services/camera/libcameraservice/Android.bp
+++ b/services/camera/libcameraservice/Android.bp
@@ -53,9 +53,11 @@
         "device3/DistortionMapper.cpp",
         "gui/RingBufferConsumer.cpp",
         "utils/CameraThreadState.cpp",
+        "hidl/AidlCameraDeviceCallbacks.cpp",
         "hidl/AidlCameraServiceListener.cpp",
-        "hidl/HidlCameraService.cpp",
         "hidl/Convert.cpp",
+        "hidl/HidlCameraDeviceUser.cpp",
+        "hidl/HidlCameraService.cpp",
         "utils/CameraTraces.cpp",
         "utils/AutoConditionLock.cpp",
         "utils/TagMonitor.cpp",
@@ -82,6 +84,7 @@
         "libhidltransport",
         "libjpeg",
         "libmemunreachable",
+        "libstagefright_foundation",
         "android.frameworks.cameraservice.common@2.0",
         "android.frameworks.cameraservice.service@2.0",
         "android.frameworks.cameraservice.device@2.0",
diff --git a/services/camera/libcameraservice/hidl/AidlCameraDeviceCallbacks.cpp b/services/camera/libcameraservice/hidl/AidlCameraDeviceCallbacks.cpp
new file mode 100644
index 0000000..e5e5024
--- /dev/null
+++ b/services/camera/libcameraservice/hidl/AidlCameraDeviceCallbacks.cpp
@@ -0,0 +1,205 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <hardware/camera.h>
+
+#include <hidl/AidlCameraDeviceCallbacks.h>
+#include <hidl/Convert.h>
+
+namespace android {
+namespace frameworks {
+namespace cameraservice {
+namespace device {
+namespace V2_0 {
+namespace implementation {
+
+using hardware::hidl_vec;
+using HCaptureResultExtras = android::frameworks::cameraservice::device::V2_0::CaptureResultExtras;
+using HPhysicalCaptureResultInfo = android::frameworks::cameraservice::device::V2_0::PhysicalCaptureResultInfo;
+using HCameraMetadata = android::frameworks::cameraservice::device::V2_0::CameraMetadata;
+
+const char *H2BCameraDeviceCallbacks::kResultKey = "CaptureResult";
+
+H2BCameraDeviceCallbacks::H2BCameraDeviceCallbacks(const sp<HalInterface>& base) : CBase(base) { }
+
+bool H2BCameraDeviceCallbacks::initializeLooper() {
+    mCbLooper = new ALooper;
+    mCbLooper->setName("cs-looper");
+    status_t err = mCbLooper->start(/*runOnCallingThread*/ false, /*canCallJava*/ false,
+                                    PRIORITY_DEFAULT);
+    if (err !=OK) {
+        ALOGE("Unable to start camera device callback looper");
+        return false;
+    }
+    mHandler = new CallbackHandler(this);
+    mCbLooper->registerHandler(mHandler);
+    return true;
+}
+
+H2BCameraDeviceCallbacks::~H2BCameraDeviceCallbacks() {
+    if (mCbLooper != nullptr) {
+        if (mHandler != nullptr) {
+            mCbLooper->unregisterHandler(mHandler->id());
+        }
+        mCbLooper->stop();
+    }
+    mCbLooper.clear();
+    mHandler.clear();
+}
+
+binder::Status H2BCameraDeviceCallbacks::onDeviceError(
+    int32_t errorCode, const CaptureResultExtras& resultExtras) {
+    using hardware::cameraservice::utils::conversion::convertToHidl;
+    HCaptureResultExtras hCaptureResultExtras = convertToHidl(resultExtras);
+    auto ret = mBase->onDeviceError(convertToHidl(errorCode), hCaptureResultExtras);
+    if (!ret.isOk()) {
+        ALOGE("%s OnDeviceError callback failed due to %s",__FUNCTION__,
+              ret.description().c_str());
+    }
+    return binder::Status::ok();
+}
+
+binder::Status H2BCameraDeviceCallbacks::onDeviceIdle() {
+    auto ret = mBase->onDeviceIdle();
+    if (!ret.isOk()) {
+          ALOGE("%s OnDeviceIdle callback failed due to %s",__FUNCTION__,
+                ret.description().c_str());
+    }
+    return binder::Status::ok();
+}
+
+binder::Status H2BCameraDeviceCallbacks::onCaptureStarted(
+    const CaptureResultExtras& resultExtras, int64_t timestamp) {
+    using hardware::cameraservice::utils::conversion::convertToHidl;
+    HCaptureResultExtras hCaptureResultExtras = convertToHidl(resultExtras);
+    auto ret = mBase->onCaptureStarted(hCaptureResultExtras, timestamp);
+    if (!ret.isOk()) {
+        ALOGE("%s OnCaptureCallback failed due to %s",__FUNCTION__,
+              ret.description().c_str());
+    }
+    return binder::Status::ok();
+}
+
+void H2BCameraDeviceCallbacks::convertResultMetadataToHidl(const camera_metadata_t *rawMetadata,
+                                                           FmqSizeOrMetadata *hResultMetadata) {
+    // First try writing to fmq.
+    size_t metadata_size = get_camera_metadata_size(rawMetadata);
+    if ((metadata_size > 0) &&
+        (mCaptureResultMetadataQueue->availableToWrite() > 0)) {
+        if (mCaptureResultMetadataQueue->write((uint8_t *)rawMetadata, metadata_size)) {
+            hResultMetadata->fmqMetadataSize(metadata_size);
+        } else {
+            ALOGW("%s Couldn't use fmq, falling back to hwbinder", __FUNCTION__);
+            HCameraMetadata metadata;
+            hardware::cameraservice::utils::conversion::convertToHidl(rawMetadata, &metadata);
+            hResultMetadata->metadata(std::move(metadata));
+        }
+    }
+}
+
+void H2BCameraDeviceCallbacks::CallbackHandler::onMessageReceived(const sp<AMessage> &msg) {
+    sp<RefBase> obj = nullptr;
+    sp<ResultWrapper> resultWrapper = nullptr;
+    bool found = false;
+    switch (msg->what()) {
+        case kWhatResultReceived:
+            found = msg->findObject(kResultKey, &obj);
+            if (!found || obj == nullptr) {
+                ALOGE("Cannot find result object in callback message");
+                return;
+            }
+            resultWrapper = static_cast<ResultWrapper *>(obj.get());
+            processResultMessage(resultWrapper);
+            break;
+        default:
+            ALOGE("Unknown callback sent");
+            break;
+    }
+    return;
+}
+
+void H2BCameraDeviceCallbacks::CallbackHandler::processResultMessage(
+    sp<ResultWrapper> &resultWrapper) {
+    sp<H2BCameraDeviceCallbacks> converter = mConverter.promote();
+    if (converter == nullptr) {
+        ALOGE("Callback wrapper has died, result callback cannot be made");
+        return;
+    }
+    CameraMetadataNative &result = resultWrapper->mResult;
+    auto resultExtras = resultWrapper->mResultExtras;
+    auto &physicalCaptureResultInfos = resultWrapper->mPhysicalCaptureResultInfos;
+    HCaptureResultExtras hResultExtras =
+            hardware::cameraservice::utils::conversion::convertToHidl(resultExtras);
+    hidl_vec<HPhysicalCaptureResultInfo> hPhysicalCaptureResultInfos =
+            hardware::cameraservice::utils::conversion::convertToHidl(
+                    physicalCaptureResultInfos, converter->mCaptureResultMetadataQueue);
+
+    // Convert Metadata into HCameraMetadata;
+    FmqSizeOrMetadata hResult;
+    const camera_metadata_t *rawMetadata = result.getAndLock();
+    converter->convertResultMetadataToHidl(rawMetadata, &hResult);
+    result.unlock(rawMetadata);
+    auto ret = converter->mBase->onResultReceived(hResult, hResultExtras,
+                                                  hPhysicalCaptureResultInfos);
+    if (!ret.isOk()) {
+          ALOGE("%s OnResultReceived callback failed due to %s",__FUNCTION__,
+                ret.description().c_str());
+    }
+}
+
+binder::Status H2BCameraDeviceCallbacks::onResultReceived(
+    const CameraMetadataNative& result,
+    const CaptureResultExtras& resultExtras,
+    const ::std::vector<PhysicalCaptureResultInfo>& physicalCaptureResultInfos) {
+    // Wrap CameraMetadata, resultExtras and physicalCaptureResultInfos in on
+    // sp<RefBase>-able structure and post it.
+    sp<ResultWrapper> resultWrapper = new ResultWrapper(const_cast<CameraMetadataNative &>(result),
+                                                        resultExtras, physicalCaptureResultInfos);
+    sp<AMessage> msg = new AMessage(kWhatResultReceived, mHandler);
+    msg->setObject(kResultKey, resultWrapper);
+    msg->post();
+    return binder::Status::ok();
+}
+
+binder::Status H2BCameraDeviceCallbacks::onPrepared(int32_t streamId) {
+    // not implemented
+    // To silence Wunused-parameter.
+    (void) streamId;
+    return binder::Status::ok();
+}
+
+binder::Status H2BCameraDeviceCallbacks::onRepeatingRequestError(
+    int64_t lastFrameNumber,
+    int32_t repeatingRequestId) {
+    auto ret =
+        mBase->onRepeatingRequestError(lastFrameNumber, repeatingRequestId);
+    if (!ret.isOk()) {
+        ALOGE("%s OnRepeatingRequestEror callback failed due to %s",__FUNCTION__,
+              ret.description().c_str());
+    }
+    return binder::Status::ok();
+}
+
+binder::Status H2BCameraDeviceCallbacks::onRequestQueueEmpty() {
+    // not implemented
+    return binder::Status::ok();
+}
+
+} // implementation
+} // V2_0
+} // device
+} // cameraservice
+} // frameworks
+} // android
diff --git a/services/camera/libcameraservice/hidl/AidlCameraDeviceCallbacks.h b/services/camera/libcameraservice/hidl/AidlCameraDeviceCallbacks.h
new file mode 100644
index 0000000..dbf520a
--- /dev/null
+++ b/services/camera/libcameraservice/hidl/AidlCameraDeviceCallbacks.h
@@ -0,0 +1,132 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_FRAMEWORKS_AIDL_CAMERADEVICECALLBACKS_H
+#define ANDROID_FRAMEWORKS_AIDL_CAMERADEVICECALLBACKS_H
+
+#include <mutex>
+#include <thread>
+
+#include <android/frameworks/cameraservice/common/2.0/types.h>
+#include <android/frameworks/cameraservice/service/2.0/types.h>
+#include <android/frameworks/cameraservice/device/2.0/ICameraDeviceCallback.h>
+#include <android/frameworks/cameraservice/device/2.0/types.h>
+#include <android/hardware/camera2/BnCameraDeviceCallbacks.h>
+#include <media/stagefright/foundation/ALooper.h>
+#include <media/stagefright/foundation/AHandler.h>
+#include <media/stagefright/foundation/AMessage.h>
+#include <fmq/MessageQueue.h>
+#include <hidl/MQDescriptor.h>
+#include <hidl/Status.h>
+#include <CameraService.h>
+#include <hidl/CameraHybridInterface.h>
+
+namespace android {
+namespace frameworks {
+namespace cameraservice {
+namespace device {
+namespace V2_0 {
+namespace implementation {
+
+using camerahybrid::H2BConverter;
+using HCameraDeviceCallback = cameraservice::device::V2_0::ICameraDeviceCallback;
+using HPhysicalCaptureResultInfo = cameraservice::device::V2_0::PhysicalCaptureResultInfo;
+using android::frameworks::cameraservice::device::V2_0::FmqSizeOrMetadata;
+
+using hardware::camera2::BnCameraDeviceCallbacks;
+using hardware::camera2::ICameraDeviceCallbacks;
+using hardware::camera2::impl::CaptureResultExtras;
+using hardware::camera2::impl::CameraMetadataNative;
+using hardware::camera2::impl::PhysicalCaptureResultInfo;
+using hardware::kSynchronizedReadWrite;
+using hardware::MessageQueue;
+using CaptureResultMetadataQueue = MessageQueue<uint8_t, kSynchronizedReadWrite>;
+
+struct H2BCameraDeviceCallbacks :
+    public H2BConverter<HCameraDeviceCallback, ICameraDeviceCallbacks, BnCameraDeviceCallbacks> {
+    H2BCameraDeviceCallbacks(const sp<HalInterface>& base);
+
+    ~H2BCameraDeviceCallbacks();
+
+    bool initializeLooper();
+
+    virtual binder::Status onDeviceError(int32_t errorCode,
+                                         const CaptureResultExtras& resultExtras) override;
+
+    virtual binder::Status onDeviceIdle() override;
+
+    virtual binder::Status onCaptureStarted(const CaptureResultExtras& resultExtras,
+                                            int64_t timestamp) override;
+
+    virtual binder::Status onResultReceived(
+        const CameraMetadataNative& result, const CaptureResultExtras& resultExtras,
+        const std::vector<PhysicalCaptureResultInfo>& physicalCaptureResultInfos) override;
+
+    virtual binder::Status onPrepared(int32_t streamId) override;
+
+    virtual binder::Status onRepeatingRequestError(int64_t lastFrameNumber,
+                                                   int32_t repeatingRequestId) override;
+
+    virtual binder::Status onRequestQueueEmpty() override;
+
+    void setCaptureResultMetadataQueue(std::shared_ptr<CaptureResultMetadataQueue> metadataQueue) {
+        mCaptureResultMetadataQueue = metadataQueue;
+    }
+
+ private:
+    // Wrapper struct so that parameters to onResultReceived callback may be
+    // sent through an AMessage.
+    struct ResultWrapper : public RefBase {
+        CameraMetadataNative mResult;
+        CaptureResultExtras mResultExtras;
+        std::vector<PhysicalCaptureResultInfo> mPhysicalCaptureResultInfos;
+        ResultWrapper(CameraMetadataNative &result,
+                      const CaptureResultExtras resultExtras,
+                      const std::vector<PhysicalCaptureResultInfo> &physicalCaptureResultInfos) :
+      // TODO: make this std::movable
+      mResult(result), mResultExtras(resultExtras), mPhysicalCaptureResultInfos(physicalCaptureResultInfos) { }
+    };
+
+    struct CallbackHandler : public AHandler {
+        public:
+            void onMessageReceived(const sp<AMessage> &msg) override;
+            CallbackHandler(H2BCameraDeviceCallbacks *converter) : mConverter(converter) { }
+        private:
+            void processResultMessage(sp<ResultWrapper> &resultWrapper);
+            wp<H2BCameraDeviceCallbacks> mConverter = nullptr;
+            Mutex mMetadataQueueLock;
+    };
+
+    void convertResultMetadataToHidl(const camera_metadata *rawMetadata,
+                                     FmqSizeOrMetadata *resultMetadata);
+    enum {
+        kWhatResultReceived,
+    };
+
+    static const char *kResultKey;
+
+    std::shared_ptr<CaptureResultMetadataQueue> mCaptureResultMetadataQueue = nullptr;
+    sp<CallbackHandler> mHandler = nullptr;
+    sp<ALooper> mCbLooper = nullptr;
+};
+
+} // implementation
+} // V2_0
+} // device
+} // cameraservice
+} // frameworks
+} // android
+#endif // ANDROID_FRAMEWORKS_AIDL_CAMERADEVICECALLBACKS_H
diff --git a/services/camera/libcameraservice/hidl/Convert.cpp b/services/camera/libcameraservice/hidl/Convert.cpp
index 53097c3..22e879e 100644
--- a/services/camera/libcameraservice/hidl/Convert.cpp
+++ b/services/camera/libcameraservice/hidl/Convert.cpp
@@ -220,6 +220,43 @@
   return status;
 }
 
+HPhysicalCaptureResultInfo convertToHidl(
+    const PhysicalCaptureResultInfo &physicalCaptureResultInfo,
+    std::shared_ptr<CaptureResultMetadataQueue> &captureResultMetadataQueue) {
+    HPhysicalCaptureResultInfo hPhysicalCaptureResultInfo;
+    hPhysicalCaptureResultInfo.physicalCameraId =
+        String8(physicalCaptureResultInfo.mPhysicalCameraId).string();
+    const camera_metadata_t *rawMetadata =
+        physicalCaptureResultInfo.mPhysicalCameraMetadata.getAndLock();
+    // Try using fmq at first.
+    size_t metadata_size = get_camera_metadata_size(rawMetadata);
+    if ((metadata_size > 0) && (captureResultMetadataQueue->availableToWrite() > 0)) {
+        if (captureResultMetadataQueue->write((uint8_t *)rawMetadata, metadata_size)) {
+            hPhysicalCaptureResultInfo.physicalCameraMetadata.fmqMetadataSize(metadata_size);
+        } else {
+            ALOGW("%s Couldn't use fmq, falling back to hwbinder", __FUNCTION__);
+            HCameraMetadata metadata;
+            convertToHidl(rawMetadata, &metadata);
+            hPhysicalCaptureResultInfo.physicalCameraMetadata.metadata(std::move(metadata));
+        }
+    }
+    physicalCaptureResultInfo.mPhysicalCameraMetadata.unlock(rawMetadata);
+    return hPhysicalCaptureResultInfo;
+}
+
+hidl_vec<HPhysicalCaptureResultInfo> convertToHidl(
+    const std::vector<PhysicalCaptureResultInfo> &physicalCaptureResultInfos,
+    std::shared_ptr<CaptureResultMetadataQueue> &captureResultMetadataQueue) {
+    hidl_vec<HPhysicalCaptureResultInfo> hPhysicalCaptureResultInfos;
+    hPhysicalCaptureResultInfos.resize(physicalCaptureResultInfos.size());
+    size_t i = 0;
+    for (auto &physicalCaptureResultInfo : physicalCaptureResultInfos) {
+        hPhysicalCaptureResultInfos[i++] = convertToHidl(physicalCaptureResultInfo,
+                                                         captureResultMetadataQueue);
+    }
+    return hPhysicalCaptureResultInfos;
+}
+
 } //conversion
 } // utils
 } //cameraservice
diff --git a/services/camera/libcameraservice/hidl/Convert.h b/services/camera/libcameraservice/hidl/Convert.h
index ba2849e..82937a3 100644
--- a/services/camera/libcameraservice/hidl/Convert.h
+++ b/services/camera/libcameraservice/hidl/Convert.h
@@ -28,7 +28,9 @@
 #include <android/hardware/camera2/ICameraDeviceUser.h>
 #include <android/hardware/graphics/bufferqueue/1.0/IGraphicBufferProducer.h>
 #include <android/hardware/ICameraService.h>
+#include <fmq/MessageQueue.h>
 #include <hardware/camera.h>
+#include <hidl/MQDescriptor.h>
 
 namespace android {
 namespace hardware {
@@ -39,6 +41,7 @@
 using hardware::camera2::impl::CaptureResultExtras;
 using hardware::camera2::impl::PhysicalCaptureResultInfo;
 
+using CaptureResultMetadataQueue = MessageQueue<uint8_t, kSynchronizedReadWrite>;
 using HCameraMetadata = frameworks::cameraservice::service::V2_0::CameraMetadata;
 using HCameraDeviceStatus = frameworks::cameraservice::service::V2_0::CameraDeviceStatus;
 using HCameraStatusAndId = frameworks::cameraservice::service::V2_0::CameraStatusAndId;
@@ -79,6 +82,10 @@
 
 HCaptureResultExtras convertToHidl(const CaptureResultExtras &captureResultExtras);
 
+hidl_vec<HPhysicalCaptureResultInfo> convertToHidl(
+    const std::vector<PhysicalCaptureResultInfo> &physicalCaptureResultInfos,
+    std::shared_ptr<CaptureResultMetadataQueue> &captureResultMetadataQueue);
+
 HStatus B2HStatus(const binder::Status &bStatus);
 
 } // conversion
diff --git a/services/camera/libcameraservice/hidl/HidlCameraDeviceUser.cpp b/services/camera/libcameraservice/hidl/HidlCameraDeviceUser.cpp
new file mode 100644
index 0000000..d22ba5a
--- /dev/null
+++ b/services/camera/libcameraservice/hidl/HidlCameraDeviceUser.cpp
@@ -0,0 +1,263 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <android/hardware/camera/device/3.2/types.h>
+#include <cutils/properties.h>
+#include <gui/Surface.h>
+#include <gui/bufferqueue/1.0/H2BGraphicBufferProducer.h>
+
+#include <hidl/AidlCameraDeviceCallbacks.h>
+#include <hidl/Convert.h>
+#include <hidl/HidlCameraDeviceUser.h>
+#include <android/hardware/camera/device/3.2/types.h>
+
+namespace android {
+namespace frameworks {
+namespace cameraservice {
+namespace device {
+namespace V2_0 {
+namespace implementation {
+
+using hardware::cameraservice::utils::conversion::convertToHidl;
+using hardware::cameraservice::utils::conversion::convertFromHidl;
+using hardware::cameraservice::utils::conversion::B2HStatus;
+
+using hardware::graphics::bufferqueue::V1_0::utils::H2BGraphicBufferProducer;
+using hardware::hidl_vec;
+using hardware::Return;
+using hardware::Void;
+using HSubmitInfo = device::V2_0::SubmitInfo;
+using hardware::camera2::params::OutputConfiguration;
+
+static constexpr int32_t CAMERA_REQUEST_METADATA_QUEUE_SIZE = 1 << 20 /* 1 MB */;
+static constexpr int32_t CAMERA_RESULT_METADATA_QUEUE_SIZE = 1 << 20 /* 1 MB */;
+
+Return<void> HidlCameraDeviceUser::disconnect() {
+    mDeviceRemote->disconnect();
+    return Void();
+}
+
+HidlCameraDeviceUser::HidlCameraDeviceUser(
+    const sp<hardware::camera2::ICameraDeviceUser> &deviceRemote)
+  : mDeviceRemote(deviceRemote) {
+    mInitSuccess = initDevice();
+}
+
+bool HidlCameraDeviceUser::initDevice() {
+    // TODO: Get request and result metadata queue size from a system property.
+    int32_t reqFMQSize = CAMERA_REQUEST_METADATA_QUEUE_SIZE;
+
+    mCaptureRequestMetadataQueue =
+        std::make_unique<CaptureRequestMetadataQueue>(static_cast<size_t>(reqFMQSize),
+                                                      false /* non blocking */);
+    if (!mCaptureRequestMetadataQueue->isValid()) {
+        ALOGE("%s: invalid request fmq", __FUNCTION__);
+        return false;
+    }
+
+    int32_t resFMQSize = CAMERA_RESULT_METADATA_QUEUE_SIZE;
+    mCaptureResultMetadataQueue =
+        std::make_shared<CaptureResultMetadataQueue>(static_cast<size_t>(resFMQSize),
+                                                     false /* non blocking */);
+    if (!mCaptureResultMetadataQueue->isValid()) {
+        ALOGE("%s: invalid result fmq", __FUNCTION__);
+        return false;
+    }
+    return true;
+}
+
+Return<void> HidlCameraDeviceUser::getCaptureRequestMetadataQueue(
+    getCaptureRequestMetadataQueue_cb _hidl_cb) {
+    if (mInitSuccess) {
+        _hidl_cb(*mCaptureRequestMetadataQueue->getDesc());
+    }
+    return Void();
+}
+
+Return<void> HidlCameraDeviceUser::getCaptureResultMetadataQueue(
+    getCaptureResultMetadataQueue_cb _hidl_cb) {
+    if (mInitSuccess) {
+        _hidl_cb(*mCaptureResultMetadataQueue->getDesc());
+    }
+    return Void();
+}
+
+/**
+ * To be used only by submitRequestList implementation, since it requires
+ * clients to call this method serially, incase fmq is used to send metadata.
+ */
+bool HidlCameraDeviceUser::copyPhysicalCameraSettings(
+    const hidl_vec<HPhysicalCameraSettings> &hPhysicalCameraSettings,
+    std::vector<CaptureRequest::PhysicalCameraSettings> *physicalCameraSettings) {
+    bool converted = false;
+    for (auto &e : hPhysicalCameraSettings) {
+        physicalCameraSettings->emplace_back();
+        CaptureRequest::PhysicalCameraSettings &physicalCameraSetting =
+            physicalCameraSettings->back();
+        physicalCameraSetting.id = e.id.c_str();
+
+        // Read the settings either from the fmq or straightaway from the
+        // request. We don't need any synchronization, since submitRequestList
+        // is guaranteed to be called serially by the client if it decides to
+        // use fmq.
+        if (e.settings.getDiscriminator() ==
+            FmqSizeOrMetadata::hidl_discriminator::fmqMetadataSize) {
+            /**
+             * Get settings from the fmq.
+             */
+            HCameraMetadata settingsFmq;
+            settingsFmq.resize(e.settings.fmqMetadataSize());
+            bool read = mCaptureRequestMetadataQueue->read(settingsFmq.data(),
+                                                           e.settings.fmqMetadataSize());
+            if (!read) {
+                ALOGE("%s capture request settings could't be read from fmq size",
+                      __FUNCTION__);
+                converted = false;
+            } else {
+                converted = convertFromHidl(settingsFmq, &physicalCameraSetting.settings);
+            }
+        } else {
+            /**
+             * The settings metadata is contained in request settings field.
+             */
+            converted =
+                convertFromHidl(e.settings.metadata(),
+                                &physicalCameraSetting.settings);
+        }
+        if (!converted) {
+          ALOGE("%s: Unable to convert physicalCameraSettings from HIDL to AIDL.", __FUNCTION__);
+          return false;
+        }
+    }
+    return true;
+}
+
+bool HidlCameraDeviceUser::convertRequestFromHidl(const HCaptureRequest &hRequest,
+                                                  CaptureRequest *request) {
+    // No reprocessing support.
+    request->mIsReprocess = false;
+    for (const auto &streamAndWindowId : hRequest.streamAndWindowIds) {
+        request->mStreamIdxList.push_back(streamAndWindowId.streamId);
+        request->mSurfaceIdxList.push_back(streamAndWindowId.windowId);
+    }
+    return copyPhysicalCameraSettings(hRequest.physicalCameraSettings,
+                                      &(request->mPhysicalCameraSettings));
+}
+
+Return<void> HidlCameraDeviceUser::submitRequestList(const hidl_vec<HCaptureRequest>& hRequestList,
+                                                     bool streaming,
+                                                     submitRequestList_cb _hidl_cb) {
+    hardware::camera2::utils::SubmitInfo submitInfo;
+    HSubmitInfo hSubmitInfo;
+    /**
+     * Create AIDL CaptureRequest from requestList and graphicBufferProducers.
+     */
+    std::vector<hardware::camera2::CaptureRequest> requests;
+    for (auto &hRequest : hRequestList) {
+        requests.emplace_back();
+        auto &request = requests.back();
+        if (!convertRequestFromHidl(hRequest, &request)) {
+            _hidl_cb(HStatus::ILLEGAL_ARGUMENT, hSubmitInfo);
+            return Void();
+        }
+    }
+    mDeviceRemote->submitRequestList(requests, streaming, &submitInfo);
+    mRequestId = submitInfo.mRequestId;
+    convertToHidl(submitInfo, &hSubmitInfo);
+    _hidl_cb(HStatus::NO_ERROR, hSubmitInfo);
+    return Void();
+}
+
+Return<void> HidlCameraDeviceUser::cancelRepeatingRequest(cancelRepeatingRequest_cb _hidl_cb) {
+    int64_t lastFrameNumber = 0;
+    binder::Status ret = mDeviceRemote->cancelRequest(mRequestId, &lastFrameNumber);
+    _hidl_cb(B2HStatus(ret), lastFrameNumber);
+    return Void();
+}
+
+Return<HStatus> HidlCameraDeviceUser::beginConfigure() {
+    binder::Status ret = mDeviceRemote->beginConfigure();
+    return B2HStatus(ret);
+}
+
+Return<HStatus> HidlCameraDeviceUser::endConfigure(StreamConfigurationMode operatingMode,
+                                                   const hidl_vec<uint8_t>& sessionParams) {
+    android::CameraMetadata cameraMetadata;
+    if (!convertFromHidl(sessionParams, &cameraMetadata)) {
+        return HStatus::ILLEGAL_ARGUMENT;
+    }
+
+    binder::Status ret = mDeviceRemote->endConfigure(convertFromHidl(operatingMode),
+                                                     cameraMetadata);
+    return B2HStatus(ret);
+}
+
+Return<HStatus> HidlCameraDeviceUser::deleteStream(int32_t streamId) {
+    binder::Status ret = mDeviceRemote->deleteStream(streamId);
+    return B2HStatus(ret);
+}
+
+Return<void> HidlCameraDeviceUser::createStream(const HOutputConfiguration& hOutputConfiguration,
+                                                createStream_cb hidl_cb_) {
+    OutputConfiguration outputConfiguration =
+        convertFromHidl(hOutputConfiguration);
+    int32_t newStreamId = 0;
+    binder::Status ret = mDeviceRemote->createStream(outputConfiguration, &newStreamId);
+    HStatus status = B2HStatus(ret);
+    hidl_cb_(status, newStreamId);
+    return Void();
+}
+
+Return<void> HidlCameraDeviceUser::createDefaultRequest(TemplateId templateId,
+                                                        createDefaultRequest_cb _hidl_cb) {
+    android::CameraMetadata cameraMetadata;
+    binder::Status ret = mDeviceRemote->createDefaultRequest(convertFromHidl(templateId),
+                                                             &cameraMetadata);
+    HStatus hStatus = B2HStatus(ret);
+    HCameraMetadata hidlMetadata;
+    const camera_metadata_t *rawMetadata = cameraMetadata.getAndLock();
+    convertToHidl(rawMetadata, &hidlMetadata);
+    _hidl_cb(hStatus, hidlMetadata);
+    cameraMetadata.unlock(rawMetadata);
+    return Void();
+}
+
+Return<HStatus> HidlCameraDeviceUser::waitUntilIdle() {
+    binder::Status ret = mDeviceRemote->waitUntilIdle();
+    return B2HStatus(ret);
+}
+
+Return<void> HidlCameraDeviceUser::flush(flush_cb _hidl_cb) {
+    int64_t lastFrameNumber = 0;
+    binder::Status ret = mDeviceRemote->flush(&lastFrameNumber);
+    _hidl_cb(B2HStatus(ret),lastFrameNumber);
+    return Void();
+}
+
+Return<HStatus> HidlCameraDeviceUser::updateOutputConfiguration(
+    int32_t streamId,
+    const HOutputConfiguration& hOutputConfiguration) {
+    OutputConfiguration outputConfiguration = convertFromHidl(hOutputConfiguration);
+    binder::Status ret = mDeviceRemote->updateOutputConfiguration(streamId, outputConfiguration);
+    return B2HStatus(ret);
+}
+
+} // implementation
+} // V2_0
+} // device
+} // cameraservice
+} // frameworks
+} // android
diff --git a/services/camera/libcameraservice/hidl/HidlCameraDeviceUser.h b/services/camera/libcameraservice/hidl/HidlCameraDeviceUser.h
new file mode 100644
index 0000000..be8f1d6
--- /dev/null
+++ b/services/camera/libcameraservice/hidl/HidlCameraDeviceUser.h
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_FRAMEWORKS_CAMERADEVICEUSER_V2_0_CAMERADEVICEUSER_H
+#define ANDROID_FRAMEWORKS_CAMERADEVICEUSER_V2_0_CAMERADEVICEUSER_H
+
+#include <mutex>
+#include <memory>
+#include <thread>
+
+#include <android/frameworks/cameraservice/common/2.0/types.h>
+#include <android/frameworks/cameraservice/service/2.0/types.h>
+#include <android/frameworks/cameraservice/device/2.0/ICameraDeviceUser.h>
+#include <android/frameworks/cameraservice/device/2.0/types.h>
+#include <android/hardware/camera2/ICameraDeviceCallbacks.h>
+#include <fmq/MessageQueue.h>
+#include <hidl/MQDescriptor.h>
+#include <hidl/Status.h>
+
+#include <CameraService.h>
+
+namespace android {
+namespace frameworks {
+namespace cameraservice {
+namespace device {
+namespace V2_0 {
+namespace implementation {
+
+using frameworks::cameraservice::device::V2_0::StreamConfigurationMode;
+using hardware::camera2::CaptureRequest;
+using hardware::hidl_vec;
+using hardware::kSynchronizedReadWrite;
+using hardware::MessageQueue;
+using hardware::MQDescriptorSync;
+using hardware::Return;
+using CaptureResultMetadataQueue = MessageQueue<uint8_t, kSynchronizedReadWrite>;
+using CaptureRequestMetadataQueue = MessageQueue<uint8_t, kSynchronizedReadWrite>;
+using TemplateId = frameworks::cameraservice::device::V2_0::TemplateId;
+
+using HCameraDeviceUser = device::V2_0::ICameraDeviceUser;
+using HCameraMetadata = cameraservice::service::V2_0::CameraMetadata;
+using HCaptureRequest = device::V2_0::CaptureRequest;
+using HOutputConfiguration = frameworks::cameraservice::device::V2_0::OutputConfiguration;
+using HPhysicalCameraSettings = frameworks::cameraservice::device::V2_0::PhysicalCameraSettings;
+using HStatus = frameworks::cameraservice::common::V2_0::Status;
+
+static constexpr int32_t REQUEST_ID_NONE = -1;
+
+struct HidlCameraDeviceUser final : public HCameraDeviceUser {
+    HidlCameraDeviceUser(const sp<hardware::camera2::ICameraDeviceUser> &deviceRemote);
+
+    ~HidlCameraDeviceUser() { }
+
+    virtual Return<void> disconnect() override;
+
+    virtual Return<void> getCaptureRequestMetadataQueue(
+        getCaptureRequestMetadataQueue_cb _hidl_cb) override;
+
+    virtual Return<void> getCaptureResultMetadataQueue(
+        getCaptureResultMetadataQueue_cb _hidl_cb) override;
+
+    virtual Return<void> submitRequestList(const hidl_vec<HCaptureRequest>& requestList,
+                                           bool streaming, submitRequestList_cb _hidl_cb) override;
+
+    virtual Return<void> cancelRepeatingRequest(cancelRepeatingRequest_cb _hidl_cb) override;
+
+    virtual Return<HStatus> beginConfigure() override;
+
+    virtual Return<HStatus> endConfigure(StreamConfigurationMode operatingMode,
+                                         const hidl_vec<uint8_t>& sessionParams);
+
+    virtual Return<HStatus> deleteStream(int32_t streamId) override;
+
+    virtual Return<void> createStream(const HOutputConfiguration& outputConfiguration,
+                                      createStream_cb _hidl_cb) override;
+
+    Return<void> createDefaultRequest(TemplateId templateId,
+                                      createDefaultRequest_cb _hidl_cb) override;
+
+    virtual Return<HStatus> waitUntilIdle() override;
+
+    virtual Return<void> flush(flush_cb _hidl_cb) override;
+
+    virtual Return<HStatus> updateOutputConfiguration(
+        int32_t streamId, const HOutputConfiguration& outputConfiguration) override;
+
+    bool initStatus() { return mInitSuccess; }
+
+    std::shared_ptr<CaptureResultMetadataQueue> getCaptureResultMetadataQueue() {
+        return mCaptureResultMetadataQueue;
+    }
+
+ private:
+    bool initDevice();
+
+    bool convertRequestFromHidl(const HCaptureRequest &hRequest, CaptureRequest *request);
+
+    bool copyPhysicalCameraSettings(
+        const hidl_vec<HPhysicalCameraSettings> &hPhysicalCameraSettings,
+        std::vector<CaptureRequest::PhysicalCameraSettings> *physicalCameraSettings);
+
+    const sp<hardware::camera2::ICameraDeviceUser> mDeviceRemote;
+    std::unique_ptr<CaptureRequestMetadataQueue> mCaptureRequestMetadataQueue = nullptr;
+    std::shared_ptr<CaptureResultMetadataQueue> mCaptureResultMetadataQueue = nullptr;
+    bool mInitSuccess = false;
+    int32_t mRequestId = REQUEST_ID_NONE;
+};
+
+} // implementation
+} // V2_0
+} // device
+} // cameraservice
+} // frameworks
+} // android
+#endif // ANDROID_FRAMEOWORKS_CAMERADEVICEUSER_V2_0_CAMERADEVICEUSER_H
diff --git a/services/camera/libcameraservice/hidl/HidlCameraService.cpp b/services/camera/libcameraservice/hidl/HidlCameraService.cpp
index f34f903..31bdf6d 100644
--- a/services/camera/libcameraservice/hidl/HidlCameraService.cpp
+++ b/services/camera/libcameraservice/hidl/HidlCameraService.cpp
@@ -17,6 +17,9 @@
 #include <hidl/Convert.h>
 
 #include <hidl/HidlCameraService.h>
+
+#include <hidl/HidlCameraDeviceUser.h>
+#include <hidl/AidlCameraDeviceCallbacks.h>
 #include <hidl/AidlCameraServiceListener.h>
 
 #include <hidl/HidlTransportSupport.h>
@@ -34,6 +37,8 @@
 using hardware::cameraservice::utils::conversion::B2HStatus;
 using hardware::Void;
 
+using device::V2_0::implementation::H2BCameraDeviceCallbacks;
+using device::V2_0::implementation::HidlCameraDeviceUser;
 using service::V2_0::implementation::H2BCameraServiceListener;
 using HCameraMetadataType = android::frameworks::cameraservice::common::V2_0::CameraMetadataType;
 using HVendorTag = android::frameworks::cameraservice::common::V2_0::VendorTag;
@@ -79,11 +84,43 @@
 Return<void> HidlCameraService::connectDevice(const sp<HCameraDeviceCallback>& hCallback,
                                               const hidl_string& cameraId,
                                               connectDevice_cb _hidl_cb) {
-    // To silence Wunused-parameter.
-    (void)hCallback;
-    (void)cameraId;
-    (void)_hidl_cb;
-
+    // Here, we first get ICameraDeviceUser from mAidlICameraService, then save
+    // that interface in the newly created HidlCameraDeviceUser impl class.
+    if (mAidlICameraService == nullptr) {
+        _hidl_cb(HStatus::UNKNOWN_ERROR, nullptr);
+        return Void();
+    }
+    sp<hardware::camera2::ICameraDeviceUser> deviceRemote = nullptr;
+    // Create a hardware::camera2::ICameraDeviceCallback object which internally
+    // calls callback functions passed through hCallback.
+    sp<H2BCameraDeviceCallbacks> hybridCallbacks = new H2BCameraDeviceCallbacks(hCallback);
+    if (!hybridCallbacks->initializeLooper()) {
+        ALOGE("Unable to handle callbacks on device, cannot connect");
+        _hidl_cb(HStatus::UNKNOWN_ERROR, nullptr);
+        return Void();
+    }
+    sp<hardware::camera2::ICameraDeviceCallbacks> callbacks = hybridCallbacks;
+    binder::Status serviceRet = mAidlICameraService->connectDevice(
+            callbacks, String16(cameraId.c_str()), String16(""),
+            hardware::ICameraService::USE_CALLING_UID, /*out*/&deviceRemote);
+    HStatus status = HStatus::NO_ERROR;
+    if (!serviceRet.isOk()) {
+        ALOGE("%s: Unable to connect to camera device", __FUNCTION__);
+        status = B2HStatus(serviceRet);
+        _hidl_cb(status, nullptr);
+        return Void();
+    }
+    // Now we create a HidlCameraDeviceUser class, store the deviceRemote in it,
+    // and return that back. All calls on that interface will be forwarded to
+    // the AIDL interface.
+    sp<HidlCameraDeviceUser> hDeviceRemote = new HidlCameraDeviceUser(deviceRemote);
+    if (!hDeviceRemote->initStatus()) {
+        ALOGE("%s: Unable to initialize camera device HIDL wrapper", __FUNCTION__);
+        _hidl_cb(HStatus::UNKNOWN_ERROR, nullptr);
+        return Void();
+    }
+    hybridCallbacks->setCaptureResultMetadataQueue(hDeviceRemote->getCaptureResultMetadataQueue());
+    _hidl_cb(status, hDeviceRemote);
     return Void();
 }