Merge "Fix sensor event in vehicle HAL emulator"
diff --git a/audio/2.0/default/StreamOut.cpp b/audio/2.0/default/StreamOut.cpp
index cdc8ded..6ccdbcd 100644
--- a/audio/2.0/default/StreamOut.cpp
+++ b/audio/2.0/default/StreamOut.cpp
@@ -79,10 +79,6 @@
         ssize_t writeResult = mStream->write(mStream, &mBuffer[0], availToRead);
         if (writeResult >= 0) {
             mStatus.reply.written = writeResult;
-            // Diagnostics of the cause of b/35813113.
-            ALOGE_IF(writeResult > availToRead,
-                    "legacy hal reports more bytes written than asked for: %lld > %lld",
-                    (long long)writeResult, (long long)availToRead);
         } else {
             mStatus.retval = Stream::analyzeStatus("write", writeResult);
         }
diff --git a/automotive/vehicle/2.0/Android.mk b/automotive/vehicle/2.0/Android.mk
index f976c39..d093017 100644
--- a/automotive/vehicle/2.0/Android.mk
+++ b/automotive/vehicle/2.0/Android.mk
@@ -910,44 +910,6 @@
 LOCAL_GENERATED_SOURCES += $(GEN)
 
 #
-# Build types.hal (VmsMessageIntegerValuesIndex)
-#
-GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_0/VmsMessageIntegerValuesIndex.java
-$(GEN): $(HIDL)
-$(GEN): PRIVATE_HIDL := $(HIDL)
-$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
-$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
-$(GEN): PRIVATE_CUSTOM_TOOL = \
-        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
-        -Ljava \
-        -randroid.hardware:hardware/interfaces \
-        -randroid.hidl:system/libhidl/transport \
-        android.hardware.automotive.vehicle@2.0::types.VmsMessageIntegerValuesIndex
-
-$(GEN): $(LOCAL_PATH)/types.hal
-	$(transform-generated-source)
-LOCAL_GENERATED_SOURCES += $(GEN)
-
-#
-# Build types.hal (VmsMessageType)
-#
-GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_0/VmsMessageType.java
-$(GEN): $(HIDL)
-$(GEN): PRIVATE_HIDL := $(HIDL)
-$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
-$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
-$(GEN): PRIVATE_CUSTOM_TOOL = \
-        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
-        -Ljava \
-        -randroid.hardware:hardware/interfaces \
-        -randroid.hidl:system/libhidl/transport \
-        android.hardware.automotive.vehicle@2.0::types.VmsMessageType
-
-$(GEN): $(LOCAL_PATH)/types.hal
-	$(transform-generated-source)
-LOCAL_GENERATED_SOURCES += $(GEN)
-
-#
 # Build types.hal (Wheel)
 #
 GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_0/Wheel.java
@@ -1920,44 +1882,6 @@
 LOCAL_GENERATED_SOURCES += $(GEN)
 
 #
-# Build types.hal (VmsMessageIntegerValuesIndex)
-#
-GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_0/VmsMessageIntegerValuesIndex.java
-$(GEN): $(HIDL)
-$(GEN): PRIVATE_HIDL := $(HIDL)
-$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
-$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
-$(GEN): PRIVATE_CUSTOM_TOOL = \
-        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
-        -Ljava \
-        -randroid.hardware:hardware/interfaces \
-        -randroid.hidl:system/libhidl/transport \
-        android.hardware.automotive.vehicle@2.0::types.VmsMessageIntegerValuesIndex
-
-$(GEN): $(LOCAL_PATH)/types.hal
-	$(transform-generated-source)
-LOCAL_GENERATED_SOURCES += $(GEN)
-
-#
-# Build types.hal (VmsMessageType)
-#
-GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_0/VmsMessageType.java
-$(GEN): $(HIDL)
-$(GEN): PRIVATE_HIDL := $(HIDL)
-$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
-$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
-$(GEN): PRIVATE_CUSTOM_TOOL = \
-        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
-        -Ljava \
-        -randroid.hardware:hardware/interfaces \
-        -randroid.hidl:system/libhidl/transport \
-        android.hardware.automotive.vehicle@2.0::types.VmsMessageType
-
-$(GEN): $(LOCAL_PATH)/types.hal
-	$(transform-generated-source)
-LOCAL_GENERATED_SOURCES += $(GEN)
-
-#
 # Build types.hal (Wheel)
 #
 GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_0/Wheel.java
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h
index 9591689..f1a1ff4 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h
@@ -147,6 +147,15 @@
     },
 
     {
+        .prop = toInt(VehicleProperty::ENV_OUTSIDE_TEMPERATURE),
+        .access = VehiclePropertyAccess::READ,
+        // TODO(bryaneyler): Support ON_CHANGE as well.
+        .changeMode = VehiclePropertyChangeMode::CONTINUOUS,
+        .minSampleRate = 1.0f,
+        .maxSampleRate = 2.0f,
+    },
+
+    {
         .prop = toInt(VehicleProperty::NIGHT_MODE),
         .access = VehiclePropertyAccess::READ,
         .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultVehicleHal.cpp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultVehicleHal.cpp
index e1a3ae7..4cdd3f7 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultVehicleHal.cpp
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultVehicleHal.cpp
@@ -397,6 +397,9 @@
     case toInt(VehicleProperty::HVAC_TEMPERATURE_SET):
         prop->value.floatValues[0] = 16;
         break;
+    case toInt(VehicleProperty::ENV_OUTSIDE_TEMPERATURE):
+        prop->value.floatValues[0] = 25;
+        break;
     case toInt(VehicleProperty::NIGHT_MODE):
         prop->value.int32Values[0] = 0;
         break;
diff --git a/automotive/vehicle/2.0/default/tests/VehicleHalManager_test.cpp b/automotive/vehicle/2.0/default/tests/VehicleHalManager_test.cpp
index f637344..b5cdf5c 100644
--- a/automotive/vehicle/2.0/default/tests/VehicleHalManager_test.cpp
+++ b/automotive/vehicle/2.0/default/tests/VehicleHalManager_test.cpp
@@ -68,15 +68,16 @@
                     pValue = getValuePool()->obtainFloat(42.42);
                 }
                 break;
-            case VehicleProperty::VEHICLE_MAP_SERVICE:
-                pValue = getValuePool()->obtainComplex();
-                pValue->value.int32Values = hidl_vec<int32_t> { 10, 20 };
-                pValue->value.int64Values = hidl_vec<int64_t> { 30, 40 };
-                pValue->value.floatValues = hidl_vec<float_t> { 1.1, 2.2 };
-                pValue->value.bytes = hidl_vec<uint8_t> { 1, 2, 3 };
-                pValue->value.stringValue = kCarMake;
-                break;
             default:
+                if (requestedPropValue.prop == kCustomComplexProperty) {
+                    pValue = getValuePool()->obtainComplex();
+                    pValue->value.int32Values = hidl_vec<int32_t> { 10, 20 };
+                    pValue->value.int64Values = hidl_vec<int64_t> { 30, 40 };
+                    pValue->value.floatValues = hidl_vec<float_t> { 1.1, 2.2 };
+                    pValue->value.bytes = hidl_vec<uint8_t> { 1, 2, 3 };
+                    pValue->value.stringValue = kCarMake;
+                    break;
+                }
                 auto key = makeKey(toInt(property), areaId);
                 if (mValues.count(key) == 0) {
                     ALOGW("");
@@ -318,10 +319,10 @@
 }
 
 TEST_F(VehicleHalManagerTest, get_Complex) {
-    invokeGet(toInt(VehicleProperty::VEHICLE_MAP_SERVICE), 0);
+    invokeGet(kCustomComplexProperty, 0);
 
     ASSERT_EQ(StatusCode::OK, actualStatusCode);
-    ASSERT_EQ(toInt(VehicleProperty::VEHICLE_MAP_SERVICE), actualValue.prop);
+    ASSERT_EQ(kCustomComplexProperty, actualValue.prop);
 
     ASSERT_EQ(3u, actualValue.value.bytes.size());
     ASSERT_EQ(1, actualValue.value.bytes[0]);
diff --git a/automotive/vehicle/2.0/default/tests/VehicleHalTestUtils.h b/automotive/vehicle/2.0/default/tests/VehicleHalTestUtils.h
index ce1ed7d..28e1a5a 100644
--- a/automotive/vehicle/2.0/default/tests/VehicleHalTestUtils.h
+++ b/automotive/vehicle/2.0/default/tests/VehicleHalTestUtils.h
@@ -29,6 +29,11 @@
 namespace vehicle {
 namespace V2_0 {
 
+constexpr int32_t kCustomComplexProperty = 0xbeef
+        | VehiclePropertyGroup::VENDOR
+        | VehiclePropertyType::COMPLEX
+        | VehicleArea::GLOBAL;
+
 const VehiclePropConfig kVehicleProperties[] = {
     {
         .prop = toInt(VehicleProperty::INFO_MAKE),
@@ -109,7 +114,7 @@
 
     // Complex data type.
     {
-        .prop = toInt(VehicleProperty::VEHICLE_MAP_SERVICE),
+        .prop = kCustomComplexProperty,
         .access = VehiclePropertyAccess::READ_WRITE,
         .changeMode = VehiclePropertyChangeMode::ON_CHANGE
     }
diff --git a/automotive/vehicle/2.0/types.hal b/automotive/vehicle/2.0/types.hal
index 0d2dfdd..b33b6ee 100644
--- a/automotive/vehicle/2.0/types.hal
+++ b/automotive/vehicle/2.0/types.hal
@@ -1790,26 +1790,6 @@
         | VehiclePropertyGroup:SYSTEM
         | VehiclePropertyType:BOOLEAN
         | VehicleArea:GLOBAL),
-
-    /*
-     * Vehicle Maps Service (VMS) message
-     *
-     * This property uses COMPLEX data to communicate vms messages.
-     *
-     * Its contents are to be interpreted as follows:
-     * the indices defined in VmsMessageIntegerValuesIndex are to be used to
-     * read from int32Values;
-     * bytes is a serialized VMS message as defined in the vms protocol
-     * which is opaque to the framework;
-     *
-     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
-     * @access VehiclePropertyAccess:READ_WRITE
-     */
-    VEHICLE_MAP_SERVICE = (
-        0x0C00
-        | VehiclePropertyGroup:SYSTEM
-        | VehiclePropertyType:COMPLEX
-        | VehicleArea:GLOBAL),
 };
 
 /*
@@ -2707,35 +2687,3 @@
     LEFT_REAR = 0x4,
     RIGHT_REAR = 0x8,
 };
-
-/*
- * This enum lists the types of supported VMS messages.
- */
-enum VmsMessageType : int32_t {
-  /* A client subscribes to a layer. */
-  SUBSCRIBE = 1,
-
-  /* A client unsubscribes from a layer. */
-  UNSUBSCRIBE = 2,
-
-  /* A client publishes a data packet. */
-  DATA = 3,
-};
-
-/*
- * This enum provides the canonical mapping for VMS properties that have an
- * integer value.
- */
-enum VmsMessageIntegerValuesIndex : int32_t {
-  /* The message type as enumerated by VmsMessageType enum. */
-  VMS_MESSAGE_TYPE = 0,
-
-  /* The layer ID as defined in the vms protocol. */
-  VMS_LAYER_ID = 1,
-
-  /* The version of the VMS layer. */
-  VMS_LAYER_VERSION = 2,
-
-  /* The number of bytes in the payload */
-  VMS_PAYLOAD_SIZE_BYTES = 3,
-};
diff --git a/automotive/vehicle/2.1/Android.mk b/automotive/vehicle/2.1/Android.mk
index f5a121d..f030af08 100644
--- a/automotive/vehicle/2.1/Android.mk
+++ b/automotive/vehicle/2.1/Android.mk
@@ -208,6 +208,44 @@
 LOCAL_GENERATED_SOURCES += $(GEN)
 
 #
+# Build types.hal (VmsMessageIntegerValuesIndex)
+#
+GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_1/VmsMessageIntegerValuesIndex.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.automotive.vehicle@2.1::types.VmsMessageIntegerValuesIndex
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (VmsMessageType)
+#
+GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_1/VmsMessageType.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.automotive.vehicle@2.1::types.VmsMessageType
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
 # Build IVehicle.hal
 #
 GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_1/IVehicle.java
@@ -434,6 +472,44 @@
 LOCAL_GENERATED_SOURCES += $(GEN)
 
 #
+# Build types.hal (VmsMessageIntegerValuesIndex)
+#
+GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_1/VmsMessageIntegerValuesIndex.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.automotive.vehicle@2.1::types.VmsMessageIntegerValuesIndex
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (VmsMessageType)
+#
+GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_1/VmsMessageType.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.automotive.vehicle@2.1::types.VmsMessageType
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
 # Build IVehicle.hal
 #
 GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_1/IVehicle.java
diff --git a/automotive/vehicle/2.1/default/impl/vhal_v2_1/DefaultConfig.h b/automotive/vehicle/2.1/default/impl/vhal_v2_1/DefaultConfig.h
index 769ae6d..6bdec59 100644
--- a/automotive/vehicle/2.1/default/impl/vhal_v2_1/DefaultConfig.h
+++ b/automotive/vehicle/2.1/default/impl/vhal_v2_1/DefaultConfig.h
@@ -59,6 +59,12 @@
         .prop = V2_0::toInt(V2_1::VehicleProperty::OBD2_FREEZE_FRAME_CLEAR),
         .access = V2_0::VehiclePropertyAccess::WRITE,
         .changeMode = V2_0::VehiclePropertyChangeMode::ON_CHANGE
+    },
+
+    {
+        .prop = V2_0::toInt(VehicleProperty::VEHICLE_MAP_SERVICE),
+        .access = V2_0::VehiclePropertyAccess::READ_WRITE,
+        .changeMode = V2_0::VehiclePropertyChangeMode::ON_CHANGE
     }
 };
 
diff --git a/automotive/vehicle/2.1/types.hal b/automotive/vehicle/2.1/types.hal
index f0dd95f..9b219b2 100644
--- a/automotive/vehicle/2.1/types.hal
+++ b/automotive/vehicle/2.1/types.hal
@@ -174,6 +174,26 @@
       | VehiclePropertyGroup:SYSTEM
       | VehiclePropertyType:COMPLEX
       | VehicleArea:GLOBAL),
+
+    /*
+     * Vehicle Maps Service (VMS) message
+     *
+     * This property uses COMPLEX data to communicate vms messages.
+     *
+     * Its contents are to be interpreted as follows:
+     * the indices defined in VmsMessageIntegerValuesIndex are to be used to
+     * read from int32Values;
+     * bytes is a serialized VMS message as defined in the vms protocol
+     * which is opaque to the framework;
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     */
+    VEHICLE_MAP_SERVICE = (
+        0x0C00
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:COMPLEX
+        | VehicleArea:GLOBAL),
 };
 
 /* The status of a fuel system as described by the OBD2 specification. */
@@ -551,3 +571,35 @@
 
   LAST_SYSTEM_INDEX = ENGINE_FUEL_RATE,
 };
+
+/*
+ * This enum lists the types of supported VMS messages.
+ */
+enum VmsMessageType : int32_t {
+  /* A client subscribes to a layer. */
+  SUBSCRIBE = 1,
+
+  /* A client unsubscribes from a layer. */
+  UNSUBSCRIBE = 2,
+
+  /* A client publishes a data packet. */
+  DATA = 3,
+};
+
+/*
+ * This enum provides the canonical mapping for VMS properties that have an
+ * integer value.
+ */
+enum VmsMessageIntegerValuesIndex : int32_t {
+  /* The message type as enumerated by VmsMessageType enum. */
+  VMS_MESSAGE_TYPE = 0,
+
+  /* The layer ID as defined in the vms protocol. */
+  VMS_LAYER_ID = 1,
+
+  /* The version of the VMS layer. */
+  VMS_LAYER_VERSION = 2,
+
+  /* The number of bytes in the payload */
+  VMS_PAYLOAD_SIZE_BYTES = 3,
+};
diff --git a/broadcastradio/1.0/vts/functional/VtsHalBroadcastradioV1_0TargetTest.cpp b/broadcastradio/1.0/vts/functional/VtsHalBroadcastradioV1_0TargetTest.cpp
index 4212729..0e5f1fb 100644
--- a/broadcastradio/1.0/vts/functional/VtsHalBroadcastradioV1_0TargetTest.cpp
+++ b/broadcastradio/1.0/vts/functional/VtsHalBroadcastradioV1_0TargetTest.cpp
@@ -305,6 +305,40 @@
 }
 
 /**
+ * Test IBroadcastRadio::openTuner() after ITuner disposal.
+ *
+ * Verifies that:
+ *  - ITuner destruction gets propagated through HAL
+ *  - the openTuner method works well when called for the second time
+ */
+TEST_F(BroadcastRadioHidlTest, ReopenTuner) {
+    EXPECT_TRUE(openTuner());
+    mTuner.clear();
+    EXPECT_TRUE(openTuner());
+}
+
+/**
+ * Test IBroadcastRadio::openTuner() method called twice.
+ *
+ * Verifies that:
+ *  - the openTuner method fails when called for the second time without deleting previous
+ *    ITuner instance
+ */
+TEST_F(BroadcastRadioHidlTest, OpenTunerTwice) {
+    EXPECT_TRUE(openTuner());
+
+    Result halResult = Result::NOT_INITIALIZED;
+    Return<void> hidlReturn =
+            mRadio->openTuner(mHalProperties.bands[0], true, mTunerCallback,
+                              [&](Result result, const sp<ITuner>&) {
+                    halResult = result;
+                });
+    EXPECT_TRUE(hidlReturn.isOk());
+    EXPECT_EQ(Result::INVALID_STATE, halResult);
+    EXPECT_TRUE(waitForCallback(kConfigCallbacktimeoutNs));
+}
+
+/**
  * Test ITuner::setConfiguration() and getConfiguration methods
  *
  * Verifies that:
diff --git a/camera/Android.bp b/camera/Android.bp
index e379e49..3869766 100644
--- a/camera/Android.bp
+++ b/camera/Android.bp
@@ -3,6 +3,7 @@
     "common/1.0",
     "common/1.0/default",
     "device/1.0",
+    "device/1.0/default",
     "device/3.2",
     "device/3.2/default",
     "metadata/3.2",
diff --git a/camera/common/1.0/default/Android.bp b/camera/common/1.0/default/Android.bp
index af0ff6e..9ec266c 100644
--- a/camera/common/1.0/default/Android.bp
+++ b/camera/common/1.0/default/Android.bp
@@ -1,6 +1,10 @@
 cc_library_static {
     name: "android.hardware.camera.common@1.0-helper",
-    srcs: ["CameraModule.cpp", "CameraMetadata.cpp", "VendorTagDescriptor.cpp"],
+    srcs: [
+        "CameraModule.cpp",
+        "CameraMetadata.cpp",
+        "VendorTagDescriptor.cpp",
+        "HandleImporter.cpp"],
     cflags: [
         "-Werror",
         "-Wextra",
@@ -13,3 +17,4 @@
     include_dirs: ["system/media/private/camera/include"],
     export_include_dirs : ["include"]
 }
+
diff --git a/camera/common/1.0/default/HandleImporter.cpp b/camera/common/1.0/default/HandleImporter.cpp
new file mode 100644
index 0000000..dee2973
--- /dev/null
+++ b/camera/common/1.0/default/HandleImporter.cpp
@@ -0,0 +1,190 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "HandleImporter"
+#include <utils/Log.h>
+#include "HandleImporter.h"
+
+namespace android {
+namespace hardware {
+namespace camera {
+namespace common {
+namespace V1_0 {
+namespace helper {
+
+HandleImporter HandleImporter::sHandleImporter;
+
+HandleImporter& HandleImporter::getInstance() {
+    sHandleImporter.initialize();
+    return sHandleImporter;
+}
+
+bool HandleImporter::initialize() {
+    // allow only one client
+    if (mInitialized) {
+        return false;
+    }
+
+    if (!openGralloc()) {
+        return false;
+    }
+
+    mInitialized = true;
+    return true;
+}
+
+void HandleImporter::cleanup() {
+    if (!mInitialized) {
+        return;
+    }
+
+    closeGralloc();
+    mInitialized = false;
+}
+
+// In IComposer, any buffer_handle_t is owned by the caller and we need to
+// make a clone for hwcomposer2.  We also need to translate empty handle
+// to nullptr.  This function does that, in-place.
+bool HandleImporter::importBuffer(buffer_handle_t& handle) {
+    if (!handle->numFds && !handle->numInts) {
+        handle = nullptr;
+        return true;
+    }
+
+    buffer_handle_t clone = cloneBuffer(handle);
+    if (!clone) {
+        return false;
+    }
+
+    handle = clone;
+    return true;
+}
+
+void HandleImporter::freeBuffer(buffer_handle_t handle) {
+    if (!handle) {
+        return;
+    }
+
+    releaseBuffer(handle);
+}
+
+bool HandleImporter::importFence(const native_handle_t* handle, int& fd) {
+    if (handle == nullptr || handle->numFds == 0) {
+        fd = -1;
+    } else if (handle->numFds == 1) {
+        fd = dup(handle->data[0]);
+        if (fd < 0) {
+            ALOGE("failed to dup fence fd %d", handle->data[0]);
+            return false;
+        }
+    } else {
+        ALOGE("invalid fence handle with %d file descriptors",
+                handle->numFds);
+        return false;
+    }
+
+    return true;
+}
+
+void HandleImporter::closeFence(int fd) {
+    if (fd >= 0) {
+        close(fd);
+    }
+}
+
+bool HandleImporter::openGralloc() {
+    const hw_module_t* module;
+    int err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module);
+    if (err) {
+        ALOGE("failed to get gralloc module");
+        return false;
+    }
+
+    uint8_t major = (module->module_api_version >> 8) & 0xff;
+    if (major > 1) {
+        ALOGE("unknown gralloc module major version %d", major);
+        return false;
+    }
+
+    if (major == 1) {
+        err = gralloc1_open(module, &mDevice);
+        if (err) {
+            ALOGE("failed to open gralloc1 device");
+            return false;
+        }
+
+        mRetain = reinterpret_cast<GRALLOC1_PFN_RETAIN>(
+                mDevice->getFunction(mDevice, GRALLOC1_FUNCTION_RETAIN));
+        mRelease = reinterpret_cast<GRALLOC1_PFN_RELEASE>(
+                mDevice->getFunction(mDevice, GRALLOC1_FUNCTION_RELEASE));
+        if (!mRetain || !mRelease) {
+            ALOGE("invalid gralloc1 device");
+            gralloc1_close(mDevice);
+            return false;
+        }
+    } else {
+        mModule = reinterpret_cast<const gralloc_module_t*>(module);
+    }
+
+    return true;
+}
+
+void HandleImporter::closeGralloc() {
+    if (mDevice) {
+        gralloc1_close(mDevice);
+    }
+}
+
+buffer_handle_t HandleImporter::cloneBuffer(buffer_handle_t handle) {
+    native_handle_t* clone = native_handle_clone(handle);
+    if (!clone) {
+        ALOGE("failed to clone buffer %p", handle);
+        return nullptr;
+    }
+
+    bool err;
+    if (mDevice) {
+        err = (mRetain(mDevice, clone) != GRALLOC1_ERROR_NONE);
+    } else {
+        err = (mModule->registerBuffer(mModule, clone) != 0);
+    }
+
+    if (err) {
+        ALOGE("failed to retain/register buffer %p", clone);
+        native_handle_close(clone);
+        native_handle_delete(clone);
+        return nullptr;
+    }
+
+    return clone;
+}
+
+void HandleImporter::releaseBuffer(buffer_handle_t handle) {
+    if (mDevice) {
+        mRelease(mDevice, handle);
+    } else {
+        mModule->unregisterBuffer(mModule, handle);
+    }
+    native_handle_close(handle);
+    native_handle_delete(const_cast<native_handle_t*>(handle));
+}
+
+} // namespace helper
+} // namespace V1_0
+} // namespace common
+} // namespace camera
+} // namespace hardware
+} // namespace android
diff --git a/camera/common/1.0/default/include/CameraModule.h b/camera/common/1.0/default/include/CameraModule.h
index 68d4f90..9fbfbd5 100644
--- a/camera/common/1.0/default/include/CameraModule.h
+++ b/camera/common/1.0/default/include/CameraModule.h
@@ -20,6 +20,7 @@
 #include <hardware/camera.h>
 #include <utils/Mutex.h>
 #include <utils/KeyedVector.h>
+#include <utils/RefBase.h>
 
 #include "CameraMetadata.h"
 
diff --git a/camera/common/1.0/default/include/HandleImporter.h b/camera/common/1.0/default/include/HandleImporter.h
new file mode 100644
index 0000000..def8982
--- /dev/null
+++ b/camera/common/1.0/default/include/HandleImporter.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef CAMERA_COMMON_1_0_HANDLEIMPORTED_H
+#define CAMERA_COMMON_1_0_HANDLEIMPORTED_H
+
+#include <hardware/gralloc.h>
+#include <hardware/gralloc1.h>
+#include <system/window.h>
+
+namespace android {
+namespace hardware {
+namespace camera {
+namespace common {
+namespace V1_0 {
+namespace helper {
+
+// Borrowed from graphics HAL. Use this until gralloc mapper HAL is working
+class HandleImporter {
+public:
+    static HandleImporter& getInstance();
+
+    // In IComposer, any buffer_handle_t is owned by the caller and we need to
+    // make a clone for hwcomposer2.  We also need to translate empty handle
+    // to nullptr.  This function does that, in-place.
+    bool importBuffer(buffer_handle_t& handle);
+    void freeBuffer(buffer_handle_t handle);
+    bool importFence(const native_handle_t* handle, int& fd);
+    void closeFence(int fd);
+
+private:
+
+    HandleImporter() : mInitialized(false) {}
+    bool initialize();
+    void cleanup();
+    bool openGralloc();
+    void closeGralloc();
+    buffer_handle_t cloneBuffer(buffer_handle_t handle);
+    void releaseBuffer(buffer_handle_t handle);
+
+    static HandleImporter sHandleImporter;
+    bool mInitialized;
+
+    // gralloc1
+    gralloc1_device_t* mDevice;
+    GRALLOC1_PFN_RETAIN mRetain;
+    GRALLOC1_PFN_RELEASE mRelease;
+
+    // gralloc0
+    const gralloc_module_t* mModule;
+};
+
+} // namespace helper
+} // namespace V1_0
+} // namespace common
+} // namespace camera
+} // namespace hardware
+} // namespace android
+
+#endif // CAMERA_COMMON_1_0_HANDLEIMPORTED_H
\ No newline at end of file
diff --git a/camera/device/1.0/ICameraDevice.hal b/camera/device/1.0/ICameraDevice.hal
index d232a67..4a3a406 100644
--- a/camera/device/1.0/ICameraDevice.hal
+++ b/camera/device/1.0/ICameraDevice.hal
@@ -298,7 +298,8 @@
     recordingEnabled() generates (bool enabled);
 
     /**
-     * Release a record frame previously returned by CAMERA_MSG_VIDEO_FRAME.
+     * Release a record frame previously returned by CAMERA_MSG_VIDEO_FRAME in
+     * dataCallbackTimestamp.
      *
      * It is camera HAL client's responsibility to release video recording
      * frames sent out by the camera HAL before the camera HAL receives a call
@@ -306,10 +307,26 @@
      * disableMsgType(CAMERA_MSG_VIDEO_FRAME), it is the camera HAL's
      * responsibility to manage the life-cycle of the video recording frames.
      *
-     * @param data The memory buffer to release a recording frame from.
+     * @param memId The memory buffer to release a recording frame from.
      * @param bufferIndex The specific buffer index to return to the HAL.
      */
-    releaseRecordingFrame(MemoryId data, uint32_t bufferIndex);
+    releaseRecordingFrame(MemoryId memId, uint32_t bufferIndex);
+
+    /**
+     * Release a record frame previously returned by CAMERA_MSG_VIDEO_FRAME in
+     * handleCallbackTimestamp.
+     *
+     * It is camera HAL client's responsibility to release video recording
+     * frames sent out by the camera HAL before the camera HAL receives a call
+     * to disableMsgType(CAMERA_MSG_VIDEO_FRAME). After it receives the call to
+     * disableMsgType(CAMERA_MSG_VIDEO_FRAME), it is the camera HAL's
+     * responsibility to manage the life-cycle of the video recording frames.
+     *
+     * @param memId The memory buffer to release a recording frame from.
+     * @param bufferIndex The specific buffer index to return to the HAL.
+     * @param frame The handle for a released video frame
+     */
+    releaseRecordingFrameHandle(MemoryId memId, uint32_t bufferIndex, handle frame);
 
     /**
      * Start auto focus.
@@ -352,14 +369,14 @@
     /**
      * Set the camera parameters.
      *
-     * @param parms The parameter string, consisting of
+     * @param params The parameter string, consisting of
      *    '<key1>=<value1>; ...;<keyN>=<valueN>'.
      * @return status The status code for this operation:
      *     OK: Parameter update was successful
      *     ILLEGAL_ARGUMENT: At least one parameter was invalid or not supported
      *
      */
-    setParameters(string parms) generates (Status status);
+    setParameters(string params) generates (Status status);
 
     /**
      * Retrieve the camera parameters.
diff --git a/camera/device/1.0/ICameraDeviceCallback.hal b/camera/device/1.0/ICameraDeviceCallback.hal
index 97014ee..1b0db24 100644
--- a/camera/device/1.0/ICameraDeviceCallback.hal
+++ b/camera/device/1.0/ICameraDeviceCallback.hal
@@ -42,8 +42,10 @@
      * @param bufferCount The number of contiguous buffers that the descriptor
      *     contains.
      *
-     * @return memId A integer identifier for this memory buffer, for use with
-     *     data callbacks and unregistering memory.
+     * @return memId A positive integer identifier for this memory buffer, for
+     *     use with data callbacks and unregistering memory. 0 must be returned
+     *     in case of error, such as if the descriptor does not contain exactly
+     *     one FD.
      */
     registerMemory(handle descriptor, uint32_t bufferSize, uint32_t bufferCount)
             generates (MemoryId memId);
@@ -62,7 +64,8 @@
      *     starts.
      *
      */
-    dataCallback(DataCallbackMsg msgType, MemoryId data, uint32_t bufferIndex);
+    dataCallback(DataCallbackMsg msgType, MemoryId data, uint32_t bufferIndex,
+            CameraFrameMetadata metadata);
 
     /**
      * Send a buffer of image data to the camera service, with a timestamp
@@ -78,4 +81,21 @@
     dataCallbackTimestamp(DataCallbackMsg msgType, MemoryId data, uint32_t bufferIndex,
             int64_t timestamp);
 
+    /**
+     * Send a buffer of image data to the camera service, with a timestamp
+     *
+     * @param msgType The kind of image buffer data this call represents.
+     * @param handle The handle of image buffer data this call represents.
+     * @param data A memory handle to the buffer containing the data.
+     * @param bufferIndex The offset into the memory handle where the buffer
+     *     starts.
+     * @param timestamp The time this buffer was captured by the camera, in
+     *     nanoseconds.
+     *
+     * @return frameId a frame ID to be used with releaseRecordingFrameId later
+     *
+     */
+    handleCallbackTimestamp(DataCallbackMsg msgType, handle frameData, MemoryId data,
+            uint32_t bufferIndex, int64_t timestamp);
+
 };
diff --git a/camera/device/1.0/ICameraDevicePreviewCallback.hal b/camera/device/1.0/ICameraDevicePreviewCallback.hal
index ebc7460..4c9b517 100644
--- a/camera/device/1.0/ICameraDevicePreviewCallback.hal
+++ b/camera/device/1.0/ICameraDevicePreviewCallback.hal
@@ -30,28 +30,31 @@
      *
      * @return status The status code for this operation. If not OK, then
      *     buffer and stride must not be used.
-     * @return buffer A handle to the buffer to write into.
+     * @return bufferId A unique ID for the returned buffer.
+     * @return buffer A handle to the buffer to write into. Must be non-null if the bufferId has not
+     *     been seen by HAL before. Must be null if the bufferId is seen before. HAL must keep track
+     *     of the bufferId to actual buffer handle mapping.
      * @return stride The stride between two rows of pixels in this buffer.
      */
-    dequeueBuffer() generates (Status status, handle buffer, uint32_t stride);
+    dequeueBuffer() generates (Status status, uint64_t bufferId, handle buffer, uint32_t stride);
 
     /**
      * Send a filled preview buffer to its consumer.
      *
-     * @param buffer The handle to the preview buffer that's been filled.
+     * @param bufferId The bufferId of the preview buffer
      * @return status The status code for this operation.
      */
-    enqueueBuffer(handle buffer) generates (Status status);
+    enqueueBuffer(uint64_t bufferId) generates (Status status);
 
     /**
      * Return a preview buffer unfilled. This buffer must not be sent on to the
      * preview consumer as a valid buffer, but may be reused as if it were
      * empty.
      *
-     * @param buffer The handle to the preview buffer to return.
+     * @param bufferId The bufferId of the preview buffer
      * @return status The status code for this operation.
      */
-    cancelBuffer(handle buffer) generates (Status status);
+    cancelBuffer(uint64_t bufferId) generates (Status status);
 
     /**
      * Set the number of preview buffers needed by the HAL.
diff --git a/camera/device/1.0/default/Android.bp b/camera/device/1.0/default/Android.bp
new file mode 100644
index 0000000..1663787
--- /dev/null
+++ b/camera/device/1.0/default/Android.bp
@@ -0,0 +1,27 @@
+cc_library_shared {
+    name: "camera.device@1.0-impl",
+    srcs: [
+        "CameraDevice.cpp",
+    ],
+    shared_libs: [
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "libutils",
+        "android.hardware.camera.device@1.0",
+        "android.hardware.camera.common@1.0",
+        "android.hardware.graphics.allocator@2.0",
+        "android.hardware.graphics.common@1.0",
+        "android.hidl.base@1.0",
+        "libcutils",
+        "liblog",
+        "libhardware",
+        "libcamera_metadata",
+        "libbinder",
+    ],
+    static_libs: [
+        "android.hardware.camera.common@1.0-helper"
+    ],
+    export_include_dirs: ["."]
+}
+
diff --git a/camera/device/1.0/default/CameraDevice.cpp b/camera/device/1.0/default/CameraDevice.cpp
new file mode 100644
index 0000000..819525b
--- /dev/null
+++ b/camera/device/1.0/default/CameraDevice.cpp
@@ -0,0 +1,948 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "CamDev@1.0-impl"
+#include <utils/Log.h>
+#include <hardware/camera.h>
+#include <hardware/gralloc1.h>
+#include <utils/Trace.h>
+
+#include "CameraDevice_1_0.h"
+
+namespace android {
+namespace hardware {
+namespace camera {
+namespace device {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::graphics::allocator::V2_0::ProducerUsage;
+using ::android::hardware::graphics::common::V1_0::PixelFormat;
+
+HandleImporter& CameraDevice::sHandleImporter = HandleImporter::getInstance();
+
+Status CameraDevice::getHidlStatus(const int& status) {
+    switch (status) {
+        case 0: return Status::OK;
+        case -ENOSYS: return Status::OPERATION_NOT_SUPPORTED;
+        case -EBUSY : return Status::CAMERA_IN_USE;
+        case -EUSERS: return Status::MAX_CAMERAS_IN_USE;
+        case -ENODEV: return Status::INTERNAL_ERROR;
+        case -EINVAL: return Status::ILLEGAL_ARGUMENT;
+        default:
+            ALOGE("%s: unknown HAL status code %d", __FUNCTION__, status);
+            return Status::INTERNAL_ERROR;
+    }
+}
+
+status_t CameraDevice::getStatusT(const Status& s)  {
+    switch(s) {
+        case Status::OK:
+            return OK;
+        case Status::ILLEGAL_ARGUMENT:
+            return BAD_VALUE;
+        case Status::CAMERA_IN_USE:
+            return -EBUSY;
+        case Status::MAX_CAMERAS_IN_USE:
+            return -EUSERS;
+        case Status::METHOD_NOT_SUPPORTED:
+            return UNKNOWN_TRANSACTION;
+        case Status::OPERATION_NOT_SUPPORTED:
+            return INVALID_OPERATION;
+        case Status::CAMERA_DISCONNECTED:
+            return DEAD_OBJECT;
+        case Status::INTERNAL_ERROR:
+            return INVALID_OPERATION;
+    }
+    ALOGW("Unexpected HAL status code %d", s);
+    return INVALID_OPERATION;
+}
+
+Status CameraDevice::initStatus() const {
+    Mutex::Autolock _l(mLock);
+    Status status = Status::OK;
+    if (mInitFail) {
+        status = Status::INTERNAL_ERROR;
+    } else if (mDisconnected) {
+        status = Status::CAMERA_DISCONNECTED;
+    }
+    return status;
+}
+
+CameraDevice::CameraDevice(
+    sp<CameraModule> module, const std::string& cameraId,
+    const SortedVector<std::pair<std::string, std::string>>& cameraDeviceNames) :
+        mModule(module),
+        mCameraId(cameraId),
+        mDisconnected(false),
+        mCameraDeviceNames(cameraDeviceNames) {
+    mCameraIdInt = atoi(mCameraId.c_str());
+    // Should not reach here as provider also validate ID
+    if (mCameraIdInt < 0 || mCameraIdInt >= module->getNumberOfCameras()) {
+        ALOGE("%s: Invalid camera id: %s", __FUNCTION__, mCameraId.c_str());
+        mInitFail = true;
+    }
+
+    mDeviceVersion = mModule->getDeviceVersion(mCameraIdInt);
+    if (mDeviceVersion != CAMERA_DEVICE_API_VERSION_1_0 && !mModule->isOpenLegacyDefined()) {
+        ALOGI("%s: Camera id %s does not support HAL1.0",
+                __FUNCTION__, mCameraId.c_str());
+        mInitFail = true;
+    }
+}
+
+CameraDevice::~CameraDevice() {
+    Mutex::Autolock _l(mLock);
+    if (mDevice != nullptr) {
+        ALOGW("%s: camera %s is deleted while open", __FUNCTION__, mCameraId.c_str());
+        close();
+    }
+    mHalPreviewWindow.cleanUpCirculatingBuffers();
+}
+
+
+void CameraDevice::setConnectionStatus(bool connected) {
+    Mutex::Autolock _l(mLock);
+    mDisconnected = !connected;
+    if (mDevice == nullptr) {
+        return;
+    }
+    if (!connected) {
+        ALOGW("%s: camera %s is disconneted. Closing", __FUNCTION__, mCameraId.c_str());
+        close();
+    }
+    return;
+}
+
+void CameraDevice::CameraPreviewWindow::cleanUpCirculatingBuffers() {
+    Mutex::Autolock _l(mLock);
+    for (auto pair : mCirculatingBuffers) {
+        sHandleImporter.freeBuffer(pair.second);
+    }
+    mCirculatingBuffers.clear();
+    mBufferIdMap.clear();
+}
+
+int CameraDevice::sDequeueBuffer(struct preview_stream_ops* w,
+                                   buffer_handle_t** buffer, int *stride) {
+    CameraPreviewWindow* object = static_cast<CameraPreviewWindow*>(w);
+    if (object->mPreviewCallback == nullptr) {
+        ALOGE("%s: camera HAL calling preview ops while there is no preview window!", __FUNCTION__);
+        return INVALID_OPERATION;
+    }
+
+    if (buffer == nullptr || stride == nullptr) {
+        ALOGE("%s: buffer (%p) and stride (%p) must not be null!", __FUNCTION__, buffer, stride);
+        return BAD_VALUE;
+    }
+
+    Status s;
+    object->mPreviewCallback->dequeueBuffer(
+        [&](auto status, uint64_t bufferId, const auto& buf, uint32_t strd) {
+            s = status;
+            if (s == Status::OK) {
+                Mutex::Autolock _l(object->mLock);
+                if (object->mCirculatingBuffers.count(bufferId) == 0) {
+                    buffer_handle_t importedBuf = buf.getNativeHandle();
+                    sHandleImporter.importBuffer(importedBuf);
+                    if (importedBuf == nullptr) {
+                        ALOGE("%s: preview buffer import failed!", __FUNCTION__);
+                        s = Status::INTERNAL_ERROR;
+                        return;
+                    } else {
+                        object->mCirculatingBuffers[bufferId] = importedBuf;
+                        object->mBufferIdMap[&(object->mCirculatingBuffers[bufferId])] = bufferId;
+                    }
+                }
+                *buffer = &(object->mCirculatingBuffers[bufferId]);
+                *stride = strd;
+            }
+        });
+    return getStatusT(s);
+}
+
+int CameraDevice::sLockBuffer(struct preview_stream_ops*, buffer_handle_t*) {
+    // TODO: make sure lock_buffer is indeed a no-op (and will always be)
+    return 0;
+}
+
+int CameraDevice::sEnqueueBuffer(struct preview_stream_ops* w, buffer_handle_t* buffer) {
+    CameraPreviewWindow* object = static_cast<CameraPreviewWindow*>(w);
+    if (object->mPreviewCallback == nullptr) {
+        ALOGE("%s: camera HAL calling preview ops while there is no preview window!", __FUNCTION__);
+        return INVALID_OPERATION;
+    }
+    uint64_t bufferId = object->mBufferIdMap.at(buffer);
+    return getStatusT(object->mPreviewCallback->enqueueBuffer(bufferId));
+}
+
+int CameraDevice::sCancelBuffer(struct preview_stream_ops* w, buffer_handle_t* buffer) {
+    CameraPreviewWindow* object = static_cast<CameraPreviewWindow*>(w);
+    if (object->mPreviewCallback == nullptr) {
+        ALOGE("%s: camera HAL calling preview ops while there is no preview window!", __FUNCTION__);
+        return INVALID_OPERATION;
+    }
+    uint64_t bufferId = object->mBufferIdMap.at(buffer);
+    return getStatusT(object->mPreviewCallback->cancelBuffer(bufferId));
+}
+
+int CameraDevice::sSetBufferCount(struct preview_stream_ops* w, int count) {
+    CameraPreviewWindow* object = static_cast<CameraPreviewWindow*>(w);
+    if (object->mPreviewCallback == nullptr) {
+        ALOGE("%s: camera HAL calling preview ops while there is no preview window!", __FUNCTION__);
+        return INVALID_OPERATION;
+    }
+
+    object->cleanUpCirculatingBuffers();
+    return getStatusT(object->mPreviewCallback->setBufferCount(count));
+}
+
+int CameraDevice::sSetBuffersGeometry(struct preview_stream_ops* w,
+                                         int width, int height, int format) {
+    CameraPreviewWindow* object = static_cast<CameraPreviewWindow*>(w);
+    if (object->mPreviewCallback == nullptr) {
+        ALOGE("%s: camera HAL calling preview ops while there is no preview window!", __FUNCTION__);
+        return INVALID_OPERATION;
+    }
+
+    object->cleanUpCirculatingBuffers();
+    return getStatusT(
+            object->mPreviewCallback->setBuffersGeometry(width, height, (PixelFormat) format));
+}
+
+int CameraDevice::sSetCrop(struct preview_stream_ops *w,
+                             int left, int top, int right, int bottom) {
+    CameraPreviewWindow* object = static_cast<CameraPreviewWindow*>(w);
+    if (object->mPreviewCallback == nullptr) {
+        ALOGE("%s: camera HAL calling preview ops while there is no preview window!", __FUNCTION__);
+        return INVALID_OPERATION;
+    }
+
+    return getStatusT(object->mPreviewCallback->setCrop(left, top, right, bottom));
+}
+
+int CameraDevice::sSetTimestamp(struct preview_stream_ops *w, int64_t timestamp) {
+    CameraPreviewWindow* object = static_cast<CameraPreviewWindow*>(w);
+    if (object->mPreviewCallback == nullptr) {
+        ALOGE("%s: camera HAL calling preview ops while there is no preview window!", __FUNCTION__);
+        return INVALID_OPERATION;
+    }
+
+    return getStatusT(object->mPreviewCallback->setTimestamp(timestamp));
+}
+
+int CameraDevice::sSetUsage(struct preview_stream_ops* w, int usage) {
+    CameraPreviewWindow* object = static_cast<CameraPreviewWindow*>(w);
+    if (object->mPreviewCallback == nullptr) {
+        ALOGE("%s: camera HAL calling preview ops while there is no preview window!", __FUNCTION__);
+        return INVALID_OPERATION;
+    }
+
+    object->cleanUpCirculatingBuffers();
+    return getStatusT(object->mPreviewCallback->setUsage((ProducerUsage) usage));
+}
+
+int CameraDevice::sSetSwapInterval(struct preview_stream_ops *w, int interval) {
+    CameraPreviewWindow* object = static_cast<CameraPreviewWindow*>(w);
+    if (object->mPreviewCallback == nullptr) {
+        ALOGE("%s: camera HAL calling preview ops while there is no preview window!", __FUNCTION__);
+        return INVALID_OPERATION;
+    }
+
+    return getStatusT(object->mPreviewCallback->setSwapInterval(interval));
+}
+
+int CameraDevice::sGetMinUndequeuedBufferCount(
+                  const struct preview_stream_ops *w,
+                  int *count) {
+    const CameraPreviewWindow* object =  static_cast<const CameraPreviewWindow*>(w);
+    if (object->mPreviewCallback == nullptr) {
+        ALOGE("%s: camera HAL calling preview ops while there is no preview window!", __FUNCTION__);
+        return INVALID_OPERATION;
+    }
+    if (count == nullptr) {
+        ALOGE("%s: count is null!", __FUNCTION__);
+        return BAD_VALUE;
+    }
+
+    Status s;
+    object->mPreviewCallback->getMinUndequeuedBufferCount(
+        [&](auto status, uint32_t cnt) {
+            s = status;
+            if (s == Status::OK) {
+                *count = cnt;
+            }
+        });
+    return getStatusT(s);
+}
+
+CameraDevice::CameraHeapMemory::CameraHeapMemory(int fd, size_t buf_size, uint_t num_buffers) :
+        mBufSize(buf_size),
+        mNumBufs(num_buffers) {
+    mHeap = new MemoryHeapBase(fd, buf_size * num_buffers);
+    commonInitialization();
+}
+
+CameraDevice::CameraHeapMemory::CameraHeapMemory(size_t buf_size, uint_t num_buffers) :
+        mBufSize(buf_size),
+        mNumBufs(num_buffers) {
+    mHeap = new MemoryHeapBase(buf_size * num_buffers);
+    commonInitialization();
+}
+
+void CameraDevice::CameraHeapMemory::commonInitialization() {
+    handle.data = mHeap->base();
+    handle.size = mBufSize * mNumBufs;
+    handle.handle = this;
+
+    mBuffers = new sp<MemoryBase>[mNumBufs];
+    for (uint_t i = 0; i < mNumBufs; i++) {
+        mBuffers[i] = new MemoryBase(mHeap, i * mBufSize, mBufSize);
+    }
+
+    handle.release = sPutMemory;
+}
+
+CameraDevice::CameraHeapMemory::~CameraHeapMemory() {
+    delete [] mBuffers;
+}
+
+// shared memory methods
+camera_memory_t* CameraDevice::sGetMemory(int fd, size_t buf_size, uint_t num_bufs, void *user) {
+    ALOGV("%s", __FUNCTION__);
+    CameraDevice* object = static_cast<CameraDevice*>(user);
+    if (object->mDeviceCallback == nullptr) {
+        ALOGE("%s: camera HAL request memory while camera is not opened!", __FUNCTION__);
+        return nullptr;
+    }
+
+    CameraHeapMemory* mem;
+    native_handle_t* handle = native_handle_create(1,0);
+
+    if (handle == nullptr) {
+        ALOGE("%s: native_handle_create failed!", __FUNCTION__);
+        return nullptr;
+    }
+
+    if (fd < 0) {
+        mem = new CameraHeapMemory(buf_size, num_bufs);
+    } else {
+        mem = new CameraHeapMemory(fd, buf_size, num_bufs);
+    }
+    handle->data[0] = mem->mHeap->getHeapID();
+    mem->incStrong(mem);
+
+    hidl_handle hidlHandle = handle;
+    MemoryId id = object->mDeviceCallback->registerMemory(hidlHandle, buf_size, num_bufs);
+    mem->handle.mId = id;
+    if (object->mMemoryMap.count(id) != 0) {
+        ALOGE("%s: duplicate MemoryId %d returned by client!", __FUNCTION__, id);
+    }
+    object->mMemoryMap[id] = mem;
+    mem->handle.mDevice = object;
+    native_handle_delete(handle);
+    return &mem->handle;
+}
+
+void CameraDevice::sPutMemory(camera_memory_t *data) {
+    if (!data)
+        return;
+
+    CameraHeapMemory* mem = static_cast<CameraHeapMemory *>(data->handle);
+    CameraDevice* device = mem->handle.mDevice;
+    if (device == nullptr) {
+        ALOGE("%s: camera HAL return memory for a null device!", __FUNCTION__);
+    }
+    if (device->mDeviceCallback == nullptr) {
+        ALOGE("%s: camera HAL return memory while camera is not opened!", __FUNCTION__);
+    }
+    device->mDeviceCallback->unregisterMemory(mem->handle.mId);
+    device->mMemoryMap.erase(mem->handle.mId);
+    mem->decStrong(mem);
+}
+
+// Callback forwarding methods
+void CameraDevice::sNotifyCb(int32_t msg_type, int32_t ext1, int32_t ext2, void *user) {
+    ALOGV("%s", __FUNCTION__);
+    CameraDevice* object = static_cast<CameraDevice*>(user);
+    if (object->mDeviceCallback != nullptr) {
+        object->mDeviceCallback->notifyCallback((NotifyCallbackMsg) msg_type, ext1, ext2);
+    }
+}
+
+void CameraDevice::sDataCb(int32_t msg_type, const camera_memory_t *data, unsigned int index,
+        camera_frame_metadata_t *metadata, void *user) {
+    ALOGV("%s", __FUNCTION__);
+    CameraDevice* object = static_cast<CameraDevice*>(user);
+    sp<CameraHeapMemory> mem(static_cast<CameraHeapMemory*>(data->handle));
+    if (index >= mem->mNumBufs) {
+        ALOGE("%s: invalid buffer index %d, max allowed is %d", __FUNCTION__,
+             index, mem->mNumBufs);
+        return;
+    }
+    if (object->mDeviceCallback != nullptr) {
+        CameraFrameMetadata hidlMetadata;
+        if (metadata) {
+            hidlMetadata.faces.resize(metadata->number_of_faces);
+            for (size_t i = 0; i < hidlMetadata.faces.size(); i++) {
+                hidlMetadata.faces[i].score = metadata->faces[i].score;
+                hidlMetadata.faces[i].id = metadata->faces[i].id;
+                for (int k = 0; k < 4; k++) {
+                    hidlMetadata.faces[i].rect[k] = metadata->faces[i].rect[k];
+                }
+                for (int k = 0; k < 2; k++) {
+                    hidlMetadata.faces[i].leftEye[k] = metadata->faces[i].left_eye[k];
+                }
+                for (int k = 0; k < 2; k++) {
+                    hidlMetadata.faces[i].rightEye[k] = metadata->faces[i].right_eye[k];
+                }
+                for (int k = 0; k < 2; k++) {
+                    hidlMetadata.faces[i].mouth[k] = metadata->faces[i].mouth[k];
+                }
+            }
+        }
+        CameraHeapMemory* mem = static_cast<CameraHeapMemory *>(data->handle);
+        object->mDeviceCallback->dataCallback(
+                (DataCallbackMsg) msg_type, mem->handle.mId, index, hidlMetadata);
+    }
+}
+
+void CameraDevice::sDataCbTimestamp(nsecs_t timestamp, int32_t msg_type,
+        const camera_memory_t *data, unsigned index, void *user) {
+    ALOGV("%s", __FUNCTION__);
+    CameraDevice* object = static_cast<CameraDevice*>(user);
+    // Start refcounting the heap object from here on.  When the clients
+    // drop all references, it will be destroyed (as well as the enclosed
+    // MemoryHeapBase.
+    sp<CameraHeapMemory> mem(static_cast<CameraHeapMemory*>(data->handle));
+    if (index >= mem->mNumBufs) {
+        ALOGE("%s: invalid buffer index %d, max allowed is %d", __FUNCTION__,
+             index, mem->mNumBufs);
+        return;
+    }
+
+    native_handle_t* handle = nullptr;
+    if (object->mMetadataMode) {
+        if (mem->mBufSize == sizeof(VideoNativeHandleMetadata)) {
+            VideoNativeHandleMetadata* md = (VideoNativeHandleMetadata*)
+                    mem->mBuffers[index]->pointer();
+            if (md->eType == VideoNativeHandleMetadata::kMetadataBufferTypeNativeHandleSource) {
+                handle = md->pHandle;
+            }
+        }
+    }
+
+    if (object->mDeviceCallback != nullptr) {
+        if (handle == nullptr) {
+            object->mDeviceCallback->dataCallbackTimestamp(
+                    (DataCallbackMsg) msg_type, mem->handle.mId, index, timestamp);
+        } else {
+            object->mDeviceCallback->handleCallbackTimestamp(
+                    (DataCallbackMsg) msg_type, handle, mem->handle.mId, index, timestamp);
+        }
+    }
+}
+
+void CameraDevice::initHalPreviewWindow()
+{
+    mHalPreviewWindow.cancel_buffer = sCancelBuffer;
+    mHalPreviewWindow.lock_buffer = sLockBuffer;
+    mHalPreviewWindow.dequeue_buffer = sDequeueBuffer;
+    mHalPreviewWindow.enqueue_buffer = sEnqueueBuffer;
+    mHalPreviewWindow.set_buffer_count = sSetBufferCount;
+    mHalPreviewWindow.set_buffers_geometry = sSetBuffersGeometry;
+    mHalPreviewWindow.set_crop = sSetCrop;
+    mHalPreviewWindow.set_timestamp = sSetTimestamp;
+    mHalPreviewWindow.set_usage = sSetUsage;
+    mHalPreviewWindow.set_swap_interval = sSetSwapInterval;
+
+    mHalPreviewWindow.get_min_undequeued_buffer_count =
+            sGetMinUndequeuedBufferCount;
+}
+
+// Methods from ::android::hardware::camera::device::V1_0::ICameraDevice follow.
+Return<void> CameraDevice::getResourceCost(getResourceCost_cb _hidl_cb) {
+    Status status = initStatus();
+    CameraResourceCost resCost;
+    if (status == Status::OK) {
+        int cost = 100;
+        std::vector<std::string> conflicting_devices;
+        struct camera_info info;
+
+        // If using post-2.4 module version, query the cost + conflicting devices from the HAL
+        if (mModule->getModuleApiVersion() >= CAMERA_MODULE_API_VERSION_2_4) {
+            int ret = mModule->getCameraInfo(mCameraIdInt, &info);
+            if (ret == OK) {
+                cost = info.resource_cost;
+                for (size_t i = 0; i < info.conflicting_devices_length; i++) {
+                    std::string cameraId(info.conflicting_devices[i]);
+                    for (const auto& pair : mCameraDeviceNames) {
+                        if (cameraId == pair.first) {
+                            conflicting_devices.push_back(pair.second);
+                        }
+                    }
+                }
+            } else {
+                status = Status::INTERNAL_ERROR;
+            }
+        }
+
+        if (status == Status::OK) {
+            resCost.resourceCost = cost;
+            resCost.conflictingDevices.resize(conflicting_devices.size());
+            for (size_t i = 0; i < conflicting_devices.size(); i++) {
+                resCost.conflictingDevices[i] = conflicting_devices[i];
+                ALOGV("CamDevice %s is conflicting with camDevice %s",
+                        mCameraId.c_str(), resCost.conflictingDevices[i].c_str());
+            }
+        }
+    }
+    _hidl_cb(status, resCost);
+    return Void();
+}
+
+Return<void> CameraDevice::getCameraInfo(getCameraInfo_cb _hidl_cb) {
+    Status status = initStatus();
+    CameraInfo cameraInfo;
+    if (status == Status::OK) {
+        struct camera_info info;
+        int ret = mModule->getCameraInfo(mCameraIdInt, &info);
+        if (ret == OK) {
+            cameraInfo.facing = (CameraFacing) info.facing;
+            // Device 1.0 does not support external camera facing.
+            // The closest approximation would be front camera.
+            // TODO: figure out should we override here or let
+            //       camera service handle it.
+            if (cameraInfo.facing == CameraFacing::EXTERNAL) {
+                cameraInfo.facing = CameraFacing::FRONT;
+            }
+            cameraInfo.orientation = info.orientation;
+        } else {
+            ALOGE("%s: get camera info failed!", __FUNCTION__);
+            status = Status::INTERNAL_ERROR;
+        }
+    }
+    _hidl_cb(status, cameraInfo);
+    return Void();
+}
+
+Return<Status> CameraDevice::setTorchMode(TorchMode mode) {
+    if (!mModule->isSetTorchModeSupported()) {
+        return Status::METHOD_NOT_SUPPORTED;
+    }
+
+    Status status = initStatus();
+    if (status == Status::OK) {
+        bool enable = (mode == TorchMode::ON) ? true : false;
+        status = getHidlStatus(mModule->setTorchMode(mCameraId.c_str(), enable));
+    }
+    return status;
+}
+
+Return<Status> CameraDevice::dumpState(const hidl_handle& handle) {
+    Mutex::Autolock _l(mLock);
+    if (handle.getNativeHandle() == nullptr) {
+        ALOGE("%s: handle must not be null", __FUNCTION__);
+        return Status::ILLEGAL_ARGUMENT;
+    }
+    if (handle->numFds != 1 || handle->numInts != 0) {
+        ALOGE("%s: handle must contain 1 FD and 0 integers! Got %d FDs and %d ints",
+                __FUNCTION__, handle->numFds, handle->numInts);
+        return Status::ILLEGAL_ARGUMENT;
+    }
+    int fd = handle->data[0];
+
+    if (mDevice != nullptr) {
+        if (mDevice->ops->dump) { // It's fine if the HAL doesn't implement dump()
+            return getHidlStatus(mDevice->ops->dump(mDevice, fd));
+        }
+    }
+    return Status::OK;
+}
+
+Return<Status> CameraDevice::open(const sp<ICameraDeviceCallback>& callback) {
+    ALOGI("Opening camera %s", mCameraId.c_str());
+    Mutex::Autolock _l(mLock);
+
+    camera_info info;
+    status_t res = mModule->getCameraInfo(mCameraIdInt, &info);
+    if (res != OK) {
+        ALOGE("Could not get camera info: %s: %d", mCameraId.c_str(), res);
+        return getHidlStatus(res);
+    }
+
+    int rc = OK;
+    if (mModule->getModuleApiVersion() >= CAMERA_MODULE_API_VERSION_2_3 &&
+        info.device_version > CAMERA_DEVICE_API_VERSION_1_0) {
+        // Open higher version camera device as HAL1.0 device.
+        rc = mModule->openLegacy(mCameraId.c_str(),
+                                 CAMERA_DEVICE_API_VERSION_1_0,
+                                 (hw_device_t **)&mDevice);
+    } else {
+        rc = mModule->open(mCameraId.c_str(), (hw_device_t **)&mDevice);
+    }
+    if (rc != OK) {
+        mDevice = nullptr;
+        ALOGE("Could not open camera %s: %d", mCameraId.c_str(), rc);
+        return getHidlStatus(rc);
+    }
+
+    initHalPreviewWindow();
+    mDeviceCallback = callback;
+
+    if (mDevice->ops->set_callbacks) {
+        mDevice->ops->set_callbacks(mDevice,
+                sNotifyCb, sDataCb, sDataCbTimestamp, sGetMemory, this);
+    }
+
+    return getHidlStatus(rc);
+}
+
+Return<Status> CameraDevice::setPreviewWindow(const sp<ICameraDevicePreviewCallback>& window) {
+    ALOGV("%s(%s)", __FUNCTION__, mCameraId.c_str());
+    Mutex::Autolock _l(mLock);
+    if (!mDevice) {
+        ALOGE("%s called while camera is not opened", __FUNCTION__);
+        return Status::OPERATION_NOT_SUPPORTED;
+    }
+
+    mHalPreviewWindow.mPreviewCallback = window;
+    if (mDevice->ops->set_preview_window) {
+        return getHidlStatus(mDevice->ops->set_preview_window(mDevice,
+                (window == nullptr) ? nullptr : &mHalPreviewWindow));
+    }
+    return Status::INTERNAL_ERROR; // HAL should provide set_preview_window
+}
+
+Return<void> CameraDevice::enableMsgType(uint32_t msgType) {
+    ALOGV("%s(%s)", __FUNCTION__, mCameraId.c_str());
+    Mutex::Autolock _l(mLock);
+    if (!mDevice) {
+        ALOGE("%s called while camera is not opened", __FUNCTION__);
+        return Void();
+    }
+    if (mDevice->ops->enable_msg_type) {
+        mDevice->ops->enable_msg_type(mDevice, msgType);
+    }
+    return Void();
+}
+
+Return<void> CameraDevice::disableMsgType(uint32_t msgType) {
+    ALOGV("%s(%s)", __FUNCTION__, mCameraId.c_str());
+    Mutex::Autolock _l(mLock);
+    if (!mDevice) {
+        ALOGE("%s called while camera is not opened", __FUNCTION__);
+        return Void();
+    }
+    if (mDevice->ops->disable_msg_type) {
+        mDevice->ops->disable_msg_type(mDevice, msgType);
+    }
+    return Void();
+}
+
+Return<bool> CameraDevice::msgTypeEnabled(uint32_t msgType) {
+    ALOGV("%s(%s)", __FUNCTION__, mCameraId.c_str());
+    Mutex::Autolock _l(mLock);
+    if (!mDevice) {
+        ALOGE("%s called while camera is not opened", __FUNCTION__);
+        return false;
+    }
+    if (mDevice->ops->msg_type_enabled) {
+        return mDevice->ops->msg_type_enabled(mDevice, msgType);
+    }
+    return false;
+}
+
+Return<Status> CameraDevice::startPreview() {
+    ALOGV("%s(%s)", __FUNCTION__, mCameraId.c_str());
+    Mutex::Autolock _l(mLock);
+    if (!mDevice) {
+        ALOGE("%s called while camera is not opened", __FUNCTION__);
+        return Status::OPERATION_NOT_SUPPORTED;
+    }
+    if (mDevice->ops->start_preview) {
+        return getHidlStatus(mDevice->ops->start_preview(mDevice));
+    }
+    return Status::INTERNAL_ERROR; // HAL should provide start_preview
+}
+
+Return<void> CameraDevice::stopPreview() {
+    ALOGV("%s(%s)", __FUNCTION__, mCameraId.c_str());
+    Mutex::Autolock _l(mLock);
+    if (!mDevice) {
+        ALOGE("%s called while camera is not opened", __FUNCTION__);
+        return Void();
+    }
+    if (mDevice->ops->stop_preview) {
+        mDevice->ops->stop_preview(mDevice);
+    }
+    return Void();
+}
+
+Return<bool> CameraDevice::previewEnabled() {
+    ALOGV("%s(%s)", __FUNCTION__, mCameraId.c_str());
+    Mutex::Autolock _l(mLock);
+    if (!mDevice) {
+        ALOGE("%s called while camera is not opened", __FUNCTION__);
+        return false;
+    }
+    if (mDevice->ops->preview_enabled) {
+        return mDevice->ops->preview_enabled(mDevice);
+    }
+    return false;
+}
+
+Return<Status> CameraDevice::storeMetaDataInBuffers(bool enable) {
+    ALOGV("%s(%s)", __FUNCTION__, mCameraId.c_str());
+    Mutex::Autolock _l(mLock);
+    if (!mDevice) {
+        ALOGE("%s called while camera is not opened", __FUNCTION__);
+        return Status::OPERATION_NOT_SUPPORTED;
+    }
+    if (mDevice->ops->store_meta_data_in_buffers) {
+        status_t s = mDevice->ops->store_meta_data_in_buffers(mDevice, enable);
+        if (s == OK && enable) {
+            mMetadataMode = true;
+        }
+        return getHidlStatus(s);
+    }
+    return enable ? Status::ILLEGAL_ARGUMENT : Status::OK;
+}
+
+Return<Status> CameraDevice::startRecording() {
+    ALOGV("%s(%s)", __FUNCTION__, mCameraId.c_str());
+    Mutex::Autolock _l(mLock);
+    if (!mDevice) {
+        ALOGE("%s called while camera is not opened", __FUNCTION__);
+        return Status::OPERATION_NOT_SUPPORTED;
+    }
+    if (mDevice->ops->start_recording) {
+        return getHidlStatus(mDevice->ops->start_recording(mDevice));
+    }
+    return Status::ILLEGAL_ARGUMENT;
+}
+
+Return<void> CameraDevice::stopRecording() {
+    ALOGV("%s(%s)", __FUNCTION__, mCameraId.c_str());
+    Mutex::Autolock _l(mLock);
+    if (!mDevice) {
+        ALOGE("%s called while camera is not opened", __FUNCTION__);
+        return Void();
+    }
+    if (mDevice->ops->stop_recording) {
+        mDevice->ops->stop_recording(mDevice);
+    }
+    return Void();
+}
+
+Return<bool> CameraDevice::recordingEnabled() {
+    ALOGV("%s(%s)", __FUNCTION__, mCameraId.c_str());
+    Mutex::Autolock _l(mLock);
+    if (!mDevice) {
+        ALOGE("%s called while camera is not opened", __FUNCTION__);
+        return false;
+    }
+    if (mDevice->ops->recording_enabled) {
+        return mDevice->ops->recording_enabled(mDevice);
+    }
+    return false;
+}
+
+void CameraDevice::releaseRecordingFrameLocked(
+        uint32_t memId, uint32_t bufferIndex, const native_handle_t* handle) {
+    if (!mDevice) {
+        ALOGE("%s called while camera is not opened", __FUNCTION__);
+        return;
+    }
+    if (mDevice->ops->release_recording_frame) {
+        CameraHeapMemory* camMemory = mMemoryMap.at(memId);
+        sp<MemoryHeapBase> heap = camMemory->mHeap;
+        if (bufferIndex >= camMemory->mNumBufs) {
+            ALOGE("%s: bufferIndex %d exceeds number of buffers %d",
+                    __FUNCTION__, bufferIndex, camMemory->mNumBufs);
+            return;
+        }
+        sp<IMemory> mem = camMemory->mBuffers[bufferIndex];
+        // TODO: simplify below logic once we verify offset is indeed idx * mBufSize
+        //       and heap == heap2
+        ssize_t offset;
+        size_t size;
+        sp<IMemoryHeap> heap2 = mem->getMemory(&offset, &size);
+        if ((size_t)offset != bufferIndex * camMemory->mBufSize) {
+            ALOGI("%s: unexpected offset %zd (was expecting %zu)",
+                    __FUNCTION__, offset, bufferIndex * camMemory->mBufSize);
+        }
+        if (heap != heap2) {
+            ALOGE("%s: heap mismatch!", __FUNCTION__);
+            return;
+        }
+        void *data = ((uint8_t *)heap->base()) + offset;
+        if (handle) {
+            VideoNativeHandleMetadata* md = (VideoNativeHandleMetadata*) data;
+            if (md->eType == VideoNativeHandleMetadata::kMetadataBufferTypeNativeHandleSource) {
+                // Input handle will be closed by HIDL transport later, so clone it
+                // HAL implementation is responsible to close/delete the clone
+                native_handle_t* clone = native_handle_clone(handle);
+                if (!clone) {
+                    ALOGE("%s: failed to clone buffer %p", __FUNCTION__, handle);
+                    return;
+                }
+                md->pHandle = clone;
+            } else {
+                ALOGE("%s:Malform VideoNativeHandleMetadata at memId %d, bufferId %d",
+                        __FUNCTION__, memId, bufferIndex);
+                return;
+            }
+        }
+        mDevice->ops->release_recording_frame(mDevice, data);
+    }
+}
+
+Return<void> CameraDevice::releaseRecordingFrame(uint32_t memId, uint32_t bufferIndex) {
+    ALOGV("%s(%s)", __FUNCTION__, mCameraId.c_str());
+    Mutex::Autolock _l(mLock);
+    releaseRecordingFrameLocked(memId, bufferIndex, nullptr);
+    return Void();
+}
+
+Return<void> CameraDevice::releaseRecordingFrameHandle(
+        uint32_t memId, uint32_t bufferIndex, const hidl_handle& frame) {
+    ALOGV("%s(%s)", __FUNCTION__, mCameraId.c_str());
+    Mutex::Autolock _l(mLock);
+    releaseRecordingFrameLocked(
+            memId, bufferIndex, frame.getNativeHandle());
+    return Void();
+}
+
+Return<Status> CameraDevice::autoFocus() {
+    ALOGV("%s(%s)", __FUNCTION__, mCameraId.c_str());
+    Mutex::Autolock _l(mLock);
+    if (!mDevice) {
+        ALOGE("%s called while camera is not opened", __FUNCTION__);
+        return Status::OPERATION_NOT_SUPPORTED;
+    }
+    if (mDevice->ops->auto_focus) {
+        return getHidlStatus(mDevice->ops->auto_focus(mDevice));
+    }
+    return Status::ILLEGAL_ARGUMENT;
+}
+
+Return<Status> CameraDevice::cancelAutoFocus() {
+    ALOGV("%s(%s)", __FUNCTION__, mCameraId.c_str());
+    Mutex::Autolock _l(mLock);
+    if (!mDevice) {
+        ALOGE("%s called while camera is not opened", __FUNCTION__);
+        return Status::OPERATION_NOT_SUPPORTED;
+    }
+    if (mDevice->ops->cancel_auto_focus) {
+        return getHidlStatus(mDevice->ops->cancel_auto_focus(mDevice));
+    }
+    return Status::ILLEGAL_ARGUMENT;
+}
+
+Return<Status> CameraDevice::takePicture() {
+    ALOGV("%s(%s)", __FUNCTION__, mCameraId.c_str());
+    Mutex::Autolock _l(mLock);
+    if (!mDevice) {
+        ALOGE("%s called while camera is not opened", __FUNCTION__);
+        return Status::OPERATION_NOT_SUPPORTED;
+    }
+    if (mDevice->ops->take_picture) {
+        return getHidlStatus(mDevice->ops->take_picture(mDevice));
+    }
+    return Status::ILLEGAL_ARGUMENT;
+}
+
+Return<Status> CameraDevice::cancelPicture() {
+    ALOGV("%s(%s)", __FUNCTION__, mCameraId.c_str());
+    Mutex::Autolock _l(mLock);
+    if (!mDevice) {
+        ALOGE("%s called while camera is not opened", __FUNCTION__);
+        return Status::OPERATION_NOT_SUPPORTED;
+    }
+    if (mDevice->ops->cancel_picture) {
+        return getHidlStatus(mDevice->ops->cancel_picture(mDevice));
+    }
+    return Status::ILLEGAL_ARGUMENT;
+}
+
+Return<Status> CameraDevice::setParameters(const hidl_string& params) {
+    ALOGV("%s(%s)", __FUNCTION__, mCameraId.c_str());
+    Mutex::Autolock _l(mLock);
+    if (!mDevice) {
+        ALOGE("%s called while camera is not opened", __FUNCTION__);
+        return Status::OPERATION_NOT_SUPPORTED;
+    }
+    if (mDevice->ops->set_parameters) {
+        return getHidlStatus(mDevice->ops->set_parameters(mDevice, params.c_str()));
+    }
+    return Status::ILLEGAL_ARGUMENT;
+}
+
+Return<void> CameraDevice::getParameters(getParameters_cb _hidl_cb) {
+    ALOGV("%s(%s)", __FUNCTION__, mCameraId.c_str());
+    Mutex::Autolock _l(mLock);
+    hidl_string outStr;
+    if (!mDevice) {
+        ALOGE("%s called while camera is not opened", __FUNCTION__);
+        _hidl_cb(outStr);
+        return Void();
+    }
+    if (mDevice->ops->get_parameters) {
+        char *temp = mDevice->ops->get_parameters(mDevice);
+        outStr = temp;
+        if (mDevice->ops->put_parameters) {
+            mDevice->ops->put_parameters(mDevice, temp);
+        } else {
+            free(temp);
+        }
+    }
+    _hidl_cb(outStr);
+    return Void();
+}
+
+Return<Status> CameraDevice::sendCommand(CommandType cmd, int32_t arg1, int32_t arg2) {
+    ALOGV("%s(%s)", __FUNCTION__, mCameraId.c_str());
+    Mutex::Autolock _l(mLock);
+    if (!mDevice) {
+        ALOGE("%s called while camera is not opened", __FUNCTION__);
+        return Status::OPERATION_NOT_SUPPORTED;
+    }
+    if (mDevice->ops->send_command) {
+        return getHidlStatus(mDevice->ops->send_command(mDevice, (int32_t) cmd, arg1, arg2));
+    }
+    return Status::ILLEGAL_ARGUMENT;
+}
+
+Return<void> CameraDevice::close() {
+    ALOGI("Closing camera %s", mCameraId.c_str());
+    Mutex::Autolock _l(mLock);
+    if(mDevice) {
+        int rc = mDevice->common.close(&mDevice->common);
+        if (rc != OK) {
+            ALOGE("Could not close camera %s: %d", mCameraId.c_str(), rc);
+        }
+        mDevice = nullptr;
+    }
+    return Void();
+}
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace device
+}  // namespace camera
+}  // namespace hardware
+}  // namespace android
diff --git a/camera/device/1.0/default/CameraDevice_1_0.h b/camera/device/1.0/default/CameraDevice_1_0.h
new file mode 100644
index 0000000..2568f86
--- /dev/null
+++ b/camera/device/1.0/default/CameraDevice_1_0.h
@@ -0,0 +1,224 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_CAMERA_DEVICE_V1_0_CAMERADEVICE_H
+#define ANDROID_HARDWARE_CAMERA_DEVICE_V1_0_CAMERADEVICE_H
+
+#include <unordered_map>
+#include "utils/Mutex.h"
+#include "utils/SortedVector.h"
+#include <binder/MemoryBase.h>
+#include <binder/MemoryHeapBase.h>
+#include "CameraModule.h"
+#include "HandleImporter.h"
+
+#include <android/hardware/camera/device/1.0/ICameraDevice.h>
+#include <hidl/MQDescriptor.h>
+#include <hidl/Status.h>
+
+namespace android {
+namespace hardware {
+namespace camera {
+namespace device {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::camera::common::V1_0::CameraResourceCost;
+using ::android::hardware::camera::common::V1_0::Status;
+using ::android::hardware::camera::common::V1_0::TorchMode;
+using ::android::hardware::camera::common::V1_0::helper::CameraModule;
+using ::android::hardware::camera::common::V1_0::helper::HandleImporter;
+using ::android::hardware::camera::device::V1_0::CameraInfo;
+using ::android::hardware::camera::device::V1_0::CommandType;
+using ::android::hardware::camera::device::V1_0::ICameraDevice;
+using ::android::hardware::camera::device::V1_0::ICameraDeviceCallback;
+using ::android::hardware::camera::device::V1_0::ICameraDevicePreviewCallback;
+using ::android::hardware::camera::device::V1_0::MemoryId;
+using ::android::hidl::base::V1_0::IBase;
+using ::android::hardware::hidl_array;
+using ::android::hardware::hidl_memory;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::sp;
+
+struct CameraDevice : public ICameraDevice {
+
+    // Called by provider HAL. Provider HAL must ensure the uniqueness of
+    // CameraDevice object per cameraId, or there could be multiple CameraDevice
+    // trying to access the same physical camera.
+    // Also, provider will have to keep track of all CameraDevice objects in
+    // order to notify CameraDevice when the underlying camera is detached
+    CameraDevice(sp<CameraModule> module,
+                 const std::string& cameraId,
+                 const SortedVector<std::pair<std::string, std::string>>& cameraDeviceNames);
+    ~CameraDevice();
+
+    // Caller must use this method to check if CameraDevice ctor failed
+    bool isInitFailed() { return mInitFail; }
+    // Used by provider HAL to signal external camera disconnected
+    void setConnectionStatus(bool connected);
+
+    // Methods from ::android::hardware::camera::device::V1_0::ICameraDevice follow.
+    Return<void> getResourceCost(getResourceCost_cb _hidl_cb) override;
+    Return<void> getCameraInfo(getCameraInfo_cb _hidl_cb) override;
+    Return<Status> setTorchMode(TorchMode mode) override;
+    Return<Status> dumpState(const hidl_handle& fd) override;
+    Return<Status> open(const sp<ICameraDeviceCallback>& callback) override;
+    Return<Status> setPreviewWindow(const sp<ICameraDevicePreviewCallback>& window) override;
+    Return<void> enableMsgType(uint32_t msgType) override;
+    Return<void> disableMsgType(uint32_t msgType) override;
+    Return<bool> msgTypeEnabled(uint32_t msgType) override;
+    Return<Status> startPreview() override;
+    Return<void> stopPreview() override;
+    Return<bool> previewEnabled() override;
+    Return<Status> storeMetaDataInBuffers(bool enable) override;
+    Return<Status> startRecording() override;
+    Return<void> stopRecording() override;
+    Return<bool> recordingEnabled() override;
+    Return<void> releaseRecordingFrame(uint32_t memId, uint32_t bufferIndex) override;
+    Return<void> releaseRecordingFrameHandle(
+            uint32_t memId, uint32_t bufferIndex, const hidl_handle& frame) override;
+    Return<Status> autoFocus() override;
+    Return<Status> cancelAutoFocus() override;
+    Return<Status> takePicture() override;
+    Return<Status> cancelPicture() override;
+    Return<Status> setParameters(const hidl_string& params) override;
+    Return<void> getParameters(getParameters_cb _hidl_cb) override;
+    Return<Status> sendCommand(CommandType cmd, int32_t arg1, int32_t arg2) override;
+    Return<void> close() override;
+
+private:
+    struct CameraMemory : public camera_memory_t {
+        MemoryId mId;
+        CameraDevice* mDevice;
+    };
+
+    class CameraHeapMemory : public RefBase {
+    public:
+        CameraHeapMemory(int fd, size_t buf_size, uint_t num_buffers = 1);
+        explicit CameraHeapMemory(size_t buf_size, uint_t num_buffers = 1);
+        void commonInitialization();
+        virtual ~CameraHeapMemory();
+
+        size_t mBufSize;
+        uint_t mNumBufs;
+        // TODO: b/35887419: use hidl_memory instead and get rid of libbinder
+        sp<MemoryHeapBase> mHeap;
+        sp<MemoryBase>* mBuffers;
+        CameraMemory handle;
+    };
+
+    // TODO: b/35625849
+    // Meta data buffer layout for passing a native_handle to codec
+    // matching frameworks/native/include/media/hardware/MetadataBufferType.h and
+    //          frameworks/native/include/media/hardware/HardwareAPI.h
+    struct VideoNativeHandleMetadata {
+        static const uint32_t kMetadataBufferTypeNativeHandleSource = 3;
+        uint32_t eType; // must be kMetadataBufferTypeNativeHandleSource
+        native_handle_t* pHandle;
+    };
+
+    const sp<CameraModule> mModule;
+    const std::string mCameraId;
+    // const after ctor
+    int   mCameraIdInt;
+    int   mDeviceVersion;
+
+    camera_device_t* mDevice = nullptr;
+
+    void initHalPreviewWindow();
+    struct CameraPreviewWindow : public preview_stream_ops {
+        // Called when we expect buffer will be re-allocated
+        void cleanUpCirculatingBuffers();
+
+        Mutex mLock;
+        sp<ICameraDevicePreviewCallback> mPreviewCallback = nullptr;
+        std::unordered_map<uint64_t, buffer_handle_t> mCirculatingBuffers;
+        std::unordered_map<buffer_handle_t*, uint64_t> mBufferIdMap;
+    } mHalPreviewWindow;
+
+    // gating access to mDevice, mInitFail, mDisconnected
+    mutable Mutex mLock;
+
+    bool  mInitFail = false;
+    // Set by provider (when external camera is connected/disconnected)
+    bool  mDisconnected;
+
+    static HandleImporter& sHandleImporter;
+
+    const SortedVector<std::pair<std::string, std::string>>& mCameraDeviceNames;
+
+    sp<ICameraDeviceCallback> mDeviceCallback = nullptr;
+
+    std::unordered_map<MemoryId, CameraHeapMemory*> mMemoryMap;
+
+    bool mMetadataMode = false;
+
+    void releaseRecordingFrameLocked(uint32_t memId, uint32_t bufferIndex, const native_handle_t*);
+
+    // shared memory methods
+    static camera_memory_t* sGetMemory(int fd, size_t buf_size, uint_t num_bufs, void *user);
+    static void sPutMemory(camera_memory_t *data);
+
+    // Device callback forwarding methods
+    static void sNotifyCb(int32_t msg_type, int32_t ext1, int32_t ext2, void *user);
+    static void sDataCb(int32_t msg_type, const camera_memory_t *data, unsigned int index,
+                          camera_frame_metadata_t *metadata, void *user);
+    static void sDataCbTimestamp(nsecs_t timestamp, int32_t msg_type,
+                                    const camera_memory_t *data, unsigned index, void *user);
+
+    // Preview window callback forwarding methods
+    static int sDequeueBuffer(struct preview_stream_ops* w,
+                                buffer_handle_t** buffer, int *stride);
+
+    static int sLockBuffer(struct preview_stream_ops* w, buffer_handle_t* buffer);
+
+    static int sEnqueueBuffer(struct preview_stream_ops* w, buffer_handle_t* buffer);
+
+    static int sCancelBuffer(struct preview_stream_ops* w, buffer_handle_t* buffer);
+
+    static int sSetBufferCount(struct preview_stream_ops* w, int count);
+
+    static int sSetBuffersGeometry(struct preview_stream_ops* w,
+                                     int width, int height, int format);
+
+    static int sSetCrop(struct preview_stream_ops *w, int left, int top, int right, int bottom);
+
+    static int sSetTimestamp(struct preview_stream_ops *w, int64_t timestamp);
+
+    static int sSetUsage(struct preview_stream_ops* w, int usage);
+
+    static int sSetSwapInterval(struct preview_stream_ops *w, int interval);
+
+    static int sGetMinUndequeuedBufferCount(const struct preview_stream_ops *w, int *count);
+
+    // convert conventional HAL status to HIDL Status
+    static Status getHidlStatus(const int&);
+    static status_t getStatusT(const Status& s);
+
+    Status initStatus() const;
+};
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace device
+}  // namespace camera
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_CAMERA_DEVICE_V1_0_CAMERADEVICE_H
diff --git a/camera/device/1.0/types.hal b/camera/device/1.0/types.hal
index 83c0be4..b32c938 100644
--- a/camera/device/1.0/types.hal
+++ b/camera/device/1.0/types.hal
@@ -189,6 +189,66 @@
     PREVIEW_METADATA = 0x0400
 };
 
+/**
+ * Information for a single detected face.
+ */
+ struct CameraFace {
+    /**
+     * Bounds of the face [left, top, right, bottom]. (-1000, -1000) represents
+     * the top-left of the camera field of view, and (1000, 1000) represents the
+     * bottom-right of the field of view. The width and height cannot be 0 or
+     * negative. This is supported by both hardware and software face detection.
+     *
+     * The direction is relative to the sensor orientation, that is, what the
+     * sensor sees. The direction is not affected by the rotation or mirroring
+     * of CAMERA_CMD_SET_DISPLAY_ORIENTATION.
+     */
+    int32_t[4] rect;
+
+    /**
+     * The confidence level of the face. The range is 1 to 100. 100 is the
+     * highest confidence. This is supported by both hardware and software
+     * face detection.
+     */
+    int32_t score;
+
+    /**
+     * An unique id per face while the face is visible to the tracker. If
+     * the face leaves the field-of-view and comes back, it will get a new
+     * id. If the value is 0, id is not supported.
+     */
+    int32_t id;
+
+    /**
+     * The coordinates of the center of the left eye. The range is -1000 to
+     * 1000. -2000, -2000 if this is not supported.
+     */
+    int32_t[2] leftEye;
+
+    /**
+     * The coordinates of the center of the right eye. The range is -1000 to
+     * 1000. -2000, -2000 if this is not supported.
+     */
+    int32_t[2] rightEye;
+
+    /**
+     * The coordinates of the center of the mouth. The range is -1000 to 1000.
+     * -2000, -2000 if this is not supported.
+     */
+    int32_t[2] mouth;
+
+};
+
+/**
+ * The metadata of the frame data, such as face detection result.
+ */
+struct CameraFrameMetadata {
+    /**
+     * A vector of the detected faces.
+     */
+    vec<CameraFace> faces;
+};
+
 /*
  * A simple integer handle to use to reference a particular memory buffer
  * between the HAL and the framework.
diff --git a/camera/device/3.2/default/CameraDevice.cpp b/camera/device/3.2/default/CameraDevice.cpp
index 18e0e7b..0a457ad 100644
--- a/camera/device/3.2/default/CameraDevice.cpp
+++ b/camera/device/3.2/default/CameraDevice.cpp
@@ -15,11 +15,11 @@
  */
 
 #define LOG_TAG "CamDev@3.2-impl"
-#include <android/log.h>
+#include <utils/Log.h>
 
 #include <utils/Vector.h>
 #include <utils/Trace.h>
-#include "CameraDevice.h"
+#include "CameraDevice_3_2.h"
 #include <include/convert.h>
 
 namespace android {
diff --git a/camera/device/3.2/default/CameraDeviceSession.cpp b/camera/device/3.2/default/CameraDeviceSession.cpp
index 0f3d97b..3c3c078 100644
--- a/camera/device/3.2/default/CameraDeviceSession.cpp
+++ b/camera/device/3.2/default/CameraDeviceSession.cpp
@@ -29,198 +29,13 @@
 namespace V3_2 {
 namespace implementation {
 
-namespace {
-
-// Copy pasted from Hwc.cpp. Use this until gralloc mapper HAL is working
-class HandleImporter {
-public:
-    HandleImporter() : mInitialized(false) {}
-
-    bool initialize()
-    {
-        // allow only one client
-        if (mInitialized) {
-            return false;
-        }
-
-        if (!openGralloc()) {
-            return false;
-        }
-
-        mInitialized = true;
-        return true;
-    }
-
-    void cleanup()
-    {
-        if (!mInitialized) {
-            return;
-        }
-
-        closeGralloc();
-        mInitialized = false;
-    }
-
-    // In IComposer, any buffer_handle_t is owned by the caller and we need to
-    // make a clone for hwcomposer2.  We also need to translate empty handle
-    // to nullptr.  This function does that, in-place.
-    bool importBuffer(buffer_handle_t& handle)
-    {
-        if (!handle->numFds && !handle->numInts) {
-            handle = nullptr;
-            return true;
-        }
-
-        buffer_handle_t clone = cloneBuffer(handle);
-        if (!clone) {
-            return false;
-        }
-
-        handle = clone;
-        return true;
-    }
-
-    void freeBuffer(buffer_handle_t handle)
-    {
-        if (!handle) {
-            return;
-        }
-
-        releaseBuffer(handle);
-    }
-
-    bool importFence(const native_handle_t* handle, int& fd)
-    {
-        if (handle == nullptr || handle->numFds == 0) {
-            fd = -1;
-        } else if (handle->numFds == 1) {
-            fd = dup(handle->data[0]);
-            if (fd < 0) {
-                ALOGE("failed to dup fence fd %d", handle->data[0]);
-                return false;
-            }
-        } else {
-            ALOGE("invalid fence handle with %d file descriptors",
-                    handle->numFds);
-            return false;
-        }
-
-        return true;
-    }
-
-    void closeFence(int fd)
-    {
-        if (fd >= 0) {
-            close(fd);
-        }
-    }
-
-private:
-    bool mInitialized;
-
-    bool openGralloc()
-    {
-        const hw_module_t* module;
-        int err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module);
-        if (err) {
-            ALOGE("failed to get gralloc module");
-            return false;
-        }
-
-        uint8_t major = (module->module_api_version >> 8) & 0xff;
-        if (major > 1) {
-            ALOGE("unknown gralloc module major version %d", major);
-            return false;
-        }
-
-        if (major == 1) {
-            err = gralloc1_open(module, &mDevice);
-            if (err) {
-                ALOGE("failed to open gralloc1 device");
-                return false;
-            }
-
-            mRetain = reinterpret_cast<GRALLOC1_PFN_RETAIN>(
-                    mDevice->getFunction(mDevice, GRALLOC1_FUNCTION_RETAIN));
-            mRelease = reinterpret_cast<GRALLOC1_PFN_RELEASE>(
-                    mDevice->getFunction(mDevice, GRALLOC1_FUNCTION_RELEASE));
-            if (!mRetain || !mRelease) {
-                ALOGE("invalid gralloc1 device");
-                gralloc1_close(mDevice);
-                return false;
-            }
-        } else {
-            mModule = reinterpret_cast<const gralloc_module_t*>(module);
-        }
-
-        return true;
-    }
-
-    void closeGralloc()
-    {
-        if (mDevice) {
-            gralloc1_close(mDevice);
-        }
-    }
-
-    buffer_handle_t cloneBuffer(buffer_handle_t handle)
-    {
-        native_handle_t* clone = native_handle_clone(handle);
-        if (!clone) {
-            ALOGE("failed to clone buffer %p", handle);
-            return nullptr;
-        }
-
-        bool err;
-        if (mDevice) {
-            err = (mRetain(mDevice, clone) != GRALLOC1_ERROR_NONE);
-        } else {
-            err = (mModule->registerBuffer(mModule, clone) != 0);
-        }
-
-        if (err) {
-            ALOGE("failed to retain/register buffer %p", clone);
-            native_handle_close(clone);
-            native_handle_delete(clone);
-            return nullptr;
-        }
-
-        return clone;
-    }
-
-    void releaseBuffer(buffer_handle_t handle)
-    {
-        if (mDevice) {
-            mRelease(mDevice, handle);
-        } else {
-            mModule->unregisterBuffer(mModule, handle);
-        }
-        native_handle_close(handle);
-        native_handle_delete(const_cast<native_handle_t*>(handle));
-    }
-
-    // gralloc1
-    gralloc1_device_t* mDevice;
-    GRALLOC1_PFN_RETAIN mRetain;
-    GRALLOC1_PFN_RELEASE mRelease;
-
-    // gralloc0
-    const gralloc_module_t* mModule;
-};
-
-HandleImporter sHandleImporter;
-
-} // Anonymous namespace
+HandleImporter& CameraDeviceSession::sHandleImporter = HandleImporter::getInstance();
 
 CameraDeviceSession::CameraDeviceSession(
     camera3_device_t* device, const sp<ICameraDeviceCallback>& callback) :
         camera3_callback_ops({&sProcessCaptureResult, &sNotify}),
         mDevice(device),
         mCallback(callback) {
-    // For now, we init sHandleImporter but do not cleanup (keep it alive until
-    // HAL process ends)
-    sHandleImporter.initialize();
-
     mInitFail = initialize();
 }
 
diff --git a/camera/device/3.2/default/CameraDeviceSession.h b/camera/device/3.2/default/CameraDeviceSession.h
index f8689d3..3786e4b 100644
--- a/camera/device/3.2/default/CameraDeviceSession.h
+++ b/camera/device/3.2/default/CameraDeviceSession.h
@@ -26,6 +26,7 @@
 #include <hidl/Status.h>
 #include <hidl/MQDescriptor.h>
 #include <include/convert.h>
+#include "HandleImporter.h"
 
 namespace android {
 namespace hardware {
@@ -39,6 +40,7 @@
 using ::android::hardware::camera::device::V3_2::StreamConfiguration;
 using ::android::hardware::camera::device::V3_2::ICameraDeviceSession;
 using ::android::hardware::camera::common::V1_0::Status;
+using ::android::hardware::camera::common::V1_0::helper::HandleImporter;
 using ::android::hardware::Return;
 using ::android::hardware::Void;
 using ::android::hardware::hidl_vec;
@@ -109,6 +111,8 @@
     // Stream ID -> circulating buffers map
     std::map<int, CirculatingBuffers> mCirculatingBuffers;
 
+    static HandleImporter& sHandleImporter;
+
     bool mInitFail;
     bool initialize();
 
diff --git a/camera/device/3.2/default/CameraDevice.h b/camera/device/3.2/default/CameraDevice_3_2.h
similarity index 97%
rename from camera/device/3.2/default/CameraDevice.h
rename to camera/device/3.2/default/CameraDevice_3_2.h
index 317eea5..4e86067 100644
--- a/camera/device/3.2/default/CameraDevice.h
+++ b/camera/device/3.2/default/CameraDevice_3_2.h
@@ -55,7 +55,7 @@
     // Called by provider HAL. Provider HAL must ensure the uniqueness of
     // CameraDevice object per cameraId, or there could be multiple CameraDevice
     // trying to access the same physical camera.
-    // Also, provider will have to keep track of all CameraDevice object in
+    // Also, provider will have to keep track of all CameraDevice objects in
     // order to notify CameraDevice when the underlying camera is detached
     CameraDevice(sp<CameraModule> module,
                  const std::string& cameraId,
@@ -81,8 +81,7 @@
     /* End of Methods from ::android::hardware::camera::device::V3_2::ICameraDevice */
 
 private:
-    // Passed from provider HAL. Should not change.
-    sp<CameraModule> mModule;
+    const sp<CameraModule> mModule;
     const std::string mCameraId;
     // const after ctor
     int   mCameraIdInt;
diff --git a/camera/provider/2.4/default/Android.bp b/camera/provider/2.4/default/Android.bp
index 7315292..a6febec 100644
--- a/camera/provider/2.4/default/Android.bp
+++ b/camera/provider/2.4/default/Android.bp
@@ -10,6 +10,7 @@
         "libcutils",
         "android.hardware.camera.device@1.0",
         "android.hardware.camera.device@3.2",
+        "camera.device@1.0-impl",
         "camera.device@3.2-impl",
         "android.hardware.camera.provider@2.4",
         "android.hardware.camera.common@1.0",
@@ -34,15 +35,9 @@
         "libhidltransport",
         "liblog",
         "libutils",
-        "libhardware",
         "android.hardware.camera.device@1.0",
         "android.hardware.camera.device@3.2",
         "android.hardware.camera.provider@2.4",
         "android.hardware.camera.common@1.0",
-        "libcutils",
-        "libcamera_metadata"
     ],
-    static_libs: [
-        "android.hardware.camera.common@1.0-helper"
-    ]
 }
diff --git a/camera/provider/2.4/default/CameraProvider.cpp b/camera/provider/2.4/default/CameraProvider.cpp
index 5714f83..ad9f0b8 100644
--- a/camera/provider/2.4/default/CameraProvider.cpp
+++ b/camera/provider/2.4/default/CameraProvider.cpp
@@ -18,7 +18,8 @@
 #include <android/log.h>
 
 #include "CameraProvider.h"
-#include "CameraDevice.h"
+#include "CameraDevice_1_0.h"
+#include "CameraDevice_3_2.h"
 #include <string.h>
 #include <utils/Trace.h>
 
@@ -59,8 +60,6 @@
         return;
     }
 
-    ALOGI("%s resolved provider %p", __FUNCTION__, cp);
-
     Mutex::Autolock _l(cp->mCbLock);
     char cameraId[kMaxCameraIdLen];
     snprintf(cameraId, sizeof(cameraId), "%d", camera_id);
@@ -89,8 +88,6 @@
         return;
     }
 
-    ALOGI("%s resolved provider %p", __FUNCTION__, cp);
-
     Mutex::Autolock _l(cp->mCbLock);
     if (cp->mCallbacks != nullptr) {
         std::string cameraIdStr(camera_id);
@@ -323,9 +320,57 @@
 }
 
 Return<void> CameraProvider::getCameraDeviceInterface_V1_x(
-        const hidl_string& /*cameraDeviceName*/, getCameraDeviceInterface_V1_x_cb _hidl_cb)  {
-    // TODO implement after device 1.0 is implemented
-    _hidl_cb(Status::INTERNAL_ERROR, nullptr);
+        const hidl_string& cameraDeviceName, getCameraDeviceInterface_V1_x_cb _hidl_cb)  {
+    std::smatch sm;
+    bool match = matchDeviceName(cameraDeviceName, sm);
+    if (!match) {
+        _hidl_cb(Status::ILLEGAL_ARGUMENT, nullptr);
+        return Void();
+    }
+
+    std::string cameraId = sm[2];
+    std::string deviceVersion = sm[1];
+    std::string deviceName(cameraDeviceName.c_str());
+    ssize_t index = mCameraDeviceNames.indexOf(std::make_pair(cameraId, deviceName));
+    if (index == NAME_NOT_FOUND) { // Either an illegal name or a device version mismatch
+        Status status = Status::OK;
+        ssize_t idx = mCameraIds.indexOf(cameraId);
+        if (idx == NAME_NOT_FOUND) {
+            ALOGE("%s: cannot find camera %s!", __FUNCTION__, cameraId.c_str());
+            status = Status::ILLEGAL_ARGUMENT;
+        } else { // invalid version
+            ALOGE("%s: camera device %s does not support version %s!",
+                    __FUNCTION__, cameraId.c_str(), deviceVersion.c_str());
+            status = Status::OPERATION_NOT_SUPPORTED;
+        }
+        _hidl_cb(status, nullptr);
+        return Void();
+    }
+
+    if (mCameraStatusMap.count(cameraId) == 0 ||
+            mCameraStatusMap[cameraId] != CAMERA_DEVICE_STATUS_PRESENT) {
+        _hidl_cb(Status::ILLEGAL_ARGUMENT, nullptr);
+        return Void();
+    }
+
+    sp<android::hardware::camera::device::V1_0::implementation::CameraDevice> device =
+            new android::hardware::camera::device::V1_0::implementation::CameraDevice(
+                    mModule, cameraId, mCameraDeviceNames);
+
+    if (device == nullptr) {
+        ALOGE("%s: cannot allocate camera device for id %s", __FUNCTION__, cameraId.c_str());
+        _hidl_cb(Status::INTERNAL_ERROR, nullptr);
+        return Void();
+    }
+
+    if (device->isInitFailed()) {
+        ALOGE("%s: camera device %s init failed!", __FUNCTION__, cameraId.c_str());
+        device = nullptr;
+        _hidl_cb(Status::INTERNAL_ERROR, nullptr);
+        return Void();
+    }
+
+    _hidl_cb (Status::OK, device);
     return Void();
 }
 
diff --git a/graphics/common/1.0/types.hal b/graphics/common/1.0/types.hal
index 7663701..1ddd892 100644
--- a/graphics/common/1.0/types.hal
+++ b/graphics/common/1.0/types.hal
@@ -792,7 +792,7 @@
     TRANSFER_GAMMA2_8 = 6 << TRANSFER_SHIFT,
 
     /*
-     * SMPTE ST 2084
+     * SMPTE ST 2084 (Dolby Perceptual Quantizer)
      *
      * Transfer characteristic curve:
      *  E = ((c1 + c2 * L^n) / (1 + c3 * L^n)) ^ m
@@ -1068,6 +1068,15 @@
      */
     BT2020 = STANDARD_BT2020 | TRANSFER_SMPTE_170M | RANGE_FULL,
 
+    /*
+     * ITU-R Recommendation 2020 (BT.2020)
+     *
+     * Ultra High-definition television
+     *
+     * Use full range, SMPTE 2084 (PQ) transfer and BT2020 standard
+     */
+    BT2020_PQ = STANDARD_BT2020 | TRANSFER_ST2084 | RANGE_FULL,
+
 
     /*
      * Data spaces for non-color formats
diff --git a/media/omx/1.0/IGraphicBufferSource.hal b/media/omx/1.0/IGraphicBufferSource.hal
index 4dbfd32..62073ad 100644
--- a/media/omx/1.0/IGraphicBufferSource.hal
+++ b/media/omx/1.0/IGraphicBufferSource.hal
@@ -29,25 +29,25 @@
  */
 interface IGraphicBufferSource {
 
-    configure(IOmxNode omxNode, Dataspace dataspace);
+    configure(IOmxNode omxNode, Dataspace dataspace) generates (Status status);
 
-    setSuspend(bool suspend, int64_t timeUs);
+    setSuspend(bool suspend, int64_t timeUs) generates (Status status);
 
-    setRepeatPreviousFrameDelayUs(int64_t repeatAfterUs);
+    setRepeatPreviousFrameDelayUs(int64_t repeatAfterUs) generates (Status status);
 
-    setMaxFps(float maxFps);
+    setMaxFps(float maxFps) generates (Status status);
 
-    setTimeLapseConfig(int64_t timePerFrameUs, int64_t timePerCaptureUs);
+    setTimeLapseConfig(int64_t timePerFrameUs, int64_t timePerCaptureUs) generates (Status status);
 
-    setStartTimeUs(int64_t startTimeUs);
+    setStartTimeUs(int64_t startTimeUs) generates (Status status);
 
-    setStopTimeUs(int64_t stopTimeUs);
+    setStopTimeUs(int64_t stopTimeUs) generates (Status status);
 
-    setColorAspects(ColorAspects aspects);
+    setColorAspects(ColorAspects aspects) generates (Status status);
 
-    setTimeOffsetUs(int64_t timeOffsetUs);
+    setTimeOffsetUs(int64_t timeOffsetUs) generates (Status status);
 
-    signalEndOfInputStream();
+    signalEndOfInputStream() generates (Status status);
 
 };
 
diff --git a/sensors/1.0/default/Sensors.cpp b/sensors/1.0/default/Sensors.cpp
index 41eb945..37e2b81 100644
--- a/sensors/1.0/default/Sensors.cpp
+++ b/sensors/1.0/default/Sensors.cpp
@@ -145,22 +145,41 @@
 }
 
 Return<void> Sensors::poll(int32_t maxCount, poll_cb _hidl_cb) {
+
     hidl_vec<Event> out;
     hidl_vec<SensorInfo> dynamicSensorsAdded;
 
-    if (maxCount <= 0) {
-        _hidl_cb(Result::BAD_VALUE, out, dynamicSensorsAdded);
-        return Void();
+    std::unique_ptr<sensors_event_t[]> data;
+    int err = android::NO_ERROR;
+
+    { // scope of reentry lock
+
+        // This enforces a single client, meaning that a maximum of one client can call poll().
+        // If this function is re-entred, it means that we are stuck in a state that may prevent
+        // the system from proceeding normally.
+        //
+        // Exit and let the system restart the sensor-hal-implementation hidl service.
+        //
+        // This function must not call _hidl_cb(...) or return until there is no risk of blocking.
+        std::unique_lock<std::mutex> lock(mPollLock, std::try_to_lock);
+        if(!lock.owns_lock()){
+            // cannot get the lock, hidl service will go into deadlock if it is not restarted.
+            // This is guaranteed to not trigger in passthrough mode.
+            LOG(FATAL) <<
+                    "ISensors::poll() re-entry. I do not know what to do except killing myself.";
+        }
+
+        if (maxCount <= 0) {
+            err = android::BAD_VALUE;
+        } else {
+            int bufferSize = maxCount <= kPollMaxBufferSize ? maxCount : kPollMaxBufferSize;
+            data.reset(new sensors_event_t[bufferSize]);
+            err = mSensorDevice->poll(
+                    reinterpret_cast<sensors_poll_device_t *>(mSensorDevice),
+                    data.get(), bufferSize);
+        }
     }
 
-    int bufferSize = maxCount <= kPollMaxBufferSize ? maxCount : kPollMaxBufferSize;
-
-    std::unique_ptr<sensors_event_t[]> data(new sensors_event_t[bufferSize]);
-
-    int err = mSensorDevice->poll(
-            reinterpret_cast<sensors_poll_device_t *>(mSensorDevice),
-            data.get(), bufferSize);
-
     if (err < 0) {
         _hidl_cb(ResultFromStatus(err), out, dynamicSensorsAdded);
         return Void();
diff --git a/sensors/1.0/default/Sensors.h b/sensors/1.0/default/Sensors.h
index 09729d3..7d715e0 100644
--- a/sensors/1.0/default/Sensors.h
+++ b/sensors/1.0/default/Sensors.h
@@ -20,6 +20,7 @@
 
 #include <android/hardware/sensors/1.0/ISensors.h>
 #include <hardware/sensors.h>
+#include <mutex>
 
 namespace android {
 namespace hardware {
@@ -65,6 +66,7 @@
     status_t mInitCheck;
     sensors_module_t *mSensorModule;
     sensors_poll_device_1_t *mSensorDevice;
+    std::mutex mPollLock;
 
     int getHalDeviceVersion() const;
 
diff --git a/soundtrigger/2.0/default/SoundTriggerHalImpl.h b/soundtrigger/2.0/default/SoundTriggerHalImpl.h
index 4e0d01d..8aa9285 100644
--- a/soundtrigger/2.0/default/SoundTriggerHalImpl.h
+++ b/soundtrigger/2.0/default/SoundTriggerHalImpl.h
@@ -20,6 +20,7 @@
 #include <android/hardware/soundtrigger/2.0/ISoundTriggerHw.h>
 #include <android/hardware/soundtrigger/2.0/ISoundTriggerHwCallback.h>
 #include <hidl/Status.h>
+#include <stdatomic.h>
 #include <utils/threads.h>
 #include <utils/KeyedVector.h>
 #include <system/sound_trigger.h>
diff --git a/wifi/1.0/default/android.hardware.wifi@1.0-service.rc b/wifi/1.0/default/android.hardware.wifi@1.0-service.rc
index c0ae4d4..696b1f9 100644
--- a/wifi/1.0/default/android.hardware.wifi@1.0-service.rc
+++ b/wifi/1.0/default/android.hardware.wifi@1.0-service.rc
@@ -1,4 +1,4 @@
 service wifi_hal_legacy /vendor/bin/hw/android.hardware.wifi@1.0-service
     class hal
     user wifi
-    group wifi
+    group wifi gps
diff --git a/wifi/1.0/default/hidl_struct_util.cpp b/wifi/1.0/default/hidl_struct_util.cpp
index 82364cb..485ae7e 100644
--- a/wifi/1.0/default/hidl_struct_util.cpp
+++ b/wifi/1.0/default/hidl_struct_util.cpp
@@ -96,7 +96,7 @@
   if (!hidl_caps) {
     return false;
   }
-  *hidl_caps = 0;
+  *hidl_caps = {};
   using HidlChipCaps = IWifiChip::ChipCapabilityMask;
   for (const auto feature : {legacy_hal::WIFI_LOGGER_MEMORY_DUMP_SUPPORTED,
                              legacy_hal::WIFI_LOGGER_DRIVER_DUMP_SUPPORTED,
@@ -133,6 +133,7 @@
   if (!hidl_status) {
     return false;
   }
+  *hidl_status = {};
   hidl_status->ringName = reinterpret_cast<const char*>(legacy_status.name);
   hidl_status->flags = 0;
   for (const auto flag : {WIFI_RING_BUFFER_FLAG_HAS_BINARY_ENTRIES,
@@ -165,7 +166,7 @@
   if (!hidl_status_vec) {
     return false;
   }
-  hidl_status_vec->clear();
+  *hidl_status_vec = {};
   for (const auto& legacy_status : legacy_status_vec) {
     WifiDebugRingBufferStatus hidl_status;
     if (!convertLegacyDebugRingBufferStatusToHidl(legacy_status,
@@ -183,6 +184,7 @@
   if (!hidl_stats) {
     return false;
   }
+  *hidl_stats = {};
   hidl_stats->totalCmdEventWakeCnt =
       legacy_stats.wake_reason_cnt.total_cmd_event_wake;
   hidl_stats->cmdEventWakeCntPerType = legacy_stats.cmd_event_wake_cnt;
@@ -227,6 +229,7 @@
   if (!hidl_caps) {
     return false;
   }
+  *hidl_caps = {};
   *hidl_caps = 0;
   using HidlStaIfaceCaps = IWifiStaIface::StaIfaceCapabilityMask;
   for (const auto feature : {legacy_hal::WIFI_LOGGER_PACKET_FATE_SUPPORTED}) {
@@ -263,6 +266,7 @@
   if (!hidl_caps) {
     return false;
   }
+  *hidl_caps = {};
   hidl_caps->version = legacy_caps.version;
   hidl_caps->maxLength = legacy_caps.max_len;
   return true;
@@ -299,6 +303,7 @@
   if (!hidl_caps) {
     return false;
   }
+  *hidl_caps = {};
   hidl_caps->maxCacheSize = legacy_caps.max_scan_cache_size;
   hidl_caps->maxBuckets = legacy_caps.max_scan_buckets;
   hidl_caps->maxApCachePerScan = legacy_caps.max_ap_cache_per_scan;
@@ -332,6 +337,7 @@
   if (!legacy_scan_params) {
     return false;
   }
+  *legacy_scan_params = {};
   legacy_scan_params->base_period = hidl_scan_params.basePeriodInMs;
   legacy_scan_params->max_ap_per_scan = hidl_scan_params.maxApPerScan;
   legacy_scan_params->report_threshold_percent =
@@ -350,7 +356,7 @@
         legacy_scan_params->buckets[bucket_idx];
     legacy_bucket_spec.bucket = bucket_idx;
     legacy_bucket_spec.band =
-        static_cast<legacy_hal::wifi_band>(hidl_bucket_spec.band);
+        convertHidlWifiBandToLegacy(hidl_bucket_spec.band);
     legacy_bucket_spec.period = hidl_bucket_spec.periodInMs;
     legacy_bucket_spec.max_period = hidl_bucket_spec.exponentialMaxPeriodInMs;
     legacy_bucket_spec.base = hidl_bucket_spec.exponentialBase;
@@ -384,6 +390,7 @@
   if (!hidl_ie) {
     return false;
   }
+  *hidl_ie = {};
   hidl_ie->id = legacy_ie.id;
   hidl_ie->data =
       std::vector<uint8_t>(legacy_ie.data, legacy_ie.data + legacy_ie.len);
@@ -396,6 +403,7 @@
   if (!ie_blob || !hidl_ies) {
     return false;
   }
+  *hidl_ies = {};
   const uint8_t* ies_begin = ie_blob;
   const uint8_t* ies_end = ie_blob + ie_blob_len;
   const uint8_t* next_ie = ies_begin;
@@ -426,10 +434,11 @@
   if (!hidl_scan_result) {
     return false;
   }
+  *hidl_scan_result = {};
   hidl_scan_result->timeStampInUs = legacy_scan_result.ts;
   hidl_scan_result->ssid = std::vector<uint8_t>(
       legacy_scan_result.ssid,
-      legacy_scan_result.ssid + sizeof(legacy_scan_result.ssid));
+      legacy_scan_result.ssid + strlen(legacy_scan_result.ssid));
   memcpy(hidl_scan_result->bssid.data(),
          legacy_scan_result.bssid,
          hidl_scan_result->bssid.size());
@@ -456,6 +465,7 @@
   if (!hidl_scan_data) {
     return false;
   }
+  *hidl_scan_data = {};
   hidl_scan_data->flags = 0;
   for (const auto flag : {legacy_hal::WIFI_SCAN_FLAG_INTERRUPTED}) {
     if (legacy_cached_scan_result.flags & flag) {
@@ -492,7 +502,7 @@
   if (!hidl_scan_datas) {
     return false;
   }
-  hidl_scan_datas->clear();
+  *hidl_scan_datas = {};
   for (const auto& legacy_cached_scan_result : legacy_cached_scan_results) {
     StaScanData hidl_scan_data;
     if (!convertLegacyCachedGscanResultsToHidl(legacy_cached_scan_result,
@@ -579,6 +589,7 @@
   if (!hidl_frame) {
     return false;
   }
+  *hidl_frame = {};
   hidl_frame->frameType =
       convertLegacyDebugPacketFateFrameTypeToHidl(legacy_frame.payload_type);
   hidl_frame->frameLen = legacy_frame.frame_len;
@@ -597,6 +608,7 @@
   if (!hidl_fate) {
     return false;
   }
+  *hidl_fate = {};
   hidl_fate->fate = convertLegacyDebugTxPacketFateToHidl(legacy_fate.fate);
   return convertLegacyDebugPacketFateFrameToHidl(legacy_fate.frame_inf,
                                                  &hidl_fate->frameInfo);
@@ -608,7 +620,7 @@
   if (!hidl_fates) {
     return false;
   }
-  hidl_fates->clear();
+  *hidl_fates = {};
   for (const auto& legacy_fate : legacy_fates) {
     WifiDebugTxPacketFateReport hidl_fate;
     if (!convertLegacyDebugTxPacketFateToHidl(legacy_fate, &hidl_fate)) {
@@ -625,6 +637,7 @@
   if (!hidl_fate) {
     return false;
   }
+  *hidl_fate = {};
   hidl_fate->fate = convertLegacyDebugRxPacketFateToHidl(legacy_fate.fate);
   return convertLegacyDebugPacketFateFrameToHidl(legacy_fate.frame_inf,
                                                  &hidl_fate->frameInfo);
@@ -636,7 +649,7 @@
   if (!hidl_fates) {
     return false;
   }
-  hidl_fates->clear();
+  *hidl_fates = {};
   for (const auto& legacy_fate : legacy_fates) {
     WifiDebugRxPacketFateReport hidl_fate;
     if (!convertLegacyDebugRxPacketFateToHidl(legacy_fate, &hidl_fate)) {
@@ -653,6 +666,7 @@
   if (!hidl_stats) {
     return false;
   }
+  *hidl_stats = {};
   // iface legacy_stats conversion.
   hidl_stats->iface.beaconRx = legacy_stats.iface.beacon_rx;
   hidl_stats->iface.avgRssiMgmt = legacy_stats.iface.rssi_mgmt;
@@ -706,6 +720,7 @@
   if (!hidl_caps) {
     return false;
   }
+  *hidl_caps = {};
   hidl_caps->maxBlacklistSize = legacy_caps.max_blacklist_size;
   hidl_caps->maxWhitelistSize = legacy_caps.max_whitelist_size;
   return true;
@@ -717,6 +732,7 @@
   if (!legacy_config) {
     return false;
   }
+  *legacy_config = {};
   if (hidl_config.bssidBlacklist.size() > MAX_BLACKLIST_BSSID ||
       hidl_config.ssidWhitelist.size() > MAX_WHITELIST_SSID) {
     return false;
@@ -762,7 +778,7 @@
     LOG(ERROR) << "convertHidlNanEnableRequestToLegacy: null legacy_request";
     return false;
   }
-  memset(legacy_request, 0, sizeof(legacy_hal::NanEnableRequest));
+  *legacy_request = {};
 
   legacy_request->config_2dot4g_support = 1;
   legacy_request->support_2dot4g_val = hidl_request.operateInBand[
@@ -892,7 +908,7 @@
     LOG(ERROR) << "convertHidlNanPublishRequestToLegacy: null legacy_request";
     return false;
   }
-  memset(legacy_request, 0, sizeof(legacy_hal::NanPublishRequest));
+  *legacy_request = {};
 
   legacy_request->publish_id = hidl_request.baseConfigs.sessionId;
   legacy_request->ttl = hidl_request.baseConfigs.ttlSec;
@@ -984,7 +1000,7 @@
     LOG(ERROR) << "convertHidlNanSubscribeRequestToLegacy: legacy_request is null";
     return false;
   }
-  memset(legacy_request, 0, sizeof(legacy_hal::NanSubscribeRequest));
+  *legacy_request = {};
 
   legacy_request->subscribe_id = hidl_request.baseConfigs.sessionId;
   legacy_request->ttl = hidl_request.baseConfigs.ttlSec;
@@ -1089,7 +1105,7 @@
     LOG(ERROR) << "convertHidlNanTransmitFollowupRequestToLegacy: legacy_request is null";
     return false;
   }
-  memset(legacy_request, 0, sizeof(legacy_hal::NanTransmitFollowupRequest));
+  *legacy_request = {};
 
   legacy_request->publish_subscribe_id = hidl_request.discoverySessionId;
   legacy_request->requestor_instance_id = hidl_request.peerId;
@@ -1128,7 +1144,7 @@
     LOG(ERROR) << "convertHidlNanConfigRequestToLegacy: legacy_request is null";
     return false;
   }
-  memset(legacy_request, 0, sizeof(legacy_hal::NanConfigRequest));
+  *legacy_request = {};
 
   // TODO: b/34059183 tracks missing configurations in legacy HAL or uknown defaults
   legacy_request->master_pref = hidl_request.masterPref;
@@ -1218,7 +1234,7 @@
     LOG(ERROR) << "convertHidlNanDataPathInitiatorRequestToLegacy: legacy_request is null";
     return false;
   }
-  memset(legacy_request, 0, sizeof(legacy_hal::NanDataPathInitiatorRequest));
+  *legacy_request = {};
 
   legacy_request->requestor_instance_id = hidl_request.peerId;
   memcpy(legacy_request->peer_disc_mac_addr, hidl_request.peerDiscMacAddr.data(), 6);
@@ -1253,7 +1269,7 @@
     LOG(ERROR) << "convertHidlNanDataPathIndicationResponseToLegacy: legacy_request is null";
     return false;
   }
-  memset(legacy_request, 0, sizeof(legacy_hal::NanDataPathIndicationResponse));
+  *legacy_request = {};
 
   legacy_request->rsp_code = hidl_request.acceptRequest ?
         legacy_hal::NAN_DP_REQUEST_ACCEPT : legacy_hal::NAN_DP_REQUEST_REJECT;
@@ -1286,9 +1302,10 @@
     LOG(ERROR) << "convertLegacyNanResponseHeaderToHidl: wifiNanStatus is null";
     return false;
   }
+  *wifiNanStatus = {};
+
   wifiNanStatus->status = convertLegacyNanStatusTypeToHidl(legacy_response.status);
   wifiNanStatus->description = legacy_response.nan_error;
-
   return true;
 }
 
@@ -1299,6 +1316,8 @@
     LOG(ERROR) << "convertLegacyNanCapabilitiesResponseToHidl: hidl_response is null";
     return false;
   }
+  *hidl_response = {};
+
   hidl_response->maxConcurrentClusters = legacy_response.max_concurrent_nan_clusters;
   hidl_response->maxPublishes = legacy_response.max_publishes;
   hidl_response->maxSubscribes = legacy_response.max_subscribes;
@@ -1325,6 +1344,8 @@
     LOG(ERROR) << "convertLegacyNanMatchIndToHidl: hidl_ind is null";
     return false;
   }
+  *hidl_ind = {};
+
   hidl_ind->discoverySessionId = legacy_ind.publish_subscribe_id;
   hidl_ind->peerId = legacy_ind.requestor_instance_id;
   hidl_ind->addr = hidl_array<uint8_t, 6>(legacy_ind.addr);
@@ -1356,6 +1377,8 @@
     LOG(ERROR) << "convertLegacyNanFollowupIndToHidl: hidl_ind is null";
     return false;
   }
+  *hidl_ind = {};
+
   hidl_ind->discoverySessionId = legacy_ind.publish_subscribe_id;
   hidl_ind->peerId = legacy_ind.requestor_instance_id;
   hidl_ind->addr = hidl_array<uint8_t, 6>(legacy_ind.addr);
@@ -1376,6 +1399,8 @@
     LOG(ERROR) << "convertLegacyNanDataPathRequestIndToHidl: hidl_ind is null";
     return false;
   }
+  *hidl_ind = {};
+
   hidl_ind->discoverySessionId = legacy_ind.service_instance_id;
   hidl_ind->peerDiscMacAddr = hidl_array<uint8_t, 6>(legacy_ind.peer_disc_mac_addr);
   hidl_ind->ndpInstanceId = legacy_ind.ndp_instance_id;
@@ -1394,6 +1419,8 @@
     LOG(ERROR) << "convertLegacyNanDataPathConfirmIndToHidl: hidl_ind is null";
     return false;
   }
+  *hidl_ind = {};
+
   hidl_ind->ndpInstanceId = legacy_ind.ndp_instance_id;
   hidl_ind->dataPathSetupSuccess = legacy_ind.rsp_code == legacy_hal::NAN_DP_REQUEST_ACCEPT;
   hidl_ind->peerNdiMacAddr = hidl_array<uint8_t, 6>(legacy_ind.peer_ndi_mac_addr);
@@ -1635,6 +1662,7 @@
   if (!legacy_info) {
     return false;
   }
+  *legacy_info = {};
   legacy_info->width = convertHidlWifiChannelWidthToLegacy(hidl_info.width);
   legacy_info->center_freq = hidl_info.centerFreq;
   legacy_info->center_freq0 = hidl_info.centerFreq0;
@@ -1648,6 +1676,7 @@
   if (!hidl_info) {
     return false;
   }
+  *hidl_info = {};
   hidl_info->width = convertLegacyWifiChannelWidthToHidl(legacy_info.width);
   hidl_info->centerFreq = legacy_info.center_freq;
   hidl_info->centerFreq0 = legacy_info.center_freq0;
@@ -1660,6 +1689,7 @@
   if (!legacy_config) {
     return false;
   }
+  *legacy_config = {};
   CHECK(hidl_config.addr.size() == sizeof(legacy_config->addr));
   memcpy(legacy_config->addr, hidl_config.addr.data(), hidl_config.addr.size());
   legacy_config->type = convertHidlRttTypeToLegacy(hidl_config.type);
@@ -1688,7 +1718,7 @@
   if (!legacy_configs) {
     return false;
   }
-  legacy_configs->clear();
+  *legacy_configs = {};
   for (const auto& hidl_config : hidl_configs) {
     legacy_hal::wifi_rtt_config legacy_config;
     if (!convertHidlRttConfigToLegacy(hidl_config, &legacy_config)) {
@@ -1705,6 +1735,7 @@
   if (!legacy_info) {
     return false;
   }
+  *legacy_info = {};
   legacy_info->latitude = hidl_info.latitude;
   legacy_info->longitude = hidl_info.longitude;
   legacy_info->altitude = hidl_info.altitude;
@@ -1725,6 +1756,7 @@
   if (!legacy_info) {
     return false;
   }
+  *legacy_info = {};
   CHECK(hidl_info.countryCode.size() == sizeof(legacy_info->country_code));
   memcpy(legacy_info->country_code,
          hidl_info.countryCode.data(),
@@ -1745,6 +1777,7 @@
   if (!legacy_responder) {
     return false;
   }
+  *legacy_responder = {};
   if (!convertHidlWifiChannelInfoToLegacy(hidl_responder.channel,
                                           &legacy_responder->channel)) {
     return false;
@@ -1760,6 +1793,7 @@
   if (!hidl_responder) {
     return false;
   }
+  *hidl_responder = {};
   if (!convertLegacyWifiChannelInfoToHidl(legacy_responder.channel,
                                           &hidl_responder->channel)) {
     return false;
@@ -1775,6 +1809,7 @@
   if (!hidl_capabilities) {
     return false;
   }
+  *hidl_capabilities = {};
   hidl_capabilities->rttOneSidedSupported =
       legacy_capabilities.rtt_one_sided_supported;
   hidl_capabilities->rttFtmSupported = legacy_capabilities.rtt_ftm_supported;
@@ -1814,6 +1849,7 @@
   if (!hidl_rate) {
     return false;
   }
+  *hidl_rate = {};
   hidl_rate->preamble =
       convertLegacyWifiRatePreambleToHidl(legacy_rate.preamble);
   hidl_rate->nss = convertLegacyWifiRateNssToHidl(legacy_rate.nss);
@@ -1829,6 +1865,7 @@
   if (!hidl_result) {
     return false;
   }
+  *hidl_result = {};
   CHECK(sizeof(legacy_result.addr) == hidl_result->addr.size());
   memcpy(
       hidl_result->addr.data(), legacy_result.addr, sizeof(legacy_result.addr));
@@ -1873,7 +1910,7 @@
   if (!hidl_results) {
     return false;
   }
-  hidl_results->clear();
+  *hidl_results = {};
   for (const auto legacy_result : legacy_results) {
     RttResult hidl_result;
     if (!convertLegacyRttResultToHidl(*legacy_result, &hidl_result)) {
diff --git a/wifi/1.0/vts/functional/wifi_hidl_test_utils.cpp b/wifi/1.0/vts/functional/wifi_hidl_test_utils.cpp
index 9042075..e0c92fe 100644
--- a/wifi/1.0/vts/functional/wifi_hidl_test_utils.cpp
+++ b/wifi/1.0/vts/functional/wifi_hidl_test_utils.cpp
@@ -36,11 +36,12 @@
 using ::android::hardware::hidl_vec;
 
 void stopFramework() {
-    ASSERT_EQ(std::system("svc wifi disable"), 0);
+    ASSERT_EQ(std::system("stop"), 0);
+    stopWifi();
     sleep(5);
 }
 
-void startFramework() { ASSERT_EQ(std::system("svc wifi enable"), 0); }
+void startFramework() { ASSERT_EQ(std::system("start"), 0); }
 
 sp<IWifi> getWifi() {
     sp<IWifi> wifi = ::testing::VtsHalHidlTargetBaseTest::getService<IWifi>();
diff --git a/wifi/1.0/vts/functional/wifi_nan_iface_hidl_test.cpp b/wifi/1.0/vts/functional/wifi_nan_iface_hidl_test.cpp
index eb482c9..95c0e5d 100644
--- a/wifi/1.0/vts/functional/wifi_nan_iface_hidl_test.cpp
+++ b/wifi/1.0/vts/functional/wifi_nan_iface_hidl_test.cpp
@@ -17,24 +17,427 @@
 #include <android-base/logging.h>
 
 #include <android/hardware/wifi/1.0/IWifiNanIface.h>
+#include <android/hardware/wifi/1.0/IWifiNanIfaceEventCallback.h>
 
 #include <VtsHalHidlTargetBaseTest.h>
+#include <chrono>
+#include <condition_variable>
+#include <mutex>
 
+#include "wifi_hidl_call_util.h"
 #include "wifi_hidl_test_utils.h"
 
-using ::android::hardware::wifi::V1_0::IWifiNanIface;
+using namespace ::android::hardware::wifi::V1_0;
+
+using ::android::hardware::Return;
+using ::android::hardware::Void;
 using ::android::sp;
 
+#define TIMEOUT_PERIOD 10
+
 /**
  * Fixture to use for all NAN Iface HIDL interface tests.
  */
 class WifiNanIfaceHidlTest : public ::testing::VtsHalHidlTargetBaseTest {
-   public:
-    virtual void SetUp() override {}
+  public:
+    virtual void SetUp() override {
+      iwifiNanIface = getWifiNanIface();
+      ASSERT_NE(nullptr, iwifiNanIface.get());
+      ASSERT_EQ(WifiStatusCode::SUCCESS, HIDL_INVOKE(iwifiNanIface, registerEventCallback,
+            new WifiNanIfaceEventCallback(*this)).code);
+    }
 
-    virtual void TearDown() override { stopWifi(); }
+    virtual void TearDown() override {
+      stopWifi();
+    }
 
-   protected:
+    /* Used as a mechanism to inform the test about data/event callback */
+    inline void notify() {
+      std::unique_lock<std::mutex> lock(mtx_);
+      count_++;
+      cv_.notify_one();
+    }
+
+    enum CallbackType {
+        INVALID = -2,
+        ANY_CALLBACK = -1,
+
+        NOTIFY_CAPABILITIES_RESPONSE = 0,
+        NOTIFY_ENABLE_RESPONSE,
+        NOTIFY_CONFIG_RESPONSE,
+        NOTIFY_DISABLE_RESPONSE,
+        NOTIFY_START_PUBLISH_RESPONSE,
+        NOTIFY_STOP_PUBLISH_RESPONSE,
+        NOTIFY_START_SUBSCRIBE_RESPONSE,
+        NOTIFY_STOP_SUBSCRIBE_RESPONSE,
+        NOTIFY_TRANSMIT_FOLLOWUP_RESPONSE,
+        NOTIFY_CREATE_DATA_INTERFACE_RESPONSE,
+        NOTIFY_DELETE_DATA_INTERFACE_RESPONSE,
+        NOTIFY_INITIATE_DATA_PATH_RESPONSE,
+        NOTIFY_RESPOND_TO_DATA_PATH_INDICATION_RESPONSE,
+        NOTIFY_TERMINATE_DATA_PATH_RESPONSE,
+
+        EVENT_CLUSTER_EVENT,
+        EVENT_DISABLED,
+        EVENT_PUBLISH_TERMINATED,
+        EVENT_SUBSCRIBE_TERMINATED,
+        EVENT_MATCH,
+        EVENT_MATCH_EXPIRED,
+        EVENT_FOLLOWUP_RECEIVED,
+        EVENT_TRANSMIT_FOLLOWUP,
+        EVENT_DATA_PATH_REQUEST,
+        EVENT_DATA_PATH_CONFIRM,
+        EVENT_DATA_PATH_TERMINATED
+    };
+
+    /* Test code calls this function to wait for data/event callback */
+    inline std::cv_status wait(CallbackType waitForCallbackType) {
+      std::unique_lock<std::mutex> lock(mtx_);
+
+      EXPECT_NE(INVALID, waitForCallbackType); // can't ASSERT in a non-void-returning method
+
+      callbackType = INVALID;
+      std::cv_status status = std::cv_status::no_timeout;
+      auto now = std::chrono::system_clock::now();
+      while (count_ == 0) {
+        status = cv_.wait_until(lock, now + std::chrono::seconds(TIMEOUT_PERIOD));
+        if (status == std::cv_status::timeout) return status;
+        if (waitForCallbackType != ANY_CALLBACK && callbackType != INVALID
+            && callbackType != waitForCallbackType) {
+          count_--;
+        }
+      }
+      count_--;
+      return status;
+    }
+
+    class WifiNanIfaceEventCallback: public IWifiNanIfaceEventCallback {
+      WifiNanIfaceHidlTest& parent_;
+
+     public:
+      WifiNanIfaceEventCallback(WifiNanIfaceHidlTest& parent) : parent_(parent) {};
+
+      virtual ~WifiNanIfaceEventCallback() = default;
+
+      Return<void> notifyCapabilitiesResponse(
+            uint16_t id,
+            const WifiNanStatus& status,
+            const NanCapabilities& capabilities) override {
+        parent_.callbackType = NOTIFY_CAPABILITIES_RESPONSE;
+
+        parent_.id = id;
+        parent_.status = status;
+        parent_.capabilities = capabilities;
+
+        parent_.notify();
+        return Void();
+      }
+
+      Return<void> notifyEnableResponse(
+            uint16_t id,
+            const WifiNanStatus& status) override {
+        parent_.callbackType = NOTIFY_ENABLE_RESPONSE;
+
+        parent_.id = id;
+        parent_.status = status;
+
+        parent_.notify();
+        return Void();
+      }
+
+      Return<void> notifyConfigResponse(
+            uint16_t id,
+            const WifiNanStatus& status) override {
+        parent_.callbackType = NOTIFY_CONFIG_RESPONSE;
+
+        parent_.id = id;
+        parent_.status = status;
+
+        parent_.notify();
+        return Void();
+      }
+
+      Return<void> notifyDisableResponse(
+            uint16_t id,
+            const WifiNanStatus& status) override {
+        parent_.callbackType = NOTIFY_DISABLE_RESPONSE;
+
+        parent_.id = id;
+        parent_.status = status;
+
+        parent_.notify();
+        return Void();
+      }
+
+      Return<void> notifyStartPublishResponse(
+            uint16_t id,
+            const WifiNanStatus& status,
+            uint8_t sessionId) override {
+        parent_.callbackType = NOTIFY_START_PUBLISH_RESPONSE;
+
+        parent_.id = id;
+        parent_.status = status;
+        parent_.sessionId = sessionId;
+
+        parent_.notify();
+        return Void();
+      }
+
+      Return<void> notifyStopPublishResponse(
+            uint16_t id,
+            const WifiNanStatus& status) override {
+        parent_.callbackType = NOTIFY_STOP_PUBLISH_RESPONSE;
+
+        parent_.id = id;
+        parent_.status = status;
+
+        parent_.notify();
+        return Void();
+      }
+
+      Return<void> notifyStartSubscribeResponse(
+            uint16_t id,
+            const WifiNanStatus& status,
+            uint8_t sessionId) override {
+        parent_.callbackType = NOTIFY_START_SUBSCRIBE_RESPONSE;
+
+        parent_.id = id;
+        parent_.status = status;
+        parent_.sessionId = sessionId;
+
+        parent_.notify();
+        return Void();
+      }
+
+      Return<void> notifyStopSubscribeResponse(
+            uint16_t id,
+            const WifiNanStatus& status) override {
+        parent_.callbackType = NOTIFY_STOP_SUBSCRIBE_RESPONSE;
+
+        parent_.id = id;
+        parent_.status = status;
+
+        parent_.notify();
+        return Void();
+      }
+
+      Return<void> notifyTransmitFollowupResponse(
+            uint16_t id,
+            const WifiNanStatus& status) override {
+        parent_.callbackType = NOTIFY_TRANSMIT_FOLLOWUP_RESPONSE;
+
+        parent_.id = id;
+        parent_.status = status;
+
+        parent_.notify();
+        return Void();
+      }
+
+      Return<void> notifyCreateDataInterfaceResponse(
+            uint16_t id,
+            const WifiNanStatus& status) override {
+        parent_.callbackType = NOTIFY_CREATE_DATA_INTERFACE_RESPONSE;
+
+        parent_.id = id;
+        parent_.status = status;
+
+        parent_.notify();
+        return Void();
+      }
+
+      Return<void> notifyDeleteDataInterfaceResponse(
+            uint16_t id,
+            const WifiNanStatus& status) override {
+        parent_.callbackType = NOTIFY_DELETE_DATA_INTERFACE_RESPONSE;
+
+        parent_.id = id;
+        parent_.status = status;
+
+        parent_.notify();
+        return Void();
+      }
+
+      Return<void> notifyInitiateDataPathResponse(
+            uint16_t id,
+            const WifiNanStatus& status,
+            uint32_t ndpInstanceId) override {
+        parent_.callbackType = NOTIFY_INITIATE_DATA_PATH_RESPONSE;
+
+        parent_.id = id;
+        parent_.status = status;
+        parent_.ndpInstanceId = ndpInstanceId;
+
+        parent_.notify();
+        return Void();
+      }
+
+      Return<void> notifyRespondToDataPathIndicationResponse(
+            uint16_t id,
+            const WifiNanStatus& status) override {
+        parent_.callbackType = NOTIFY_RESPOND_TO_DATA_PATH_INDICATION_RESPONSE;
+
+        parent_.id = id;
+        parent_.status = status;
+
+        parent_.notify();
+        return Void();
+      }
+
+      Return<void> notifyTerminateDataPathResponse(
+            uint16_t id,
+            const WifiNanStatus& status) override {
+        parent_.callbackType = NOTIFY_TERMINATE_DATA_PATH_RESPONSE;
+
+        parent_.id = id;
+        parent_.status = status;
+
+        parent_.notify();
+        return Void();
+      }
+
+      Return<void> eventClusterEvent(
+            const NanClusterEventInd& event) override {
+        parent_.callbackType = EVENT_CLUSTER_EVENT;
+
+        parent_.nanClusterEventInd = event;
+
+        parent_.notify();
+        return Void();
+      }
+
+      Return<void> eventDisabled(
+            const WifiNanStatus& status) override {
+        parent_.callbackType = EVENT_DISABLED;
+
+        parent_.status = status;
+
+        parent_.notify();
+        return Void();
+      }
+
+      Return<void> eventPublishTerminated(
+            uint8_t sessionId,
+            const WifiNanStatus& status) override {
+        parent_.callbackType = EVENT_PUBLISH_TERMINATED;
+
+        parent_.sessionId = sessionId;
+        parent_.status = status;
+
+        parent_.notify();
+        return Void();
+      }
+
+      Return<void> eventSubscribeTerminated(
+            uint8_t sessionId,
+            const WifiNanStatus& status) override {
+        parent_.callbackType = EVENT_SUBSCRIBE_TERMINATED;
+
+        parent_.sessionId = sessionId;
+        parent_.status = status;
+
+        parent_.notify();
+        return Void();
+      }
+
+      Return<void> eventMatch(
+            const NanMatchInd& event) override {
+        parent_.callbackType = EVENT_MATCH;
+
+        parent_.nanMatchInd = event;
+
+        parent_.notify();
+        return Void();
+      }
+
+      Return<void> eventMatchExpired(
+            uint8_t discoverySessionId,
+            uint32_t peerId) override {
+        parent_.callbackType = EVENT_MATCH_EXPIRED;
+
+        parent_.sessionId = discoverySessionId;
+        parent_.peerId = peerId;
+
+        parent_.notify();
+        return Void();
+      }
+
+      Return<void> eventFollowupReceived(
+            const NanFollowupReceivedInd& event) override {
+        parent_.callbackType = EVENT_FOLLOWUP_RECEIVED;
+
+        parent_.nanFollowupReceivedInd = event;
+
+        parent_.notify();
+        return Void();
+      }
+
+      Return<void> eventTransmitFollowup(
+            uint16_t id,
+            const WifiNanStatus& status) override {
+        parent_.callbackType = EVENT_TRANSMIT_FOLLOWUP;
+
+        parent_.id = id;
+        parent_.status = status;
+
+        parent_.notify();
+        return Void();
+      }
+
+      Return<void> eventDataPathRequest(
+            const NanDataPathRequestInd& event) override {
+        parent_.callbackType = EVENT_DATA_PATH_REQUEST;
+
+        parent_.nanDataPathRequestInd = event;
+
+        parent_.notify();
+        return Void();
+      }
+
+      Return<void> eventDataPathConfirm(
+            const NanDataPathConfirmInd& event) override {
+        parent_.callbackType = EVENT_DATA_PATH_CONFIRM;
+
+        parent_.nanDataPathConfirmInd = event;
+
+        parent_.notify();
+        return Void();
+      }
+
+      Return<void> eventDataPathTerminated(
+            uint32_t ndpInstanceId) override {
+        parent_.callbackType = EVENT_DATA_PATH_TERMINATED;
+
+        parent_.ndpInstanceId = ndpInstanceId;
+
+        parent_.notify();
+        return Void();
+      }
+    };
+
+    private:
+      // synchronization objects
+      std::mutex mtx_;
+      std::condition_variable cv_;
+      int count_;
+
+    protected:
+      android::sp<IWifiNanIface> iwifiNanIface;
+
+      // Data from IWifiNanIfaceEventCallback callbacks: this is the collection of all
+      // arguments to all callbacks. They are set by the callback (notifications or
+      // events) and can be retrieved by tests.
+      CallbackType callbackType;
+      uint16_t id;
+      WifiNanStatus status;
+      NanCapabilities capabilities;
+      uint8_t sessionId;
+      uint32_t ndpInstanceId;
+      NanClusterEventInd nanClusterEventInd;
+      NanMatchInd nanMatchInd;
+      uint32_t peerId;
+      NanFollowupReceivedInd nanFollowupReceivedInd;
+      NanDataPathRequestInd nanDataPathRequestInd;
+      NanDataPathConfirmInd nanDataPathConfirmInd;
 };
 
 /*
@@ -43,6 +446,49 @@
  * successfully created.
  */
 TEST(WifiNanIfaceHidlTestNoFixture, Create) {
-    EXPECT_NE(nullptr, getWifiNanIface().get());
-    stopWifi();
+  ASSERT_NE(nullptr, getWifiNanIface().get());
+  stopWifi();
+}
+
+/*
+ * Fail: use past destruction
+ * Ensure that API calls fail with ERROR_WIFI_IFACE_INVALID when using an interface once wifi
+ * is disabled.
+ */
+TEST(WifiNanIfaceHidlTestNoFixture, FailOnIfaceInvalid) {
+  android::sp<IWifiNanIface> iwifiNanIface = getWifiNanIface();
+  ASSERT_NE(nullptr, iwifiNanIface.get());
+  stopWifi();
+  sleep(5); // make sure that all chips/interfaces are invalidated
+  ASSERT_EQ(WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+          HIDL_INVOKE(iwifiNanIface, getCapabilitiesRequest, 0).code);
+}
+
+/*
+ * getCapabilitiesRequest: validate that returns capabilities.
+ */
+TEST_F(WifiNanIfaceHidlTest, getCapabilitiesRequest) {
+  uint16_t inputCmdId = 10;
+  ASSERT_EQ(WifiStatusCode::SUCCESS,
+        HIDL_INVOKE(iwifiNanIface, getCapabilitiesRequest, inputCmdId).code);
+  // wait for a callback
+  ASSERT_EQ(std::cv_status::no_timeout, wait(NOTIFY_CAPABILITIES_RESPONSE));
+  ASSERT_EQ(NOTIFY_CAPABILITIES_RESPONSE, callbackType);
+  ASSERT_EQ(id, inputCmdId);
+
+  // check for reasonable capability values
+  EXPECT_GT(capabilities.maxConcurrentClusters, (unsigned int) 0);
+  EXPECT_GT(capabilities.maxPublishes, (unsigned int) 0);
+  EXPECT_GT(capabilities.maxSubscribes, (unsigned int) 0);
+  EXPECT_EQ(capabilities.maxServiceNameLen, (unsigned int) 255);
+  EXPECT_EQ(capabilities.maxMatchFilterLen, (unsigned int) 255);
+  EXPECT_GT(capabilities.maxTotalMatchFilterLen, (unsigned int) 255);
+  EXPECT_EQ(capabilities.maxServiceSpecificInfoLen, (unsigned int) 255);
+  EXPECT_GE(capabilities.maxExtendedServiceSpecificInfoLen, (unsigned int) 255);
+  EXPECT_GT(capabilities.maxNdiInterfaces, (unsigned int) 0);
+  EXPECT_GT(capabilities.maxNdpSessions, (unsigned int) 0);
+  EXPECT_GT(capabilities.maxAppInfoLen, (unsigned int) 0);
+  EXPECT_GT(capabilities.maxQueuedTransmitFollowupMsgs, (unsigned int) 0);
+  EXPECT_GT(capabilities.maxSubscribeInterfaceAddresses, (unsigned int) 0);
+  EXPECT_NE(capabilities.supportedCipherSuites, (unsigned int) 0);
 }