Merge "Fix HalGatekeeperHidlTargetBasicProfilingTest."
diff --git a/audio/2.0/default/Stream.h b/audio/2.0/default/Stream.h
index 0bbd803..73afe05 100644
--- a/audio/2.0/default/Stream.h
+++ b/audio/2.0/default/Stream.h
@@ -127,6 +127,7 @@
                                              IStream::createMmapBuffer_cb _hidl_cb) {
     Result retval(Result::NOT_SUPPORTED);
     MmapBufferInfo info;
+    native_handle_t* hidlHandle = nullptr;
 
     if (mStream->create_mmap_buffer != NULL) {
         struct audio_mmap_buffer_info halInfo;
@@ -134,7 +135,7 @@
                 "create_mmap_buffer",
                 mStream->create_mmap_buffer(mStream, minSizeFrames, &halInfo));
         if (retval == Result::OK) {
-            native_handle_t* hidlHandle = native_handle_create(1, 0);
+            hidlHandle = native_handle_create(1, 0);
             hidlHandle->data[0] = halInfo.shared_memory_fd;
             info.sharedMemory = hidl_memory("audio_buffer", hidlHandle,
                                             frameSize *halInfo.buffer_size_frames);
@@ -143,6 +144,10 @@
         }
     }
     _hidl_cb(retval, info);
+    if (hidlHandle != nullptr) {
+        native_handle_close(hidlHandle);
+        native_handle_delete(hidlHandle);
+    }
     return Void();
 }
 
diff --git a/audio/effect/2.0/vts/functional/audio_effect_hidl_hal_test.cpp b/audio/effect/2.0/vts/functional/audio_effect_hidl_hal_test.cpp
index 9b7d0cf..145d4c3 100644
--- a/audio/effect/2.0/vts/functional/audio_effect_hidl_hal_test.cpp
+++ b/audio/effect/2.0/vts/functional/audio_effect_hidl_hal_test.cpp
@@ -38,8 +38,7 @@
 class AudioEffectHidlTest : public ::testing::Test {
  public:
   virtual void SetUp() override {
-    // currently test passthrough mode only
-    effectsFactory = IEffectsFactory::getService("audio_effects_factory", true);
+    effectsFactory = IEffectsFactory::getService("audio_effects_factory");
     ASSERT_NE(effectsFactory, nullptr);
   }
 
diff --git a/biometrics/fingerprint/2.1/Android.bp b/biometrics/fingerprint/2.1/Android.bp
index 02b7328..2a252dc 100644
--- a/biometrics/fingerprint/2.1/Android.bp
+++ b/biometrics/fingerprint/2.1/Android.bp
@@ -62,3 +62,155 @@
         "android.hidl.base@1.0",
     ],
 }
+
+genrule {
+    name: "android.hardware.biometrics.fingerprint.vts.driver@2.1_genc++",
+    tools: ["hidl-gen", "vtsc"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lvts -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.biometrics.fingerprint@2.1 && $(location vtsc) -mDRIVER -tSOURCE -b$(genDir) android/hardware/biometrics/fingerprint/2.1/ $(genDir)/android/hardware/biometrics/fingerprint/2.1/",
+    srcs: [
+        "types.hal",
+        "IBiometricsFingerprint.hal",
+        "IBiometricsFingerprintClientCallback.hal",
+    ],
+    out: [
+        "android/hardware/biometrics/fingerprint/2.1/types.vts.cpp",
+        "android/hardware/biometrics/fingerprint/2.1/BiometricsFingerprint.vts.cpp",
+        "android/hardware/biometrics/fingerprint/2.1/BiometricsFingerprintClientCallback.vts.cpp",
+    ],
+}
+
+genrule {
+    name: "android.hardware.biometrics.fingerprint.vts.driver@2.1_genc++_headers",
+    tools: ["hidl-gen", "vtsc"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lvts -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.biometrics.fingerprint@2.1 && $(location vtsc) -mDRIVER -tHEADER -b$(genDir) android/hardware/biometrics/fingerprint/2.1/ $(genDir)/android/hardware/biometrics/fingerprint/2.1/",
+    srcs: [
+        "types.hal",
+        "IBiometricsFingerprint.hal",
+        "IBiometricsFingerprintClientCallback.hal",
+    ],
+    out: [
+        "android/hardware/biometrics/fingerprint/2.1/types.vts.h",
+        "android/hardware/biometrics/fingerprint/2.1/BiometricsFingerprint.vts.h",
+        "android/hardware/biometrics/fingerprint/2.1/BiometricsFingerprintClientCallback.vts.h",
+    ],
+}
+
+cc_library_shared {
+    name: "android.hardware.biometrics.fingerprint.vts.driver@2.1",
+    generated_sources: ["android.hardware.biometrics.fingerprint.vts.driver@2.1_genc++"],
+    generated_headers: ["android.hardware.biometrics.fingerprint.vts.driver@2.1_genc++_headers"],
+    export_generated_headers: ["android.hardware.biometrics.fingerprint.vts.driver@2.1_genc++_headers"],
+    shared_libs: [
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "liblog",
+        "libutils",
+        "libcutils",
+        "libvts_common",
+        "libvts_datatype",
+        "libvts_measurement",
+        "libvts_multidevice_proto",
+        "libcamera_metadata",
+        "libprotobuf-cpp-full",
+        "android.hidl.base@1.0",
+        "android.hardware.biometrics.fingerprint@2.1",
+    ],
+    export_shared_lib_headers: [
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "libutils",
+        "android.hidl.base@1.0",
+    ],
+}
+
+genrule {
+    name: "android.hardware.biometrics.fingerprint@2.1-IBiometricsFingerprint-vts.profiler_genc++",
+    tools: ["hidl-gen", "vtsc"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lvts -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.biometrics.fingerprint@2.1 && $(location vtsc) -mPROFILER -tSOURCE -b$(genDir) android/hardware/biometrics/fingerprint/2.1/ $(genDir)/android/hardware/biometrics/fingerprint/2.1/",
+    srcs: [
+        "IBiometricsFingerprint.hal",
+        "types.hal",
+    ],
+    out: [
+        "android/hardware/biometrics/fingerprint/2.1/BiometricsFingerprint.vts.cpp",
+        "android/hardware/biometrics/fingerprint/2.1/types.vts.cpp",
+    ],
+}
+
+genrule {
+    name: "android.hardware.biometrics.fingerprint@2.1-IBiometricsFingerprint-vts.profiler_genc++_headers",
+    tools: ["hidl-gen", "vtsc"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lvts -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.biometrics.fingerprint@2.1 && $(location vtsc) -mPROFILER -tHEADER -b$(genDir) android/hardware/biometrics/fingerprint/2.1/ $(genDir)/android/hardware/biometrics/fingerprint/2.1/",
+    srcs: [
+        "IBiometricsFingerprint.hal",
+        "types.hal",
+    ],
+    out: [
+        "android/hardware/biometrics/fingerprint/2.1/BiometricsFingerprint.vts.h",
+        "android/hardware/biometrics/fingerprint/2.1/types.vts.h",
+    ],
+}
+
+cc_library_shared {
+    name: "android.hardware.biometrics.fingerprint@2.1-IBiometricsFingerprint-vts.profiler",
+    generated_sources: ["android.hardware.biometrics.fingerprint@2.1-IBiometricsFingerprint-vts.profiler_genc++"],
+    generated_headers: ["android.hardware.biometrics.fingerprint@2.1-IBiometricsFingerprint-vts.profiler_genc++_headers"],
+    export_generated_headers: ["android.hardware.biometrics.fingerprint@2.1-IBiometricsFingerprint-vts.profiler_genc++_headers"],
+    shared_libs: [
+        "libbase",
+        "libhidlbase",
+        "libhidltransport",
+        "libvts_profiling",
+        "libvts_multidevice_proto",
+        "libprotobuf-cpp-full",
+        "android.hidl.base@1.0",
+        "android.hardware.biometrics.fingerprint@2.1",
+    ],
+}
+
+genrule {
+    name: "android.hardware.biometrics.fingerprint@2.1-IBiometricsFingerprintClientCallback-vts.profiler_genc++",
+    tools: ["hidl-gen", "vtsc"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lvts -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.biometrics.fingerprint@2.1 && $(location vtsc) -mPROFILER -tSOURCE -b$(genDir) android/hardware/biometrics/fingerprint/2.1/ $(genDir)/android/hardware/biometrics/fingerprint/2.1/",
+    srcs: [
+        "IBiometricsFingerprintClientCallback.hal",
+        "types.hal",
+    ],
+    out: [
+        "android/hardware/biometrics/fingerprint/2.1/BiometricsFingerprintClientCallback.vts.cpp",
+        "android/hardware/biometrics/fingerprint/2.1/types.vts.cpp",
+    ],
+}
+
+genrule {
+    name: "android.hardware.biometrics.fingerprint@2.1-IBiometricsFingerprintClientCallback-vts.profiler_genc++_headers",
+    tools: ["hidl-gen", "vtsc"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lvts -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.biometrics.fingerprint@2.1 && $(location vtsc) -mPROFILER -tHEADER -b$(genDir) android/hardware/biometrics/fingerprint/2.1/ $(genDir)/android/hardware/biometrics/fingerprint/2.1/",
+    srcs: [
+        "IBiometricsFingerprintClientCallback.hal",
+        "types.hal",
+    ],
+    out: [
+        "android/hardware/biometrics/fingerprint/2.1/BiometricsFingerprintClientCallback.vts.h",
+        "android/hardware/biometrics/fingerprint/2.1/types.vts.h",
+    ],
+}
+
+cc_library_shared {
+    name: "android.hardware.biometrics.fingerprint@2.1-IBiometricsFingerprintClientCallback-vts.profiler",
+    generated_sources: ["android.hardware.biometrics.fingerprint@2.1-IBiometricsFingerprintClientCallback-vts.profiler_genc++"],
+    generated_headers: ["android.hardware.biometrics.fingerprint@2.1-IBiometricsFingerprintClientCallback-vts.profiler_genc++_headers"],
+    export_generated_headers: ["android.hardware.biometrics.fingerprint@2.1-IBiometricsFingerprintClientCallback-vts.profiler_genc++_headers"],
+    shared_libs: [
+        "libbase",
+        "libhidlbase",
+        "libhidltransport",
+        "libvts_profiling",
+        "libvts_multidevice_proto",
+        "libprotobuf-cpp-full",
+        "android.hidl.base@1.0",
+        "android.hardware.biometrics.fingerprint@2.1",
+    ],
+}
diff --git a/biometrics/fingerprint/2.1/IBiometricsFingerprintClientCallback.hal b/biometrics/fingerprint/2.1/IBiometricsFingerprintClientCallback.hal
index 63435d1..d913cf1 100644
--- a/biometrics/fingerprint/2.1/IBiometricsFingerprintClientCallback.hal
+++ b/biometrics/fingerprint/2.1/IBiometricsFingerprintClientCallback.hal
@@ -43,8 +43,9 @@
      * @param deviceId the instance of this fingerprint device
      * @param fingerId the fingerprint templetate that was authenticated
      * @param groupId the groupid for the template that was authenticated
+     * @param token the hardware authentication token to pass to Keystore.addAuthToken()
      */
-    oneway onAuthenticated(uint64_t deviceId, uint32_t fingerId, uint32_t groupId);
+    oneway onAuthenticated(uint64_t deviceId, uint32_t fingerId, uint32_t groupId, vec<uint8_t> token);
 
     /**
      * Sent when a fingerprint error occurs
diff --git a/biometrics/fingerprint/2.1/default/BiometricsFingerprint.cpp b/biometrics/fingerprint/2.1/default/BiometricsFingerprint.cpp
index 516cd00..154b7a6 100644
--- a/biometrics/fingerprint/2.1/default/BiometricsFingerprint.cpp
+++ b/biometrics/fingerprint/2.1/default/BiometricsFingerprint.cpp
@@ -14,10 +14,9 @@
  * limitations under the License.
  */
 #define LOG_TAG "android.hardware.biometrics.fingerprint@2.1-service"
+#define LOG_VERBOSE "android.hardware.biometrics.fingerprint@2.1-service"
 
 // For communication with Keystore binder interface
-#include <binder/IServiceManager.h>
-#include <keystore/IKeystoreService.h>
 #include <keystore/keystore.h> // for error codes
 #include <hardware/hw_auth_token.h>
 
@@ -40,23 +39,19 @@
 using RequestStatus =
         android::hardware::biometrics::fingerprint::V2_1::RequestStatus;
 
-sp<IBiometricsFingerprintClientCallback>
-    BiometricsFingerprint::mClientCallback = nullptr;
+BiometricsFingerprint *BiometricsFingerprint::sInstance = nullptr;
 
-// TODO: This is here because HAL 2.1 doesn't have a way to propagate a
-// unique token for its driver. Subsequent versions should send a unique
-// token for each call to notify(). This is fine as long as there's only
-// one fingerprint device on the platform.
-fingerprint_device_t *BiometricsFingerprint::sDevice = nullptr;
-
-BiometricsFingerprint::BiometricsFingerprint(fingerprint_device_t *device)
-    : mDevice(device) {
-    sDevice = mDevice; // keep track of the most recent instance
+BiometricsFingerprint::BiometricsFingerprint() : mClientCallback(nullptr), mDevice(nullptr) {
+    sInstance = this; // keep track of the most recent instance
+    mDevice = openHal();
+    if (!mDevice) {
+        ALOGE("Can't open HAL module");
+    }
 }
 
 BiometricsFingerprint::~BiometricsFingerprint() {
-    ALOG(LOG_VERBOSE, LOG_TAG, "nativeCloseHal()\n");
-    if (mDevice == NULL) {
+    ALOGV(LOG_VERBOSE, LOG_TAG, "~BiometricsFingerprint()\n");
+    if (mDevice == nullptr) {
         ALOGE("No valid device");
         return;
     }
@@ -66,7 +61,7 @@
         ALOGE("Can't close fingerprint module, error: %d", err);
         return;
     }
-    mDevice = NULL;
+    mDevice = nullptr;
 }
 
 Return<RequestStatus> BiometricsFingerprint::ErrorFilter(int32_t error) {
@@ -107,6 +102,8 @@
             return FingerprintError::ERROR_CANCELED;
         case FINGERPRINT_ERROR_UNABLE_TO_REMOVE:
             return FingerprintError::ERROR_UNABLE_TO_REMOVE;
+        case FINGERPRINT_ERROR_LOCKOUT:
+            return FingerprintError::ERROR_LOCKOUT;
         default:
             if (error >= FINGERPRINT_ERROR_VENDOR_BASE) {
                 // vendor specific code.
@@ -114,7 +111,7 @@
                 return FingerprintError::ERROR_VENDOR;
             }
     }
-    ALOGE("Unknown error from fingerprint vendor library");
+    ALOGE("Unknown error from fingerprint vendor library: %d", error);
     return FingerprintError::ERROR_UNABLE_TO_PROCESS;
 }
 
@@ -143,13 +140,17 @@
                 return FingerprintAcquiredInfo::ACQUIRED_VENDOR;
             }
     }
-    ALOGE("Unknown acquiredmsg from fingerprint vendor library");
+    ALOGE("Unknown acquiredmsg from fingerprint vendor library: %d", info);
     return FingerprintAcquiredInfo::ACQUIRED_INSUFFICIENT;
 }
 
 Return<uint64_t> BiometricsFingerprint::setNotify(
         const sp<IBiometricsFingerprintClientCallback>& clientCallback) {
     mClientCallback = clientCallback;
+    // This is here because HAL 2.1 doesn't have a way to propagate a
+    // unique token for its driver. Subsequent versions should send a unique
+    // token for each call to setNotify(). This is fine as long as there's only
+    // one fingerprint device on the platform.
     return reinterpret_cast<uint64_t>(mDevice);
 }
 
@@ -199,36 +200,44 @@
 }
 
 IBiometricsFingerprint* BiometricsFingerprint::getInstance() {
+    if (!sInstance) {
+      sInstance = new BiometricsFingerprint();
+    }
+    return sInstance;
+}
+
+fingerprint_device_t* BiometricsFingerprint::openHal() {
     int err;
-    const hw_module_t *hw_mdl = NULL;
-    ALOGE("Opening fingerprint hal library...");
+    const hw_module_t *hw_mdl = nullptr;
+    ALOGD("Opening fingerprint hal library...");
     if (0 != (err = hw_get_module(FINGERPRINT_HARDWARE_MODULE_ID, &hw_mdl))) {
         ALOGE("Can't open fingerprint HW Module, error: %d", err);
         return nullptr;
     }
 
-    if (hw_mdl == NULL) {
+    if (hw_mdl == nullptr) {
         ALOGE("No valid fingerprint module");
         return nullptr;
     }
 
     fingerprint_module_t const *module =
         reinterpret_cast<const fingerprint_module_t*>(hw_mdl);
-    if (module->common.methods->open == NULL) {
+    if (module->common.methods->open == nullptr) {
         ALOGE("No valid open method");
         return nullptr;
     }
 
-    hw_device_t *device = NULL;
+    hw_device_t *device = nullptr;
 
-    if (0 != (err = module->common.methods->open(hw_mdl, NULL, &device))) {
+    if (0 != (err = module->common.methods->open(hw_mdl, nullptr, &device))) {
         ALOGE("Can't open fingerprint methods, error: %d", err);
         return nullptr;
     }
 
     if (kVersion != device->version) {
+        // enforce version on new devices because of HIDL@2.1 translation layer
         ALOGE("Wrong fp version. Expected %d, got %d", kVersion, device->version);
-        return 0; // enforce this on new devices because of HIDL translation layer
+        return nullptr;
     }
 
     fingerprint_device_t* fp_device =
@@ -240,23 +249,67 @@
         return nullptr;
     }
 
-    return new BiometricsFingerprint(fp_device);
+    return fp_device;
 }
 
-void BiometricsFingerprint::notifyKeystore(const uint8_t *auth_token, const size_t auth_token_length) {
-    if (auth_token != nullptr && auth_token_length > 0) {
-        // TODO: cache service?
-        sp<IServiceManager> sm = android::defaultServiceManager();
-        sp<::android::IBinder> binder = sm->getService(String16("android.security.keystore"));
-        sp<IKeystoreService> service = interface_cast<IKeystoreService>(binder);
-        if (service != nullptr) {
-            auto ret = service->addAuthToken(auth_token, auth_token_length);
-            if (!ret.isOk()) {
-                ALOGE("Failure sending auth token to KeyStore: %" PRId32, int32_t(ret));
+void BiometricsFingerprint::notify(const fingerprint_msg_t *msg) {
+    BiometricsFingerprint* thisPtr = static_cast<BiometricsFingerprint*>(
+            BiometricsFingerprint::getInstance());
+    if (thisPtr == nullptr || thisPtr->mClientCallback == nullptr) {
+        ALOGE("Receiving callbacks before the client callback is registered.");
+        return;
+    }
+    const uint64_t devId = reinterpret_cast<uint64_t>(thisPtr->mDevice);
+    switch (msg->type) {
+        case FINGERPRINT_ERROR: {
+                int32_t vendorCode = 0;
+                FingerprintError result = VendorErrorFilter(msg->data.error, &vendorCode);
+                thisPtr->mClientCallback->onError(devId, result, vendorCode);
             }
-        } else {
-            ALOGE("Unable to communicate with KeyStore");
-        }
+            break;
+        case FINGERPRINT_ACQUIRED: {
+                int32_t vendorCode = 0;
+                FingerprintAcquiredInfo result =
+                    VendorAcquiredFilter(msg->data.acquired.acquired_info, &vendorCode);
+                thisPtr->mClientCallback->onAcquired(devId, result, vendorCode);
+            }
+            break;
+        case FINGERPRINT_TEMPLATE_ENROLLING:
+            thisPtr->mClientCallback->onEnrollResult(devId,
+                msg->data.enroll.finger.fid,
+                msg->data.enroll.finger.gid,
+                msg->data.enroll.samples_remaining);
+            break;
+        case FINGERPRINT_TEMPLATE_REMOVED:
+            thisPtr->mClientCallback->onRemoved(devId,
+                msg->data.removed.finger.fid,
+                msg->data.removed.finger.gid,
+                msg->data.removed.remaining_templates);
+            break;
+        case FINGERPRINT_AUTHENTICATED:
+            if (msg->data.authenticated.finger.fid != 0) {
+                const uint8_t* hat =
+                    reinterpret_cast<const uint8_t *>(&msg->data.authenticated.hat);
+                const hidl_vec<uint8_t> token(
+                    std::vector<uint8_t>(hat, hat + sizeof(msg->data.authenticated.hat)));
+                thisPtr->mClientCallback->onAuthenticated(devId,
+                    msg->data.authenticated.finger.fid,
+                    msg->data.authenticated.finger.gid,
+                    token);
+            } else {
+                // Not a recognized fingerprint
+                thisPtr->mClientCallback->onAuthenticated(devId,
+                    msg->data.authenticated.finger.fid,
+                    msg->data.authenticated.finger.gid,
+                    hidl_vec<uint8_t>());
+            }
+            break;
+        case FINGERPRINT_TEMPLATE_ENUMERATING:
+            thisPtr->mClientCallback->onEnumerate(devId,
+                msg->data.enumerated.finger.fid,
+                msg->data.enumerated.finger.gid,
+                msg->data.enumerated.remaining_templates);
+            break;
     }
 }
 
diff --git a/biometrics/fingerprint/2.1/default/BiometricsFingerprint.h b/biometrics/fingerprint/2.1/default/BiometricsFingerprint.h
index 1f44a1c..652a3e0 100644
--- a/biometrics/fingerprint/2.1/default/BiometricsFingerprint.h
+++ b/biometrics/fingerprint/2.1/default/BiometricsFingerprint.h
@@ -43,7 +43,7 @@
 
 struct BiometricsFingerprint : public IBiometricsFingerprint {
 public:
-    BiometricsFingerprint(fingerprint_device_t *device);
+    BiometricsFingerprint();
     ~BiometricsFingerprint();
 
     // Method to wrap legacy HAL with BiometricsFingerprint class
@@ -60,68 +60,17 @@
     Return<RequestStatus> remove(uint32_t gid, uint32_t fid) override;
     Return<RequestStatus> setActiveGroup(uint32_t gid, const hidl_string& storePath) override;
     Return<RequestStatus> authenticate(uint64_t operationId, uint32_t gid) override;
-    static void notify(const fingerprint_msg_t *msg) {
-        if (mClientCallback == nullptr) {
-            ALOGE("Receiving callbacks before the client callback is registered.");
-            return;
-        }
-        const uint64_t devId = reinterpret_cast<uint64_t>(sDevice);
-        switch (msg->type) {
-            case FINGERPRINT_ERROR: {
-                int32_t vendorCode = 0;
-                FingerprintError result =
-                    VendorErrorFilter(msg->data.error, &vendorCode);
-                mClientCallback->onError(devId, result, vendorCode);
-                }
-                break;
-            case FINGERPRINT_ACQUIRED: {
-                int32_t vendorCode = 0;
-                FingerprintAcquiredInfo result =
-                    VendorAcquiredFilter(msg->data.acquired.acquired_info,
-                                         &vendorCode);
-                mClientCallback->onAcquired(devId, result, vendorCode);
-                }
-                break;
-            case FINGERPRINT_TEMPLATE_ENROLLING:
-                mClientCallback->onEnrollResult(devId,
-                    msg->data.enroll.finger.fid,
-                    msg->data.enroll.finger.gid,
-                    msg->data.enroll.samples_remaining);
-                break;
-            case FINGERPRINT_TEMPLATE_REMOVED:
-                mClientCallback->onRemoved(devId,
-                    msg->data.removed.finger.fid,
-                    msg->data.removed.finger.gid,
-                    msg->data.removed.remaining_templates);
-                break;
-            case FINGERPRINT_AUTHENTICATED:
-                if (msg->data.authenticated.finger.fid != 0) {
-                    const uint8_t* hat =
-                            reinterpret_cast<const uint8_t *>(&msg->data.authenticated.hat);
-                    notifyKeystore(hat, sizeof(msg->data.authenticated.hat));
-                }
-                mClientCallback->onAuthenticated(devId,
-                    msg->data.authenticated.finger.fid,
-                    msg->data.authenticated.finger.gid);
-                break;
-            case FINGERPRINT_TEMPLATE_ENUMERATING:
-                mClientCallback->onEnumerate(devId,
-                    msg->data.enumerated.finger.fid,
-                    msg->data.enumerated.finger.gid,
-                    msg->data.enumerated.remaining_templates);
-                break;
-        }
-    }
+
 private:
-    Return<RequestStatus> ErrorFilter(int32_t error);
-    static void notifyKeystore(const uint8_t *auth_token, const size_t auth_token_length);
-    static FingerprintError VendorErrorFilter(int32_t error,
-            int32_t* vendorCode);
-    static FingerprintAcquiredInfo VendorAcquiredFilter(int32_t error,
-            int32_t* vendorCode);
-    static sp<IBiometricsFingerprintClientCallback> mClientCallback;
+    static fingerprint_device_t* openHal();
+    static void notify(const fingerprint_msg_t *msg); /* Static callback for legacy HAL implementation */
+    static Return<RequestStatus> ErrorFilter(int32_t error);
+    static FingerprintError VendorErrorFilter(int32_t error, int32_t* vendorCode);
+    static FingerprintAcquiredInfo VendorAcquiredFilter(int32_t error, int32_t* vendorCode);
+    static BiometricsFingerprint* sInstance;
+
+    sp<IBiometricsFingerprintClientCallback> mClientCallback;
     fingerprint_device_t *mDevice;
-    static fingerprint_device_t *sDevice; // TODO: allow multiple drivers
 };
 
 }  // namespace implementation
diff --git a/camera/provider/2.4/vts/functional/camera_hidl_hal_test.cpp b/camera/provider/2.4/vts/functional/camera_hidl_hal_test.cpp
index 0eb291c..0186371 100644
--- a/camera/provider/2.4/vts/functional/camera_hidl_hal_test.cpp
+++ b/camera/provider/2.4/vts/functional/camera_hidl_hal_test.cpp
@@ -95,7 +95,7 @@
 
 void CameraHidlEnvironment::SetUp() {
     // TODO: test the binderized mode
-    mProvider = ICameraProvider::getService(CAMERA_PASSTHROUGH_SERVICE_NAME, true);
+    mProvider = ICameraProvider::getService(CAMERA_PASSTHROUGH_SERVICE_NAME);
     // TODO: handle the device doesn't have any camera case
     ALOGI_IF(mProvider, "provider is not nullptr, %p", mProvider.get());
     ASSERT_NE(mProvider, nullptr);
diff --git a/contexthub/1.0/vts/Android.mk b/contexthub/1.0/vts/Android.mk
new file mode 100644
index 0000000..266884b
--- /dev/null
+++ b/contexthub/1.0/vts/Android.mk
@@ -0,0 +1,21 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+contexthub-vts-path := $(LOCAL_PATH)
+
+include $(contexthub-vts-path)/functional/vts/testcases/hal/contexthub/hidl/target/Android.mk
diff --git a/contexthub/1.0/vts/Contexthub.vts b/contexthub/1.0/vts/Contexthub.vts
new file mode 100644
index 0000000..b4e42f5
--- /dev/null
+++ b/contexthub/1.0/vts/Contexthub.vts
@@ -0,0 +1,147 @@
+component_class: HAL_HIDL
+component_type_version: 1.0
+component_name: "IContexthub"
+
+package: "android.hardware.contexthub"
+
+import: "android.hardware.contexthub@1.0::IContexthubCallback"
+import: "android.hardware.contexthub@1.0::types"
+
+interface: {
+    api: {
+        name: "getHubs"
+        return_type_hidl: {
+            type: TYPE_VECTOR
+            vector_value: {
+                type: TYPE_STRUCT
+                predefined_type: "::android::hardware::contexthub::V1_0::ContextHub"
+            }
+        }
+    }
+
+    api: {
+        name: "registerCallback"
+        return_type_hidl: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::contexthub::V1_0::Result"
+        }
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "uint32_t"
+        }
+        arg: {
+            type: TYPE_HIDL_CALLBACK
+            predefined_type: "IContexthubCallback"
+            is_callback: true
+        }
+    }
+
+    api: {
+        name: "sendMessageToHub"
+        return_type_hidl: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::contexthub::V1_0::Result"
+        }
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "uint32_t"
+        }
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::contexthub::V1_0::ContextHubMsg"
+        }
+    }
+
+    api: {
+        name: "loadNanoApp"
+        return_type_hidl: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::contexthub::V1_0::Result"
+        }
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "uint32_t"
+        }
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::contexthub::V1_0::NanoAppBinary"
+        }
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "uint32_t"
+        }
+    }
+
+    api: {
+        name: "unloadNanoApp"
+        return_type_hidl: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::contexthub::V1_0::Result"
+        }
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "uint32_t"
+        }
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "uint64_t"
+        }
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "uint32_t"
+        }
+    }
+
+    api: {
+        name: "enableNanoApp"
+        return_type_hidl: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::contexthub::V1_0::Result"
+        }
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "uint32_t"
+        }
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "uint64_t"
+        }
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "uint32_t"
+        }
+    }
+
+    api: {
+        name: "disableNanoApp"
+        return_type_hidl: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::contexthub::V1_0::Result"
+        }
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "uint32_t"
+        }
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "uint64_t"
+        }
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "uint32_t"
+        }
+    }
+
+    api: {
+        name: "queryApps"
+        return_type_hidl: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::contexthub::V1_0::Result"
+        }
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "uint32_t"
+        }
+    }
+
+}
diff --git a/contexthub/1.0/vts/ContexthubCallback.vts b/contexthub/1.0/vts/ContexthubCallback.vts
new file mode 100644
index 0000000..c3784e8
--- /dev/null
+++ b/contexthub/1.0/vts/ContexthubCallback.vts
@@ -0,0 +1,61 @@
+component_class: HAL_HIDL
+component_type_version: 1.0
+component_name: "IContexthubCallback"
+
+package: "android.hardware.contexthub"
+
+import: "android.hardware.contexthub@1.0::types"
+
+interface: {
+    api: {
+        name: "handleClientMsg"
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::contexthub::V1_0::ContextHubMsg"
+        }
+    }
+
+    api: {
+        name: "handleTxnResult"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "uint32_t"
+        }
+        arg: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::contexthub::V1_0::TransactionResult"
+        }
+    }
+
+    api: {
+        name: "handleHubEvent"
+        arg: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::contexthub::V1_0::AsyncEventType"
+        }
+    }
+
+    api: {
+        name: "handleAppAbort"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "uint64_t"
+        }
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "uint32_t"
+        }
+    }
+
+    api: {
+        name: "handleAppsInfo"
+        arg: {
+            type: TYPE_VECTOR
+            vector_value: {
+                type: TYPE_STRUCT
+                predefined_type: "::android::hardware::contexthub::V1_0::HubAppInfo"
+            }
+        }
+    }
+
+}
diff --git a/contexthub/1.0/vts/functional/Android.bp b/contexthub/1.0/vts/functional/Android.bp
new file mode 100644
index 0000000..e78898e
--- /dev/null
+++ b/contexthub/1.0/vts/functional/Android.bp
@@ -0,0 +1,38 @@
+//
+// 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.
+//
+
+cc_test {
+    name: "contexthub_hidl_hal_test",
+    gtest: true,
+    srcs: ["contexthub_hidl_hal_test.cpp"],
+    shared_libs: [
+        "liblog",
+        "libhidlbase",
+        "libhidltransport",
+        "libutils",
+        "android.hardware.contexthub@1.0",
+    ],
+    static_libs: ["libgtest"],
+    cflags: [
+        "--coverage",
+        "-O0",
+        "-g",
+    ],
+    ldflags: [
+        "--coverage",
+    ],
+}
+
diff --git a/contexthub/1.0/vts/functional/contexthub_hidl_hal_test.cpp b/contexthub/1.0/vts/functional/contexthub_hidl_hal_test.cpp
new file mode 100644
index 0000000..e4dea4f
--- /dev/null
+++ b/contexthub/1.0/vts/functional/contexthub_hidl_hal_test.cpp
@@ -0,0 +1,388 @@
+/*
+ * 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 "contexthub_hidl_hal_test"
+
+#include <android-base/logging.h>
+#include <android/hardware/contexthub/1.0/IContexthub.h>
+#include <android/hardware/contexthub/1.0/IContexthubCallback.h>
+#include <android/hardware/contexthub/1.0/types.h>
+#include <android/log.h>
+#include <gtest/gtest.h>
+
+#include <cinttypes>
+#include <future>
+#include <utility>
+
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::contexthub::V1_0::AsyncEventType;
+using ::android::hardware::contexthub::V1_0::ContextHub;
+using ::android::hardware::contexthub::V1_0::ContextHubMsg;
+using ::android::hardware::contexthub::V1_0::HubAppInfo;
+using ::android::hardware::contexthub::V1_0::IContexthub;
+using ::android::hardware::contexthub::V1_0::IContexthubCallback;
+using ::android::hardware::contexthub::V1_0::NanoAppBinary;
+using ::android::hardware::contexthub::V1_0::Result;
+using ::android::hardware::contexthub::V1_0::TransactionResult;
+using ::android::sp;
+
+#define CONTEXTHUB_SERVICE_NAME "contexthub"
+
+#define ASSERT_OK(result) ASSERT_EQ(result, Result::OK)
+#define EXPECT_OK(result) EXPECT_EQ(result, Result::OK)
+
+namespace {
+
+// App ID with vendor "GoogT" (Google Testing), app identifier 0x555555. This
+// app ID is reserved and must never appear in the list of loaded apps.
+constexpr uint64_t kNonExistentAppId = 0x476f6f6754555555;
+
+// Helper that does explicit conversion of an enum class to its underlying/base
+// type. Useful for stream output of enum values.
+template<typename EnumType>
+constexpr typename std::underlying_type<EnumType>::type asBaseType(
+    EnumType value) {
+  return static_cast<typename std::underlying_type<EnumType>::type>(value);
+}
+
+// Synchronously queries IContexthub::getHubs() and returns the result
+hidl_vec<ContextHub> getHubsSync(sp<IContexthub> hubApi) {
+  hidl_vec<ContextHub> hubList;
+  std::promise<void> barrier;
+
+  hubApi->getHubs([&hubList, &barrier](const hidl_vec<ContextHub>& hubs) {
+    hubList = hubs;
+    barrier.set_value();
+  });
+  barrier.get_future().wait_for(std::chrono::seconds(1));
+
+  return hubList;
+}
+
+// Gets a list of valid hub IDs in the system
+std::vector<uint32_t> getHubIds() {
+  static std::vector<uint32_t> hubIds;
+
+  if (hubIds.size() == 0) {
+    sp<IContexthub> hubApi = IContexthub::getService(CONTEXTHUB_SERVICE_NAME);
+
+    if (hubApi != nullptr) {
+      for (ContextHub hub : getHubsSync(hubApi)) {
+        hubIds.push_back(hub.hubId);
+      }
+    }
+  }
+
+  ALOGD("Running tests against all %zu reported hubs", hubIds.size());
+  return hubIds;
+}
+
+// Base test fixture that initializes the HAL and makes the context hub API
+// handle available
+class ContexthubHidlTestBase : public ::testing::Test {
+ public:
+  virtual void SetUp() override {
+    hubApi = IContexthub::getService(CONTEXTHUB_SERVICE_NAME);
+    ASSERT_NE(hubApi, nullptr);
+
+    // getHubs() must be called at least once for proper initialization of the
+    // HAL implementation
+    getHubsSync(hubApi);
+  }
+
+  virtual void TearDown() override {}
+
+  sp<IContexthub> hubApi;
+};
+
+// Test fixture parameterized by hub ID
+class ContexthubHidlTest : public ContexthubHidlTestBase,
+                           public ::testing::WithParamInterface<uint32_t> {
+ public:
+  uint32_t getHubId() {
+    return GetParam();
+  }
+
+  Result registerCallback(sp<IContexthubCallback> cb) {
+    Result result = hubApi->registerCallback(getHubId(), cb);
+    ALOGD("Registered callback, result %" PRIu32, result);
+    return result;
+  }
+};
+
+// Base callback implementation that just logs all callbacks by default
+class ContexthubCallbackBase : public IContexthubCallback {
+ public:
+  virtual Return<void> handleClientMsg(const ContextHubMsg& /*msg*/) override {
+    ALOGD("Got client message callback");
+    return Void();
+  }
+
+  virtual Return<void> handleTxnResult(
+      uint32_t txnId, TransactionResult result) override {
+    ALOGD("Got transaction result callback for txnId %" PRIu32 " with result %"
+          PRId32, txnId, result);
+    return Void();
+  }
+
+  virtual Return<void> handleHubEvent(AsyncEventType evt) override {
+    ALOGD("Got hub event callback for event type %" PRIu32, evt);
+    return Void();
+  }
+
+  virtual Return<void> handleAppAbort(uint64_t appId, uint32_t abortCode)
+      override {
+    ALOGD("Got app abort notification for appId 0x%" PRIx64 " with abort code "
+          "0x%" PRIx32, appId, abortCode);
+    return Void();
+  }
+
+  virtual Return<void> handleAppsInfo(const hidl_vec<HubAppInfo>& /*appInfo*/)
+      override {
+    ALOGD("Got app info callback");
+    return Void();
+  }
+};
+
+// Wait for a callback to occur (signaled by the given future) up to the
+// provided timeout. If the future is invalid or the callback does not come
+// within the given time, returns false.
+template<class ReturnType>
+bool waitForCallback(
+    std::future<ReturnType> future,
+    ReturnType *result,
+    std::chrono::milliseconds timeout = std::chrono::seconds(5)) {
+  auto expiration = std::chrono::system_clock::now() + timeout;
+
+  EXPECT_NE(result, nullptr);
+  EXPECT_TRUE(future.valid());
+  if (result != nullptr && future.valid()) {
+    std::future_status status = future.wait_until(expiration);
+    EXPECT_NE(status, std::future_status::timeout)
+        << "Timed out waiting for callback";
+
+    if (status == std::future_status::ready) {
+      *result = future.get();
+      return true;
+    }
+  }
+
+  return false;
+}
+
+// Ensures that the metadata reported in getHubs() is sane
+TEST_F(ContexthubHidlTestBase, TestGetHubs) {
+  hidl_vec<ContextHub> hubs = getHubsSync(hubApi);
+  ALOGD("System reports %zu hubs", hubs.size());
+
+  for (ContextHub hub : hubs) {
+    ALOGD("Checking hub ID %" PRIu32, hub.hubId);
+
+    EXPECT_FALSE(hub.name.empty());
+    EXPECT_FALSE(hub.vendor.empty());
+    EXPECT_FALSE(hub.toolchain.empty());
+    EXPECT_GT(hub.peakMips, 0);
+    EXPECT_GE(hub.stoppedPowerDrawMw, 0);
+    EXPECT_GE(hub.sleepPowerDrawMw, 0);
+    EXPECT_GT(hub.peakPowerDrawMw, 0);
+
+    // Minimum 128 byte MTU as required by CHRE API v1.0
+    EXPECT_GE(hub.maxSupportedMsgLen, UINT32_C(128));
+  }
+}
+
+TEST_P(ContexthubHidlTest, TestRegisterCallback) {
+  ALOGD("TestRegisterCallback called, hubId %" PRIu32, getHubId());
+  ASSERT_OK(registerCallback(new ContexthubCallbackBase()));
+}
+
+TEST_P(ContexthubHidlTest, TestRegisterNullCallback) {
+  ALOGD("TestRegisterNullCallback called, hubId %" PRIu32, getHubId());
+  ASSERT_OK(registerCallback(nullptr));
+}
+
+// Helper callback that puts the async appInfo callback data into a promise
+class QueryAppsCallback : public ContexthubCallbackBase {
+ public:
+  virtual Return<void> handleAppsInfo(const hidl_vec<HubAppInfo>& appInfo)
+      override {
+    ALOGD("Got app info callback with %zu apps", appInfo.size());
+    promise.set_value(appInfo);
+    return Void();
+  }
+
+  std::promise<hidl_vec<HubAppInfo>> promise;
+};
+
+// Calls queryApps() and checks the returned metadata
+TEST_P(ContexthubHidlTest, TestQueryApps) {
+  ALOGD("TestQueryApps called, hubId %u", getHubId());
+  sp<QueryAppsCallback> cb = new QueryAppsCallback();
+  ASSERT_OK(registerCallback(cb));
+
+  Result result = hubApi->queryApps(getHubId());
+  ASSERT_OK(result);
+
+  ALOGD("Waiting for app info callback");
+  hidl_vec<HubAppInfo> appList;
+  ASSERT_TRUE(waitForCallback(cb->promise.get_future(), &appList));
+  for (const HubAppInfo &appInfo : appList) {
+    EXPECT_NE(appInfo.appId, UINT64_C(0));
+    EXPECT_NE(appInfo.appId, kNonExistentAppId);
+  }
+}
+
+// Helper callback that puts the TransactionResult for the expectedTxnId into a
+// promise
+class TxnResultCallback : public ContexthubCallbackBase {
+ public:
+  virtual Return<void> handleTxnResult(
+      uint32_t txnId, TransactionResult result) override {
+    ALOGD("Got transaction result callback for txnId %" PRIu32 " (expecting %"
+          PRIu32 ") with result %" PRId32, txnId, expectedTxnId, result);
+    if (txnId == expectedTxnId) {
+      promise.set_value(result);
+    }
+    return Void();
+  }
+
+  uint32_t expectedTxnId = 0;
+  std::promise<TransactionResult> promise;
+};
+
+// Parameterized fixture that sets the callback to TxnResultCallback
+class ContexthubTxnTest : public ContexthubHidlTest {
+ public:
+  virtual void SetUp() override {
+    ContexthubHidlTest::SetUp();
+    ASSERT_OK(registerCallback(cb));
+  }
+
+  sp<TxnResultCallback> cb = new TxnResultCallback();
+};
+
+
+// Checks cases where the hub implementation is expected to return an error, but
+// that error can be returned either synchronously or in the asynchronous
+// transaction callback. Returns an AssertionResult that can be used in
+// ASSERT/EXPECT_TRUE. Allows checking the sync result against 1 additional
+// allowed error code apart from OK and TRANSACTION_FAILED, which are always
+// allowed.
+::testing::AssertionResult checkFailureSyncOrAsync(
+    Result result, Result allowedSyncResult,
+    std::future<TransactionResult>&& future) {
+  if (result == Result::OK) {
+    // No error reported synchronously - this is OK, but then we should get an
+    // async callback with a failure status
+    TransactionResult asyncResult;
+    if (!waitForCallback(std::forward<std::future<TransactionResult>>(future),
+                         &asyncResult)) {
+      return ::testing::AssertionFailure()
+          << "Got successful sync result, then failed to receive async cb";
+    } else if (asyncResult == TransactionResult::SUCCESS) {
+      return ::testing::AssertionFailure()
+          << "Got successful sync result, then unexpected successful async "
+             "result";
+    }
+  } else if (result != allowedSyncResult &&
+             result != Result::TRANSACTION_FAILED) {
+    return ::testing::AssertionFailure() << "Got sync result "
+        << asBaseType(result) << ", expected TRANSACTION_FAILED or "
+        << asBaseType(allowedSyncResult);
+  }
+
+  return ::testing::AssertionSuccess();
+}
+
+TEST_P(ContexthubTxnTest, TestSendMessageToNonExistentNanoApp) {
+  ContextHubMsg msg;
+  msg.appName = kNonExistentAppId;
+  msg.msgType = 1;
+  msg.msg.resize(4);
+  std::fill(msg.msg.begin(), msg.msg.end(), 0);
+
+  ALOGD("Sending message to non-existent nanoapp");
+  Result result = hubApi->sendMessageToHub(getHubId(), msg);
+  if (result != Result::OK &&
+      result != Result::BAD_PARAMS &&
+      result != Result::TRANSACTION_FAILED) {
+    FAIL() << "Got result " << asBaseType(result) << ", expected OK, BAD_PARAMS"
+        << ", or TRANSACTION_FAILED";
+  }
+}
+
+TEST_P(ContexthubTxnTest, TestLoadEmptyNanoApp) {
+  cb->expectedTxnId = 0123;
+  NanoAppBinary emptyApp;
+
+  emptyApp.appId = kNonExistentAppId;
+  emptyApp.appVersion = 1;
+  emptyApp.flags = 0;
+  emptyApp.targetChreApiMajorVersion = 1;
+  emptyApp.targetChreApiMinorVersion = 0;
+
+  ALOGD("Loading empty nanoapp");
+  Result result = hubApi->loadNanoApp(getHubId(), emptyApp, cb->expectedTxnId);
+  EXPECT_TRUE(checkFailureSyncOrAsync(result, Result::BAD_PARAMS,
+                                      cb->promise.get_future()));
+}
+
+TEST_P(ContexthubTxnTest, TestUnloadNonexistentNanoApp) {
+  cb->expectedTxnId = 1234;
+
+  ALOGD("Unloading nonexistent nanoapp");
+  Result result = hubApi->unloadNanoApp(getHubId(), kNonExistentAppId,
+                                        cb->expectedTxnId);
+  EXPECT_TRUE(checkFailureSyncOrAsync(result, Result::BAD_PARAMS,
+                                      cb->promise.get_future()));
+}
+
+TEST_P(ContexthubTxnTest, TestEnableNonexistentNanoApp) {
+  cb->expectedTxnId = 2345;
+
+  ALOGD("Enabling nonexistent nanoapp");
+  Result result = hubApi->enableNanoApp(getHubId(), kNonExistentAppId,
+                                        cb->expectedTxnId);
+  EXPECT_TRUE(checkFailureSyncOrAsync(result, Result::BAD_PARAMS,
+                                      cb->promise.get_future()));
+}
+
+TEST_P(ContexthubTxnTest, TestDisableNonexistentNanoApp) {
+  cb->expectedTxnId = 3456;
+
+  ALOGD("Disabling nonexistent nanoapp");
+  Result result = hubApi->disableNanoApp(getHubId(), kNonExistentAppId,
+                                         cb->expectedTxnId);
+  EXPECT_TRUE(checkFailureSyncOrAsync(result, Result::BAD_PARAMS,
+                                      cb->promise.get_future()));
+}
+
+// Parameterize all SingleContexthubTest tests against each valid hub ID
+INSTANTIATE_TEST_CASE_P(HubIdSpecificTests, ContexthubHidlTest,
+                        ::testing::ValuesIn(getHubIds()));
+INSTANTIATE_TEST_CASE_P(HubIdSpecificTests, ContexthubTxnTest,
+                        ::testing::ValuesIn(getHubIds()));
+
+} // anonymous namespace
+
+int main(int argc, char **argv) {
+  ::testing::InitGoogleTest(&argc, argv);
+  return RUN_ALL_TESTS();
+}
+
diff --git a/contexthub/1.0/vts/functional/vts/testcases/hal/contexthub/hidl/target/Android.mk b/contexthub/1.0/vts/functional/vts/testcases/hal/contexthub/hidl/target/Android.mk
new file mode 100644
index 0000000..a46a0e6
--- /dev/null
+++ b/contexthub/1.0/vts/functional/vts/testcases/hal/contexthub/hidl/target/Android.mk
@@ -0,0 +1,23 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := ContexthubHidlTargetTest
+VTS_CONFIG_SRC_DIR := testcases/hal/contexthub/hidl/target
+include test/vts/tools/build/Android.host_config.mk
diff --git a/contexthub/1.0/vts/functional/vts/testcases/hal/contexthub/hidl/target/AndroidTest.xml b/contexthub/1.0/vts/functional/vts/testcases/hal/contexthub/hidl/target/AndroidTest.xml
new file mode 100644
index 0000000..a314d1b
--- /dev/null
+++ b/contexthub/1.0/vts/functional/vts/testcases/hal/contexthub/hidl/target/AndroidTest.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<configuration description="Config for VTS Context Hub HIDL HAL's target-side test cases">
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.VtsFilePusher">
+        <option name="push-group" value="HidlHalTest.push" />
+    </target_preparer>
+    <target_preparer class="com.android.tradefed.targetprep.VtsPythonVirtualenvPreparer" />
+    <test class="com.android.tradefed.testtype.VtsMultiDeviceTest">
+        <option name="test-module-name" value="ContexthubHidlTargetTest" />
+        <option name="binary-test-sources" value="
+            _32bit::DATA/nativetest/contexthub_hidl_hal_test/contexthub_hidl_hal_test,
+            _64bit::DATA/nativetest64/contexthub_hidl_hal_test/contexthub_hidl_hal_test,
+            "/>
+        <option name="binary-test-type" value="gtest" />
+        <option name="binary-test-disable-framework" value="true" />
+        <option name="test-timeout" value="10m" />
+    </test>
+</configuration>
+
diff --git a/contexthub/1.0/vts/types.vts b/contexthub/1.0/vts/types.vts
new file mode 100644
index 0000000..12576b1
--- /dev/null
+++ b/contexthub/1.0/vts/types.vts
@@ -0,0 +1,475 @@
+component_class: HAL_HIDL
+component_type_version: 1.0
+component_name: "types"
+
+package: "android.hardware.contexthub"
+
+
+attribute: {
+    name: "::android::hardware::contexthub::V1_0::Result"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "uint32_t"
+
+        enumerator: "OK"
+        scalar_value: {
+            uint32_t: 0
+        }
+        enumerator: "UNKNOWN_FAILURE"
+        scalar_value: {
+            uint32_t: 1
+        }
+        enumerator: "BAD_PARAMS"
+        scalar_value: {
+            uint32_t: 2
+        }
+        enumerator: "NOT_INIT"
+        scalar_value: {
+            uint32_t: 3
+        }
+        enumerator: "TRANSACTION_FAILED"
+        scalar_value: {
+            uint32_t: 4
+        }
+        enumerator: "TRANSACTION_PENDING"
+        scalar_value: {
+            uint32_t: 5
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::contexthub::V1_0::NanoAppFlags"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "uint32_t"
+
+        enumerator: "SIGNED"
+        scalar_value: {
+            uint32_t: 1
+        }
+        enumerator: "ENCRYPTED"
+        scalar_value: {
+            uint32_t: 2
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::contexthub::V1_0::NanoAppBinary"
+    type: TYPE_STRUCT
+    struct_value: {
+        name: "appId"
+        type: TYPE_SCALAR
+        scalar_type: "uint64_t"
+    }
+    struct_value: {
+        name: "appVersion"
+        type: TYPE_SCALAR
+        scalar_type: "uint32_t"
+    }
+    struct_value: {
+        name: "flags"
+        type: TYPE_MASK
+        predefined_type: "::android::hardware::contexthub::V1_0::NanoAppFlags"
+    }
+    struct_value: {
+        name: "targetChreApiMajorVersion"
+        type: TYPE_SCALAR
+        scalar_type: "uint8_t"
+    }
+    struct_value: {
+        name: "targetChreApiMinorVersion"
+        type: TYPE_SCALAR
+        scalar_type: "uint8_t"
+    }
+    struct_value: {
+        name: "customBinary"
+        type: TYPE_VECTOR
+        vector_value: {
+            type: TYPE_SCALAR
+            scalar_type: "uint8_t"
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::contexthub::V1_0::SensorType"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "uint32_t"
+
+        enumerator: "RESERVED"
+        scalar_value: {
+            uint32_t: 0
+        }
+        enumerator: "ACCELEROMETER"
+        scalar_value: {
+            uint32_t: 1
+        }
+        enumerator: "GYROSCOPE"
+        scalar_value: {
+            uint32_t: 2
+        }
+        enumerator: "MAGNETOMETER"
+        scalar_value: {
+            uint32_t: 3
+        }
+        enumerator: "BAROMETER"
+        scalar_value: {
+            uint32_t: 4
+        }
+        enumerator: "PROXIMITY_SENSOR"
+        scalar_value: {
+            uint32_t: 5
+        }
+        enumerator: "AMBIENT_LIGHT_SENSOR"
+        scalar_value: {
+            uint32_t: 6
+        }
+        enumerator: "STATIONARY_DETECT"
+        scalar_value: {
+            uint32_t: 7
+        }
+        enumerator: "INSTANT_MOTION_DETECT"
+        scalar_value: {
+            uint32_t: 8
+        }
+        enumerator: "GPS"
+        scalar_value: {
+            uint32_t: 256
+        }
+        enumerator: "WIFI"
+        scalar_value: {
+            uint32_t: 512
+        }
+        enumerator: "AUDIO"
+        scalar_value: {
+            uint32_t: 768
+        }
+        enumerator: "CAMERA"
+        scalar_value: {
+            uint32_t: 1024
+        }
+        enumerator: "BLE"
+        scalar_value: {
+            uint32_t: 1280
+        }
+        enumerator: "WWAN"
+        scalar_value: {
+            uint32_t: 1536
+        }
+        enumerator: "PRIVATE_SENSOR_BASE"
+        scalar_value: {
+            uint32_t: 65536
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::contexthub::V1_0::PhysicalSensor"
+    type: TYPE_STRUCT
+    struct_value: {
+        name: "sensorType"
+        type: TYPE_ENUM
+        predefined_type: "::android::hardware::contexthub::V1_0::SensorType"
+    }
+    struct_value: {
+        name: "type"
+        type: TYPE_STRING
+    }
+    struct_value: {
+        name: "name"
+        type: TYPE_STRING
+    }
+    struct_value: {
+        name: "vendor"
+        type: TYPE_STRING
+    }
+    struct_value: {
+        name: "version"
+        type: TYPE_SCALAR
+        scalar_type: "uint32_t"
+    }
+    struct_value: {
+        name: "fifoReservedCount"
+        type: TYPE_SCALAR
+        scalar_type: "uint32_t"
+    }
+    struct_value: {
+        name: "fifoMaxCount"
+        type: TYPE_SCALAR
+        scalar_type: "uint32_t"
+    }
+    struct_value: {
+        name: "minDelayMs"
+        type: TYPE_SCALAR
+        scalar_type: "uint64_t"
+    }
+    struct_value: {
+        name: "maxDelayMs"
+        type: TYPE_SCALAR
+        scalar_type: "uint64_t"
+    }
+    struct_value: {
+        name: "peakPowerMw"
+        type: TYPE_SCALAR
+        scalar_type: "float_t"
+    }
+}
+
+attribute: {
+    name: "::android::hardware::contexthub::V1_0::ContextHub"
+    type: TYPE_STRUCT
+    struct_value: {
+        name: "name"
+        type: TYPE_STRING
+    }
+    struct_value: {
+        name: "vendor"
+        type: TYPE_STRING
+    }
+    struct_value: {
+        name: "toolchain"
+        type: TYPE_STRING
+    }
+    struct_value: {
+        name: "platformVersion"
+        type: TYPE_SCALAR
+        scalar_type: "uint32_t"
+    }
+    struct_value: {
+        name: "toolchainVersion"
+        type: TYPE_SCALAR
+        scalar_type: "uint32_t"
+    }
+    struct_value: {
+        name: "hubId"
+        type: TYPE_SCALAR
+        scalar_type: "uint32_t"
+    }
+    struct_value: {
+        name: "peakMips"
+        type: TYPE_SCALAR
+        scalar_type: "float_t"
+    }
+    struct_value: {
+        name: "stoppedPowerDrawMw"
+        type: TYPE_SCALAR
+        scalar_type: "float_t"
+    }
+    struct_value: {
+        name: "sleepPowerDrawMw"
+        type: TYPE_SCALAR
+        scalar_type: "float_t"
+    }
+    struct_value: {
+        name: "peakPowerDrawMw"
+        type: TYPE_SCALAR
+        scalar_type: "float_t"
+    }
+    struct_value: {
+        name: "connectedSensors"
+        type: TYPE_VECTOR
+        vector_value: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::contexthub::V1_0::PhysicalSensor"
+        }
+    }
+    struct_value: {
+        name: "maxSupportedMsgLen"
+        type: TYPE_SCALAR
+        scalar_type: "uint32_t"
+    }
+    struct_value: {
+        name: "chrePlatformId"
+        type: TYPE_SCALAR
+        scalar_type: "uint64_t"
+    }
+    struct_value: {
+        name: "chreApiMajorVersion"
+        type: TYPE_SCALAR
+        scalar_type: "uint8_t"
+    }
+    struct_value: {
+        name: "chreApiMinorVersion"
+        type: TYPE_SCALAR
+        scalar_type: "uint8_t"
+    }
+    struct_value: {
+        name: "chrePatchVersion"
+        type: TYPE_SCALAR
+        scalar_type: "uint16_t"
+    }
+}
+
+attribute: {
+    name: "::android::hardware::contexthub::V1_0::HostEndPoint"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "uint16_t"
+
+        enumerator: "BROADCAST"
+        scalar_value: {
+            uint16_t: 65535
+        }
+        enumerator: "UNSPECIFIED"
+        scalar_value: {
+            uint16_t: 65534
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::contexthub::V1_0::ContextHubMsg"
+    type: TYPE_STRUCT
+    struct_value: {
+        name: "appName"
+        type: TYPE_SCALAR
+        scalar_type: "uint64_t"
+    }
+    struct_value: {
+        name: "hostEndPoint"
+        type: TYPE_SCALAR
+        scalar_type: "uint16_t"
+    }
+    struct_value: {
+        name: "msgType"
+        type: TYPE_SCALAR
+        scalar_type: "uint32_t"
+    }
+    struct_value: {
+        name: "msg"
+        type: TYPE_VECTOR
+        vector_value: {
+            type: TYPE_SCALAR
+            scalar_type: "uint8_t"
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::contexthub::V1_0::HubMemoryType"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "uint32_t"
+
+        enumerator: "MAIN"
+        scalar_value: {
+            uint32_t: 0
+        }
+        enumerator: "SECONDARY"
+        scalar_value: {
+            uint32_t: 1
+        }
+        enumerator: "TCM"
+        scalar_value: {
+            uint32_t: 2
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::contexthub::V1_0::HubMemoryFlag"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "uint32_t"
+
+        enumerator: "READ"
+        scalar_value: {
+            uint32_t: 1
+        }
+        enumerator: "WRITE"
+        scalar_value: {
+            uint32_t: 2
+        }
+        enumerator: "EXEC"
+        scalar_value: {
+            uint32_t: 4
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::contexthub::V1_0::MemRange"
+    type: TYPE_STRUCT
+    struct_value: {
+        name: "totalBytes"
+        type: TYPE_SCALAR
+        scalar_type: "uint32_t"
+    }
+    struct_value: {
+        name: "freeBytes"
+        type: TYPE_SCALAR
+        scalar_type: "uint32_t"
+    }
+    struct_value: {
+        name: "type"
+        type: TYPE_ENUM
+        predefined_type: "::android::hardware::contexthub::V1_0::HubMemoryType"
+    }
+    struct_value: {
+        name: "flags"
+        type: TYPE_MASK
+        predefined_type: "::android::hardware::contexthub::V1_0::HubMemoryFlag"
+    }
+}
+
+attribute: {
+    name: "::android::hardware::contexthub::V1_0::AsyncEventType"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "uint32_t"
+
+        enumerator: "RESTARTED"
+        scalar_value: {
+            uint32_t: 1
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::contexthub::V1_0::TransactionResult"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "SUCCESS"
+        scalar_value: {
+            int32_t: 0
+        }
+        enumerator: "FAILURE"
+        scalar_value: {
+            int32_t: 1
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::contexthub::V1_0::HubAppInfo"
+    type: TYPE_STRUCT
+    struct_value: {
+        name: "appId"
+        type: TYPE_SCALAR
+        scalar_type: "uint64_t"
+    }
+    struct_value: {
+        name: "version"
+        type: TYPE_SCALAR
+        scalar_type: "uint32_t"
+    }
+    struct_value: {
+        name: "memUsage"
+        type: TYPE_VECTOR
+        vector_value: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::contexthub::V1_0::MemRange"
+        }
+    }
+    struct_value: {
+        name: "enabled"
+        type: TYPE_SCALAR
+        scalar_type: "bool_t"
+    }
+}
+
diff --git a/contexthub/Android.bp b/contexthub/Android.bp
index ba90f2c..ed19a37 100644
--- a/contexthub/Android.bp
+++ b/contexthub/Android.bp
@@ -2,4 +2,5 @@
 subdirs = [
     "1.0",
     "1.0/default",
+    "1.0/vts/functional",
 ]
diff --git a/drm/1.0/default/CryptoFactory.cpp b/drm/1.0/default/CryptoFactory.cpp
index 02084e7..e46233d 100644
--- a/drm/1.0/default/CryptoFactory.cpp
+++ b/drm/1.0/default/CryptoFactory.cpp
@@ -13,6 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+#define LOG_TAG "android.hardware.drm@1.0-impl"
 
 #include "CryptoFactory.h"
 #include "CryptoPlugin.h"
diff --git a/drm/1.0/default/CryptoPlugin.cpp b/drm/1.0/default/CryptoPlugin.cpp
index 073f030..fb61ede 100644
--- a/drm/1.0/default/CryptoPlugin.cpp
+++ b/drm/1.0/default/CryptoPlugin.cpp
@@ -13,6 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+#define LOG_TAG "android.hardware.drm@1.0-impl"
 
 #include "CryptoPlugin.h"
 #include "TypeConvert.h"
@@ -61,6 +62,11 @@
             const DestinationBuffer& destination,
             decrypt_cb _hidl_cb) {
 
+        if (mSharedBufferBase == NULL) {
+            _hidl_cb(Status::BAD_VALUE, 0, "decrypt buffer base not set");
+            return Void();
+        }
+
         android::CryptoPlugin::Mode legacyMode;
         switch(mode) {
         case Mode::UNENCRYPTED:
diff --git a/drm/1.0/default/DrmFactory.cpp b/drm/1.0/default/DrmFactory.cpp
index cba2c99..b6f642f 100644
--- a/drm/1.0/default/DrmFactory.cpp
+++ b/drm/1.0/default/DrmFactory.cpp
@@ -13,6 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+#define LOG_TAG "android.hardware.drm@1.0-impl"
 
 #include "DrmFactory.h"
 #include "DrmPlugin.h"
diff --git a/drm/1.0/default/DrmPlugin.cpp b/drm/1.0/default/DrmPlugin.cpp
index 9204fc5..1b2f90e 100644
--- a/drm/1.0/default/DrmPlugin.cpp
+++ b/drm/1.0/default/DrmPlugin.cpp
@@ -13,6 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+#define LOG_TAG "android.hardware.drm@1.0-impl"
 
 #include <utils/KeyedVector.h>
 #include <utils/String8.h>
diff --git a/drm/1.0/default/TypeConvert.cpp b/drm/1.0/default/TypeConvert.cpp
index 52cc503..ede2a38 100644
--- a/drm/1.0/default/TypeConvert.cpp
+++ b/drm/1.0/default/TypeConvert.cpp
@@ -13,6 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+#define LOG_TAG "android.hardware.drm@1.0-impl"
 
 #include "TypeConvert.h"
 
diff --git a/drm/1.0/default/service.cpp b/drm/1.0/default/service.cpp
index fba56ec..d2507c4 100644
--- a/drm/1.0/default/service.cpp
+++ b/drm/1.0/default/service.cpp
@@ -13,7 +13,6 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
 #define LOG_TAG "android.hardware.drm@1.0-service"
 
 #include <1.0/default/CryptoFactory.h>
diff --git a/evs/1.0/IEvsCamera.hal b/evs/1.0/IEvsCamera.hal
index a2fc565..d0559d7 100644
--- a/evs/1.0/IEvsCamera.hal
+++ b/evs/1.0/IEvsCamera.hal
@@ -65,7 +65,7 @@
      * as one), and if the supply is exhausted, no further frames may be
      * delivered until a buffer is returned.
      */
-    doneWithFrame(uint32_t frameId, handle bufferHandle) generates (EvsResult result);
+    oneway doneWithFrame(BufferDesc buffer);
 
     /**
      * Stop the delivery of EVS camera frames.
diff --git a/evs/1.0/IEvsCameraStream.hal b/evs/1.0/IEvsCameraStream.hal
index ef5460f..fcd5717 100644
--- a/evs/1.0/IEvsCameraStream.hal
+++ b/evs/1.0/IEvsCameraStream.hal
@@ -32,5 +32,5 @@
      * must be delivered, signifying the end of the stream. No further frame
      * deliveries may happen thereafter.
      */
-    oneway deliverFrame(uint32_t frameId, handle bufferHandle);
+    oneway deliverFrame(BufferDesc buffer);
 };
diff --git a/evs/1.0/IEvsDisplay.hal b/evs/1.0/IEvsDisplay.hal
index a473872..8352221 100644
--- a/evs/1.0/IEvsDisplay.hal
+++ b/evs/1.0/IEvsDisplay.hal
@@ -65,7 +65,7 @@
      * must be returned via a call to returnTargetBufferForDisplay() even if the
      * display is no longer visible.
      */
-     getTargetBuffer() generates (handle bufferHandle);
+     getTargetBuffer() generates (BufferDesc buffer);
 
 
     /**
@@ -76,5 +76,5 @@
      * call. The buffer may be returned at any time and in any DisplayState, but all
      * buffers are expected to be returned before the IEvsDisplay interface is destroyed.
      */
-    returnTargetBufferForDisplay(handle bufferHandle) generates (EvsResult result);
+    returnTargetBufferForDisplay(BufferDesc buffer) generates (EvsResult result);
 };
diff --git a/evs/1.0/IEvsEnumerator.hal b/evs/1.0/IEvsEnumerator.hal
index e3a1382..3779866 100644
--- a/evs/1.0/IEvsEnumerator.hal
+++ b/evs/1.0/IEvsEnumerator.hal
@@ -67,5 +67,15 @@
      * NOTE: All buffer must have been returned to the display before making this call.
      */
     closeDisplay(IEvsDisplay display);
+
+    /**
+     * This call requests the current state of the display
+     *
+     * If there is no open display, this returns DisplayState::NOT_OPEN. otherwise, it returns
+     * the actual state of the active display.  This call is replicated on the IEvsEnumerator
+     * interface in order to allow secondary clients to monitor the state of the EVS display
+     * without acquiring exclusive ownership of the display.
+     */
+    getDisplayState() generates (DisplayState state);
 };
 
diff --git a/evs/1.0/default/Android.bp b/evs/1.0/default/Android.bp
index 3bda250..e3bff25 100644
--- a/evs/1.0/default/Android.bp
+++ b/evs/1.0/default/Android.bp
@@ -11,7 +11,6 @@
 
     shared_libs: [
         "android.hardware.evs@1.0",
-        "android.hardware.graphics.allocator@2.0",
         "libui",
         "libbase",
         "libbinder",
diff --git a/evs/1.0/default/EvsCamera.cpp b/evs/1.0/default/EvsCamera.cpp
index 6715a2e..c62f7b6 100644
--- a/evs/1.0/default/EvsCamera.cpp
+++ b/evs/1.0/default/EvsCamera.cpp
@@ -33,18 +33,22 @@
 const char EvsCamera::kCameraName_Backup[]    = "backup";
 const char EvsCamera::kCameraName_RightTurn[] = "Right Turn";
 
+// Arbitrary limit on number of graphics buffers allowed to be allocated
+// Safeguards against unreasonable resource consumption and provides a testable limit
+const unsigned MAX_BUFFERS_IN_FLIGHT = 100;
+
 
 // TODO(b/31632518):  Need to get notification when our client dies so we can close the camera.
-// As it stands, if the client dies suddently, the buffer may be stranded.
-// As possible work around would be to give the client a HIDL object to exclusively hold
-// and use it's destructor to perform some work in the server side.
+// As it stands, if the client dies suddenly, the buffer may be stranded.
 
-EvsCamera::EvsCamera(const char *id) {
+EvsCamera::EvsCamera(const char *id) :
+    mFramesAllowed(0),
+    mFramesInUse(0),
+    mStreamState(STOPPED) {
+
     ALOGD("EvsCamera instantiated");
 
     mDescription.cameraId = id;
-    mFrameBusy = false;
-    mStreamState = STOPPED;
 
     // Set up dummy data for testing
     if (mDescription.cameraId == kCameraName_Backup) {
@@ -52,16 +56,23 @@
         mDescription.vendorFlags            = 0xFFFFFFFF;   // Arbitrary value
         mDescription.defaultHorResolution   = 320;          // 1/2 NTSC/VGA
         mDescription.defaultVerResolution   = 240;          // 1/2 NTSC/VGA
-    }
-    else if (mDescription.cameraId == kCameraName_RightTurn) {
+    } else if (mDescription.cameraId == kCameraName_RightTurn) {
         // Nothing but the name and the usage hint
         mDescription.hints                  = static_cast<uint32_t>(UsageHint::USAGE_HINT_RIGHT_TURN);
-    }
-    else {
+    } else {
         // Leave empty for a minimalist camera description without even a hint
     }
+
+
+    // Set our buffer properties
+    mWidth  = (mDescription.defaultHorResolution) ? mDescription.defaultHorResolution : 640;
+    mHeight = (mDescription.defaultVerResolution) ? mDescription.defaultVerResolution : 480;
+
+    mFormat = HAL_PIXEL_FORMAT_RGBA_8888;
+    mUsage  = GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_HW_CAMERA_WRITE;
 }
 
+
 EvsCamera::~EvsCamera() {
     ALOGD("EvsCamera being destroyed");
     std::lock_guard<std::mutex> lock(mAccessLock);
@@ -70,11 +81,14 @@
     // (It really should be already)
     stopVideoStream();
 
-    // Drop the graphics buffer we've been using
-    if (mBuffer) {
-        // Drop the graphics buffer we've been using
-        GraphicBufferAllocator& alloc(GraphicBufferAllocator::get());
-        alloc.free(mBuffer);
+    // Drop all the graphics buffers we've been using
+    GraphicBufferAllocator& alloc(GraphicBufferAllocator::get());
+    for (auto&& rec : mBuffers) {
+        if (rec.inUse) {
+            ALOGE("Error - releasing buffer despite remote ownership");
+        }
+        alloc.free(rec.handle);
+        rec.handle = nullptr;
     }
 
     ALOGD("EvsCamera destroyed");
@@ -95,113 +109,109 @@
     ALOGD("setMaxFramesInFlight");
     std::lock_guard<std::mutex> lock(mAccessLock);
 
-    // TODO:  Update our stored value
-
-    // TODO:  Adjust our buffer count right now if we can.  Otherwise, it'll adjust in doneWithFrame
-
-    // For now we support only one!
-    if (bufferCount != 1) {
-        return EvsResult::BUFFER_NOT_AVAILABLE;
+    // We cannot function without at least one video buffer to send data
+    if (bufferCount < 1) {
+        ALOGE("Ignoring setMaxFramesInFlight with less than one buffer requested");
+        return EvsResult::INVALID_ARG;
     }
 
-    return EvsResult::OK;
+    // Update our internal state
+    if (setAvailableFrames_Locked(bufferCount)) {
+        return EvsResult::OK;
+    } else {
+        return EvsResult::BUFFER_NOT_AVAILABLE;
+    }
 }
 
+
 Return<EvsResult> EvsCamera::startVideoStream(const ::android::sp<IEvsCameraStream>& stream)  {
     ALOGD("startVideoStream");
     std::lock_guard<std::mutex> lock(mAccessLock);
 
-    // We only support a single stream at a time
     if (mStreamState != STOPPED) {
         ALOGE("ignoring startVideoStream call when a stream is already running.");
         return EvsResult::STREAM_ALREADY_RUNNING;
     }
 
+    // If the client never indicated otherwise, configure ourselves for a single streaming buffer
+    if (mFramesAllowed < 1) {
+        if (!setAvailableFrames_Locked(1)) {
+            ALOGE("Failed to start stream because we couldn't get a graphics buffer");
+            return EvsResult::BUFFER_NOT_AVAILABLE;
+        }
+    }
+
     // Record the user's callback for use when we have a frame ready
     mStream = stream;
 
-    // Allocate a graphics buffer into which we'll put our test images
-    if (!mBuffer) {
-        mWidth  = (mDescription.defaultHorResolution) ? mDescription.defaultHorResolution : 640;
-        mHeight = (mDescription.defaultVerResolution) ? mDescription.defaultVerResolution : 480;
-        // TODO:  What about stride?  Assume no padding for now...
-        mStride = 4* mWidth;    // Special cased to assume 4 byte pixels with no padding for now
-
-        ALOGD("Allocating buffer for camera frame");
-        GraphicBufferAllocator &alloc(GraphicBufferAllocator::get());
-        status_t result = alloc.allocate(mWidth, mHeight,
-                                         HAL_PIXEL_FORMAT_RGBA_8888, 1, GRALLOC_USAGE_HW_TEXTURE,
-                                         &mBuffer, &mStride, 0, "EvsCamera");
-        if (result != NO_ERROR) {
-            ALOGE("Error %d allocating %d x %d graphics buffer", result, mWidth, mHeight);
-            return EvsResult::BUFFER_NOT_AVAILABLE;
-        }
-        if (!mBuffer) {
-            ALOGE("We didn't get a buffer handle back from the allocator");
-            return EvsResult::BUFFER_NOT_AVAILABLE;
-        }
-    }
-
     // Start the frame generation thread
     mStreamState = RUNNING;
-    mCaptureThread = std::thread([this](){GenerateFrames();});
+    mCaptureThread = std::thread([this](){ generateFrames(); });
 
     return EvsResult::OK;
 }
 
-Return<EvsResult> EvsCamera::doneWithFrame(uint32_t /* frameId */, const hidl_handle& bufferHandle)  {
+
+Return<void> EvsCamera::doneWithFrame(const BufferDesc& buffer)  {
     ALOGD("doneWithFrame");
-    std::lock_guard<std::mutex> lock(mAccessLock);
-
-    if (!bufferHandle)
-    {
-        ALOGE("ignoring doneWithFrame called with invalid handle");
-        return EvsResult::INVALID_ARG;
-    }
-
-    // TODO:  Track which frames we've delivered and validate this is one of them
-
-    // Mark the frame buffer as available for a new frame
-    mFrameBusy = false;
-
-    // TODO:  If we currently have too many buffers, drop this one
-
-    return EvsResult::OK;
-}
-
-Return<void> EvsCamera::stopVideoStream()  {
-    ALOGD("stopVideoStream");
-
-    bool waitForJoin = false;
-    // Lock scope
-    {
+    {  // lock context
         std::lock_guard <std::mutex> lock(mAccessLock);
 
-        if (mStreamState == RUNNING) {
-            // Tell the GenerateFrames loop we want it to stop
-            mStreamState = STOPPING;
+        if (buffer.memHandle == nullptr) {
+            ALOGE("ignoring doneWithFrame called with null handle");
+        } else if (buffer.bufferId >= mBuffers.size()) {
+            ALOGE("ignoring doneWithFrame called with invalid bufferId %d (max is %lu)",
+                  buffer.bufferId, mBuffers.size()-1);
+        } else if (!mBuffers[buffer.bufferId].inUse) {
+            ALOGE("ignoring doneWithFrame called on frame %d which is already free",
+                  buffer.bufferId);
+        } else {
+            // Mark the frame as available
+            mBuffers[buffer.bufferId].inUse = false;
+            mFramesInUse--;
 
-            // Note that we asked the thread to stop and should wait for it do so
-            waitForJoin = true;
-        }
-    }
-
-    if (waitForJoin) {
-        // Block outside the mutex until the "stop" flag has been acknowledged
-        // NOTE:  We won't send any more frames, but the client might still get one already in flight
-        ALOGD("Waiting for stream thread to end...");
-        mCaptureThread.join();
-
-        // Lock scope
-        {
-            std::lock_guard <std::mutex> lock(mAccessLock);
-            mStreamState = STOPPED;
+            // If this frame's index is high in the array, try to move it down
+            // to improve locality after mFramesAllowed has been reduced.
+            if (buffer.bufferId >= mFramesAllowed) {
+                // Find an empty slot lower in the array (which should always exist in this case)
+                for (auto&& rec : mBuffers) {
+                    if (rec.handle == nullptr) {
+                        rec.handle = mBuffers[buffer.bufferId].handle;
+                        mBuffers[buffer.bufferId].handle = nullptr;
+                        break;
+                    }
+                }
+            }
         }
     }
 
     return Void();
 }
 
+
+Return<void> EvsCamera::stopVideoStream()  {
+    ALOGD("stopVideoStream");
+    std::unique_lock <std::mutex> lock(mAccessLock);
+
+    if (mStreamState == RUNNING) {
+        // Tell the GenerateFrames loop we want it to stop
+        mStreamState = STOPPING;
+
+        // Block outside the mutex until the "stop" flag has been acknowledged
+        // We won't send any more frames, but the client might still get some already in flight
+        ALOGD("Waiting for stream thread to end...");
+        lock.unlock();
+        mCaptureThread.join();
+        lock.lock();
+
+        mStreamState = STOPPED;
+        ALOGD("Stream marked STOPPED.");
+    }
+
+    return Void();
+}
+
+
 Return<int32_t> EvsCamera::getExtendedInfo(uint32_t opaqueIdentifier)  {
     ALOGD("getExtendedInfo");
     std::lock_guard<std::mutex> lock(mAccessLock);
@@ -215,6 +225,7 @@
     return 0;
 }
 
+
 Return<EvsResult> EvsCamera::setExtendedInfo(uint32_t /*opaqueIdentifier*/, int32_t /*opaqueValue*/)  {
     ALOGD("setExtendedInfo");
     std::lock_guard<std::mutex> lock(mAccessLock);
@@ -224,10 +235,124 @@
 }
 
 
-void EvsCamera::GenerateFrames() {
-    ALOGD("Frame generate loop started");
+bool EvsCamera::setAvailableFrames_Locked(unsigned bufferCount) {
+    if (bufferCount < 1) {
+        ALOGE("Ignoring request to set buffer count to zero");
+        return false;
+    }
+    if (bufferCount > MAX_BUFFERS_IN_FLIGHT) {
+        ALOGE("Rejecting buffer request in excess of internal limit");
+        return false;
+    }
 
-    uint32_t frameNumber;
+    // Is an increase required?
+    if (mFramesAllowed < bufferCount) {
+        // An increase is required
+        unsigned needed = bufferCount - mFramesAllowed;
+        ALOGI("Allocating %d buffers for camera frames", needed);
+
+        unsigned added = increaseAvailableFrames_Locked(needed);
+        if (added != needed) {
+            // If we didn't add all the frames we needed, then roll back to the previous state
+            ALOGE("Rolling back to previous frame queue size");
+            decreaseAvailableFrames_Locked(added);
+            return false;
+        }
+    } else if (mFramesAllowed > bufferCount) {
+        // A decrease is required
+        unsigned framesToRelease = mFramesAllowed - bufferCount;
+        ALOGI("Returning %d camera frame buffers", framesToRelease);
+
+        unsigned released = decreaseAvailableFrames_Locked(framesToRelease);
+        if (released != framesToRelease) {
+            // This shouldn't happen with a properly behaving client because the client
+            // should only make this call after returning sufficient outstanding buffers
+            // to allow a clean resize.
+            ALOGE("Buffer queue shrink failed -- too many buffers currently in use?");
+        }
+    }
+
+    return true;
+}
+
+
+unsigned EvsCamera::increaseAvailableFrames_Locked(unsigned numToAdd) {
+    // Acquire the graphics buffer allocator
+    GraphicBufferAllocator &alloc(GraphicBufferAllocator::get());
+
+    unsigned added = 0;
+
+    while (added < numToAdd) {
+        buffer_handle_t memHandle = nullptr;
+        status_t result = alloc.allocate(mWidth, mHeight,
+                                         mFormat, 1,
+                                         mUsage,
+                                         &memHandle, &mStride, 0, "EvsCamera");
+        if (result != NO_ERROR) {
+            ALOGE("Error %d allocating %d x %d graphics buffer", result, mWidth, mHeight);
+            break;
+        }
+        if (!memHandle) {
+            ALOGE("We didn't get a buffer handle back from the allocator");
+            break;
+        }
+
+        // Find a place to store the new buffer
+        bool stored = false;
+        for (auto&& rec : mBuffers) {
+            if (rec.handle == nullptr) {
+                // Use this existing entry
+                rec.handle = memHandle;
+                rec.inUse = false;
+                stored = true;
+                break;
+            }
+        }
+        if (!stored) {
+            // Add a BufferRecord wrapping this handle to our set of available buffers
+            mBuffers.emplace_back(memHandle);
+        }
+
+        mFramesAllowed++;
+        added++;
+    }
+
+    return added;
+}
+
+
+unsigned EvsCamera::decreaseAvailableFrames_Locked(unsigned numToRemove) {
+    // Acquire the graphics buffer allocator
+    GraphicBufferAllocator &alloc(GraphicBufferAllocator::get());
+
+    unsigned removed = 0;
+
+    for (auto&& rec : mBuffers) {
+        // Is this record not in use, but holding a buffer that we can free?
+        if ((rec.inUse == false) && (rec.handle != nullptr)) {
+            // Release buffer and update the record so we can recognize it as "empty"
+            alloc.free(rec.handle);
+            rec.handle = nullptr;
+
+            mFramesAllowed--;
+            removed++;
+
+            if (removed == numToRemove) {
+                break;
+            }
+        }
+    }
+
+    return removed;
+}
+
+
+// This is the asynchronous frame generation thread that runs in parallel with the
+// main serving thread.  There is one for each active camera instance.
+void EvsCamera::generateFrames() {
+    ALOGD("Frame generation loop started");
+
+    unsigned idx;
 
     while (true) {
         bool timeForFrame = false;
@@ -235,57 +360,69 @@
         {
             std::lock_guard<std::mutex> lock(mAccessLock);
 
-            // Tick the frame counter -- rollover is tolerated
-            frameNumber = mFrameId++;
-
             if (mStreamState != RUNNING) {
                 // Break out of our main thread loop
                 break;
             }
 
-            if (mFrameBusy) {
+            // Are we allowed to issue another buffer?
+            if (mFramesInUse >= mFramesAllowed) {
                 // Can't do anything right now -- skip this frame
-                ALOGW("Skipped a frame because client hasn't returned a buffer\n");
-            }
-            else {
-                // We're going to make the frame busy
-                mFrameBusy = true;
-                timeForFrame = true;
+                ALOGW("Skipped a frame because too many are in flight\n");
+            } else {
+                // Identify an available buffer to fill
+                for (idx = 0; idx < mBuffers.size(); idx++) {
+                    if (!mBuffers[idx].inUse) {
+                        if (mBuffers[idx].handle != nullptr) {
+                            // Found an available record, so stop looking
+                            break;
+                        }
+                    }
+                }
+                if (idx >= mBuffers.size()) {
+                    // This shouldn't happen since we already checked mFramesInUse vs mFramesAllowed
+                    ALOGE("Failed to find an available buffer slot\n");
+                } else {
+                    // We're going to make the frame busy
+                    mBuffers[idx].inUse = true;
+                    mFramesInUse++;
+                    timeForFrame = true;
+                }
             }
         }
 
         if (timeForFrame) {
-            // Lock our output buffer for writing
-            uint32_t *pixels = nullptr;
-            GraphicBufferMapper &mapper = GraphicBufferMapper::get();
-            mapper.lock(mBuffer,
-                        GRALLOC_USAGE_SW_WRITE_OFTEN,
-                        android::Rect(mWidth, mHeight),
-                        (void **) &pixels);
+            // Assemble the buffer description we'll transmit below
+            BufferDesc buff = {};
+            buff.width      = mWidth;
+            buff.height     = mHeight;
+            buff.stride     = mStride;
+            buff.format     = mFormat;
+            buff.usage      = mUsage;
+            buff.bufferId   = idx;
+            buff.memHandle  = mBuffers[idx].handle;
 
-            // If we failed to lock the pixel buffer, we're about to crash, but log it first
-            if (!pixels) {
-                ALOGE("Camera failed to gain access to image buffer for writing");
+            // Write test data into the image buffer
+            fillTestFrame(buff);
+
+            // Issue the (asynchronous) callback to the client -- can't be holding the lock
+            auto result = mStream->deliverFrame(buff);
+            if (result.isOk()) {
+                ALOGD("Delivered %p as id %d", buff.memHandle.getNativeHandle(), buff.bufferId);
+            } else {
+                // This can happen if the client dies and is likely unrecoverable.
+                // To avoid consuming resources generating failing calls, we stop sending
+                // frames.  Note, however, that the stream remains in the "STREAMING" state
+                // until cleaned up on the main thread.
+                ALOGE("Frame delivery call failed in the transport layer.");
+
+                // Since we didn't actually deliver it, mark the frame as available
+                std::lock_guard<std::mutex> lock(mAccessLock);
+                mBuffers[idx].inUse = false;
+                mFramesInUse--;
+
+                break;
             }
-
-            // Fill in the test pixels
-            for (unsigned row = 0; row < mHeight; row++) {
-                for (unsigned col = 0; col < mWidth; col++) {
-                    // Index into the row to set the pixel at this column
-                    // (We're making vertical gradient in the green channel, and
-                    // horitzontal gradient in the blue channel)
-                    pixels[col] = 0xFF0000FF | ((row & 0xFF) << 16) | ((col & 0xFF) << 8);
-                }
-                // Point to the next row
-                pixels = pixels + (mStride / sizeof(*pixels));
-            }
-
-            // Release our output buffer
-            mapper.unlock(mBuffer);
-
-            // Issue the (asynchronous) callback to the client
-            mStream->deliverFrame(frameNumber, mBuffer);
-            ALOGD("Delivered %p as frame %d", mBuffer, frameNumber);
         }
 
         // We arbitrarily choose to generate frames at 10 fps (1/10 * uSecPerSec)
@@ -293,11 +430,58 @@
     }
 
     // If we've been asked to stop, send one last NULL frame to signal the actual end of stream
-    mStream->deliverFrame(frameNumber, nullptr);
+    BufferDesc nullBuff = {};
+    auto result = mStream->deliverFrame(nullBuff);
+    if (!result.isOk()) {
+        ALOGE("Error delivering end of stream marker");
+    }
 
     return;
 }
 
+
+void EvsCamera::fillTestFrame(BufferDesc buff) {
+    // Lock our output buffer for writing
+    uint32_t *pixels = nullptr;
+    GraphicBufferMapper &mapper = GraphicBufferMapper::get();
+    mapper.lock(buff.memHandle,
+                GRALLOC_USAGE_SW_WRITE_OFTEN | GRALLOC_USAGE_SW_READ_NEVER,
+                android::Rect(buff.width, buff.height),
+                (void **) &pixels);
+
+    // If we failed to lock the pixel buffer, we're about to crash, but log it first
+    if (!pixels) {
+        ALOGE("Camera failed to gain access to image buffer for writing");
+    }
+
+    // Fill in the test pixels
+    for (unsigned row = 0; row < buff.height; row++) {
+        for (unsigned col = 0; col < buff.width; col++) {
+            // Index into the row to check the pixel at this column.
+            // We expect 0xFF in the LSB channel, a vertical gradient in the
+            // second channel, a horitzontal gradient in the third channel, and
+            // 0xFF in the MSB.
+            // The exception is the very first 32 bits which is used for the
+            // time varying frame signature to avoid getting fooled by a static image.
+            uint32_t expectedPixel = 0xFF0000FF           | // MSB and LSB
+                                     ((row & 0xFF) <<  8) | // vertical gradient
+                                     ((col & 0xFF) << 16);  // horizontal gradient
+            if ((row | col) == 0) {
+                static uint32_t sFrameTicker = 0;
+                expectedPixel = (sFrameTicker) & 0xFF;
+                sFrameTicker++;
+            }
+            pixels[col] = expectedPixel;
+        }
+        // Point to the next row
+        pixels = pixels + (buff.stride / sizeof(*pixels));
+    }
+
+    // Release our output buffer
+    mapper.unlock(buff.memHandle);
+}
+
+
 } // namespace implementation
 } // namespace V1_0
 } // namespace evs
diff --git a/evs/1.0/default/EvsCamera.h b/evs/1.0/default/EvsCamera.h
index 5d29125..8d644a0 100644
--- a/evs/1.0/default/EvsCamera.h
+++ b/evs/1.0/default/EvsCamera.h
@@ -23,19 +23,21 @@
 
 #include <thread>
 
+
 namespace android {
 namespace hardware {
 namespace evs {
 namespace V1_0 {
 namespace implementation {
 
+
 class EvsCamera : public IEvsCamera {
 public:
     // Methods from ::android::hardware::evs::V1_0::IEvsCamera follow.
     Return<void> getId(getId_cb id_cb)  override;
     Return<EvsResult> setMaxFramesInFlight(uint32_t bufferCount)  override;
     Return<EvsResult> startVideoStream(const ::android::sp<IEvsCameraStream>& stream) override;
-    Return<EvsResult> doneWithFrame(uint32_t frameId, const hidl_handle& bufferHandle)  override;
+    Return<void> doneWithFrame(const BufferDesc& buffer)  override;
     Return<void> stopVideoStream()  override;
     Return<int32_t> getExtendedInfo(uint32_t opaqueIdentifier)  override;
     Return<EvsResult> setExtendedInfo(uint32_t opaqueIdentifier, int32_t opaqueValue)  override;
@@ -45,34 +47,49 @@
     virtual ~EvsCamera() override;
 
     const CameraDesc& getDesc() { return mDescription; };
-    void GenerateFrames();
 
     static const char kCameraName_Backup[];
     static const char kCameraName_RightTurn[];
 
 private:
-    CameraDesc              mDescription = {};  // The properties of this camera
+    // These three functions are expected to be called while mAccessLock is held
+    bool     setAvailableFrames_Locked(unsigned bufferCount);
+    unsigned increaseAvailableFrames_Locked(unsigned numToAdd);
+    unsigned decreaseAvailableFrames_Locked(unsigned numToRemove);
 
-    buffer_handle_t         mBuffer = nullptr;  // A graphics buffer into which we'll store images
-    uint32_t                mWidth  = 0;        // number of pixels across the buffer
-    uint32_t                mHeight = 0;        // number of pixels vertically in the buffer
-    uint32_t                mStride = 0;        // Bytes per line in the buffer
+    void generateFrames();
+    void fillTestFrame(BufferDesc buff);
 
-    sp<IEvsCameraStream>    mStream = nullptr;  // The callback the user expects when a frame is ready
+    CameraDesc                  mDescription = {};  // The properties of this camera
 
-    std::thread             mCaptureThread;     // The thread we'll use to synthesize frames
+    std::thread                 mCaptureThread;     // The thread we'll use to synthesize frames
 
-    uint32_t                mFrameId;           // A frame counter used to identify specific frames
+    uint32_t                    mWidth  = 0;        // Horizontal pixel count in the buffers
+    uint32_t                    mHeight = 0;        // Vertical pixel count in the buffers
+    uint32_t                    mFormat = 0;        // Values from android_pixel_format_t [TODO: YUV?  Leave opaque?]
+    uint32_t                    mUsage  = 0;        // Values from from Gralloc.h
+    uint32_t                    mStride = 0;        // Bytes per line in the buffers
+
+    sp<IEvsCameraStream>        mStream = nullptr;  // The callback used to deliver each frame
+
+    struct BufferRecord {
+        buffer_handle_t     handle;
+        bool                inUse;
+        explicit BufferRecord(buffer_handle_t h) : handle(h), inUse(false) {};
+    };
+    std::vector<BufferRecord>   mBuffers;           // Graphics buffers to transfer images
+    unsigned                    mFramesAllowed;     // How many buffers are we currently using
+    unsigned                    mFramesInUse;       // How many buffers are currently outstanding
 
     enum StreamStateValues {
         STOPPED,
         RUNNING,
         STOPPING,
     };
-    StreamStateValues       mStreamState;
-    bool                    mFrameBusy;         // A flag telling us our one buffer is in use
+    StreamStateValues           mStreamState;
 
-    std::mutex              mAccessLock;
+    // Syncrhonization necessary to deconflict mCaptureThread from the main service thread
+    std::mutex                  mAccessLock;
 };
 
 } // namespace implementation
diff --git a/evs/1.0/default/EvsDisplay.cpp b/evs/1.0/default/EvsDisplay.cpp
index 9dba6fc..dff4c49 100644
--- a/evs/1.0/default/EvsDisplay.cpp
+++ b/evs/1.0/default/EvsDisplay.cpp
@@ -39,6 +39,7 @@
     ALOGD("EvsDisplay instantiated");
 
     // Set up our self description
+    // NOTE:  These are arbitrary values chosen for testing
     mInfo.displayId             = "Mock Display";
     mInfo.vendorFlags           = 3870;
     mInfo.defaultHorResolution  = 320;
@@ -50,16 +51,17 @@
     ALOGD("EvsDisplay being destroyed");
     std::lock_guard<std::mutex> lock(mAccessLock);
 
-    // Report if we're going away while a buffer is outstanding.  This could be bad.
+    // Report if we're going away while a buffer is outstanding
     if (mFrameBusy) {
-        ALOGE("EvsDisplay going down while client is holding a buffer\n");
+        ALOGE("EvsDisplay going down while client is holding a buffer");
     }
 
     // Make sure we release our frame buffer
-    if (mBuffer) {
+    if (mBuffer.memHandle) {
         // Drop the graphics buffer we've been using
         GraphicBufferAllocator& alloc(GraphicBufferAllocator::get());
-        alloc.free(mBuffer);
+        alloc.free(mBuffer.memHandle);
+        mBuffer.memHandle = nullptr;
     }
     ALOGD("EvsDisplay destroyed");
 }
@@ -135,36 +137,60 @@
     std::lock_guard<std::mutex> lock(mAccessLock);
 
     // If we don't already have a buffer, allocate one now
-    if (!mBuffer) {
+    if (!mBuffer.memHandle) {
+        // Assemble the buffer description we'll use for our render target
+        mBuffer.width       = mInfo.defaultHorResolution;
+        mBuffer.height      = mInfo.defaultVerResolution;
+        mBuffer.format      = HAL_PIXEL_FORMAT_RGBA_8888;
+        mBuffer.usage       = GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_COMPOSER;
+        mBuffer.bufferId    = 0x3870;  // Arbitrary magic number for self recognition
+
+        buffer_handle_t handle = nullptr;
         GraphicBufferAllocator& alloc(GraphicBufferAllocator::get());
-        status_t result = alloc.allocate(mInfo.defaultHorResolution, mInfo.defaultVerResolution,
-                                         HAL_PIXEL_FORMAT_RGBA_8888, 1,
-                                         GRALLOC_USAGE_HW_FB | GRALLOC_USAGE_HW_COMPOSER,
-                                         &mBuffer, &mStride, 0, "EvsDisplay");
+        status_t result = alloc.allocate(mBuffer.width, mBuffer.height,
+                                         mBuffer.format, 1, mBuffer.usage,
+                                         &handle, &mBuffer.stride,
+                                         0, "EvsDisplay");
+        if (result != NO_ERROR) {
+            ALOGE("Error %d allocating %d x %d graphics buffer",
+                  result, mBuffer.width, mBuffer.height);
+            BufferDesc nullBuff = {};
+            _hidl_cb(nullBuff);
+            return Void();
+        }
+        if (!handle) {
+            ALOGE("We didn't get a buffer handle back from the allocator");
+            BufferDesc nullBuff = {};
+            _hidl_cb(nullBuff);
+            return Void();
+        }
+
+        mBuffer.memHandle = handle;
         mFrameBusy = false;
-        ALOGD("Allocated new buffer %p with stride %u", mBuffer, mStride);
+        ALOGD("Allocated new buffer %p with stride %u",
+              mBuffer.memHandle.getNativeHandle(), mStride);
     }
 
     // Do we have a frame available?
     if (mFrameBusy) {
         // This means either we have a 2nd client trying to compete for buffers
         // (an unsupported mode of operation) or else the client hasn't returned
-        // a previously issues buffer yet (they're behaving badly).
-        // NOTE:  We have to make callback even if we have nothing to provide
+        // a previously issued buffer yet (they're behaving badly).
+        // NOTE:  We have to make the callback even if we have nothing to provide
         ALOGE("getTargetBuffer called while no buffers available.");
-        _hidl_cb(nullptr);
-    }
-    else {
+        BufferDesc nullBuff = {};
+        _hidl_cb(nullBuff);
+        return Void();
+    } else {
         // Mark our buffer as busy
         mFrameBusy = true;
 
         // Send the buffer to the client
-        ALOGD("Providing display buffer %p", mBuffer);
+        ALOGD("Providing display buffer handle %p as id %d",
+              mBuffer.memHandle.getNativeHandle(), mBuffer.bufferId);
         _hidl_cb(mBuffer);
+        return Void();
     }
-
-    // All done
-    return Void();
 }
 
 
@@ -172,22 +198,19 @@
  * This call tells the display that the buffer is ready for display.
  * The buffer is no longer valid for use by the client after this call.
  */
-Return<EvsResult> EvsDisplay::returnTargetBufferForDisplay(const hidl_handle& bufferHandle)  {
-    ALOGD("returnTargetBufferForDisplay %p", bufferHandle.getNativeHandle());
+Return<EvsResult> EvsDisplay::returnTargetBufferForDisplay(const BufferDesc& buffer)  {
+    ALOGD("returnTargetBufferForDisplay %p", buffer.memHandle.getNativeHandle());
     std::lock_guard<std::mutex> lock(mAccessLock);
 
-    // This shouldn't happen if we haven't issued the buffer!
-    if (!bufferHandle) {
+    // Nobody should call us with a null handle
+    if (!buffer.memHandle.getNativeHandle()) {
         ALOGE ("returnTargetBufferForDisplay called without a valid buffer handle.\n");
         return EvsResult::INVALID_ARG;
     }
-    /* TODO(b/33492405): It would be nice to validate we got back the buffer we expect,
-     * but HIDL doesn't support that (yet?)
-    if (bufferHandle != mBuffer) {
+    if (buffer.bufferId != mBuffer.bufferId) {
         ALOGE ("Got an unrecognized frame returned.\n");
         return EvsResult::INVALID_ARG;
     }
-    */
     if (!mFrameBusy) {
         ALOGE ("A frame was returned with no outstanding frames.\n");
         return EvsResult::BUFFER_NOT_AVAILABLE;
@@ -204,10 +227,71 @@
     if (mRequestedState != DisplayState::VISIBLE) {
         // We shouldn't get frames back when we're not visible.
         ALOGE ("Got an unexpected frame returned while not visible - ignoring.\n");
-    }
-    else {
-        // Make this buffer visible
-        // TODO:  Add code to put this image on the screen (or validate it somehow?)
+    } else {
+        // This is where the buffer would be made visible.
+        // For now we simply validate it has the data we expect in it by reading it back
+
+        // Lock our display buffer for reading
+        uint32_t* pixels = nullptr;
+        GraphicBufferMapper &mapper = GraphicBufferMapper::get();
+        mapper.lock(mBuffer.memHandle,
+                    GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_NEVER,
+                    android::Rect(mBuffer.width, mBuffer.height),
+                    (void **)&pixels);
+
+        // If we failed to lock the pixel buffer, we're about to crash, but log it first
+        if (!pixels) {
+            ALOGE("Camera failed to gain access to image buffer for reading");
+        }
+
+        // Check the test pixels
+        bool frameLooksGood = true;
+        for (unsigned row = 0; row < mInfo.defaultVerResolution; row++) {
+            for (unsigned col = 0; col < mInfo.defaultHorResolution; col++) {
+                // Index into the row to check the pixel at this column.
+                // We expect 0xFF in the LSB channel, a vertical gradient in the
+                // second channel, a horitzontal gradient in the third channel, and
+                // 0xFF in the MSB.
+                // The exception is the very first 32 bits which is used for the
+                // time varying frame signature to avoid getting fooled by a static image.
+                uint32_t expectedPixel = 0xFF0000FF           | // MSB and LSB
+                                         ((row & 0xFF) <<  8) | // vertical gradient
+                                         ((col & 0xFF) << 16);  // horizontal gradient
+                if ((row | col) == 0) {
+                    // we'll check the "uniqueness" of the frame signature below
+                    continue;
+                }
+                // Walk across this row (we'll step rows below)
+                if (pixels[col] != expectedPixel) {
+                    ALOGE("Pixel check mismatch in frame buffer");
+                    frameLooksGood = false;
+                    break;
+                }
+            }
+
+            if (!frameLooksGood) {
+                break;
+            }
+
+            // Point to the next row
+            pixels = pixels + (mStride / sizeof(*pixels));
+        }
+
+        // Ensure we don't see the same buffer twice without it being rewritten
+        static uint32_t prevSignature = ~0;
+        uint32_t signature = pixels[0] & 0xFF;
+        if (prevSignature == signature) {
+            frameLooksGood = false;
+            ALOGE("Duplicate, likely stale frame buffer detected");
+        }
+
+
+        // Release our output buffer
+        mapper.unlock(mBuffer.memHandle);
+
+        if (!frameLooksGood) {
+            return EvsResult::UNDERLYING_SERVICE_ERROR;
+        }
     }
 
     return EvsResult::OK;
diff --git a/evs/1.0/default/EvsDisplay.h b/evs/1.0/default/EvsDisplay.h
index a2d5d3e..6e0111e 100644
--- a/evs/1.0/default/EvsDisplay.h
+++ b/evs/1.0/default/EvsDisplay.h
@@ -33,7 +33,7 @@
     Return<EvsResult> setDisplayState(DisplayState state)  override;
     Return<DisplayState> getDisplayState()  override;
     Return<void> getTargetBuffer(getTargetBuffer_cb _hidl_cb)  override;
-    Return<EvsResult> returnTargetBufferForDisplay(const hidl_handle& bufferHandle)  override;
+    Return<EvsResult> returnTargetBufferForDisplay(const BufferDesc& buffer)  override;
 
     // Implementation details
     EvsDisplay();
@@ -41,10 +41,10 @@
 
 private:
     DisplayDesc     mInfo           = {};
-    buffer_handle_t mBuffer         = nullptr;      // A graphics buffer into which we'll store images
-    uint32_t        mStride         = 0;            // Bytes per line in the buffer
+    BufferDesc      mBuffer         = {};       // A graphics buffer into which we'll store images
+    uint32_t        mStride         = 0;        // Bytes per line in the buffer
 
-    bool            mFrameBusy      = false;        // A flag telling us our buffer is in use
+    bool            mFrameBusy      = false;    // A flag telling us our buffer is in use
     DisplayState    mRequestedState = DisplayState::NOT_VISIBLE;
 
     std::mutex      mAccessLock;
diff --git a/evs/1.0/default/EvsEnumerator.cpp b/evs/1.0/default/EvsEnumerator.cpp
index ba8da00..4bf77f3 100644
--- a/evs/1.0/default/EvsEnumerator.cpp
+++ b/evs/1.0/default/EvsEnumerator.cpp
@@ -27,6 +27,11 @@
 namespace implementation {
 
 
+// TODO(b/31632518):  Need to get notification when our client dies so we can close the camera.
+// As it stands, if the client dies suddenly, the camera will be stuck "open".
+// NOTE:  Display should already be safe by virtue of holding only a weak pointer.
+
+
 EvsEnumerator::EvsEnumerator() {
     ALOGD("EvsEnumerator created");
 
@@ -78,15 +83,11 @@
     if (!pRecord) {
         ALOGE("Requested camera %s not found", cameraId.c_str());
         return nullptr;
-    }
-    else if (pRecord->inUse) {
+    } else if (pRecord->inUse) {
         ALOGE("Cannot open camera %s which is already in use", cameraId.c_str());
         return nullptr;
-    }
-    else {
-        /* TODO(b/33492405):  Do this, When HIDL can give us back a recognizable pointer
+    } else {
         pRecord->inUse = true;
-         */
         return(pRecord->pCamera);
     }
 }
@@ -96,14 +97,21 @@
 
     if (camera == nullptr) {
         ALOGE("Ignoring call to closeCamera with null camera pointer");
-    }
-    else {
-        // Make sure the camera has stopped streaming
-        camera->stopVideoStream();
+    } else {
+        // Find this camera in our list
+        auto it = std::find_if(mCameraList.begin(),
+                               mCameraList.end(),
+                               [camera](const CameraRecord& rec) {
+                                   return (rec.pCamera == camera);
+                               });
+        if (it == mCameraList.end()) {
+            ALOGE("Ignoring close on unrecognized camera");
+        } else {
+            // Make sure the camera has stopped streaming
+            camera->stopVideoStream();
 
-        /* TODO(b/33492405):  Do this, When HIDL can give us back a recognizable pointer
-        pRecord->inUse = false;
-         */
+            it->inUse = false;
+        }
     }
 
     return Void();
@@ -113,41 +121,49 @@
     ALOGD("openDisplay");
 
     // If we already have a display active, then this request must be denied
-    if (mActiveDisplay != nullptr) {
+    sp<IEvsDisplay> pActiveDisplay = mActiveDisplay.promote();
+    if (pActiveDisplay != nullptr) {
         ALOGW("Rejecting openDisplay request the display is already in use.");
         return nullptr;
-    }
-    else {
+    } else {
         // Create a new display interface and return it
-        mActiveDisplay = new EvsDisplay();
-        ALOGD("Returning new EvsDisplay object %p", mActiveDisplay.get());
-        return mActiveDisplay;
+        pActiveDisplay = new EvsDisplay();
+        mActiveDisplay = pActiveDisplay;
+        ALOGD("Returning new EvsDisplay object %p", pActiveDisplay.get());
+        return pActiveDisplay;
     }
 }
 
 Return<void> EvsEnumerator::closeDisplay(const ::android::sp<IEvsDisplay>& display) {
     ALOGD("closeDisplay");
 
-    if (mActiveDisplay == nullptr) {
-        ALOGE("Ignoring closeDisplay when display is not active");
-    }
-    else if (display == nullptr) {
-        ALOGE("Ignoring closeDisplay with null display pointer");
-    }
-    else {
+    // Do we still have a display object we think should be active?
+    sp<IEvsDisplay> pActiveDisplay = mActiveDisplay.promote();
+
+    if (pActiveDisplay == nullptr) {
+        ALOGE("Ignoring closeDisplay when there is no active display.");
+    } else if (display != pActiveDisplay) {
+        ALOGE("Ignoring closeDisplay on a display we didn't issue");
+        ALOGI("Got %p while active display is %p.", display.get(), pActiveDisplay.get());
+    } else {
         // Drop the active display
-        // TODO(b/33492405):  When HIDL provides recognizable pointers, add validation here.
         mActiveDisplay = nullptr;
     }
 
     return Void();
 }
 
+Return<DisplayState> EvsEnumerator::getDisplayState()  {
+    ALOGD("getDisplayState");
 
-// TODO(b/31632518):  Need to get notification when our client dies so we can close the camera.
-// As possible work around would be to give the client a HIDL object to exclusively hold
-// and use it's destructor to perform some work in the server side.
-
+    // Do we still have a display object we think should be active?
+    sp<IEvsDisplay> pActiveDisplay = mActiveDisplay.promote();
+    if (pActiveDisplay != nullptr) {
+        return pActiveDisplay->getDisplayState();
+    } else {
+        return DisplayState::NOT_OPEN;
+    }
+}
 
 } // namespace implementation
 } // namespace V1_0
diff --git a/evs/1.0/default/EvsEnumerator.h b/evs/1.0/default/EvsEnumerator.h
index 90df837..0e719bd 100644
--- a/evs/1.0/default/EvsEnumerator.h
+++ b/evs/1.0/default/EvsEnumerator.h
@@ -38,6 +38,7 @@
     Return<void> closeCamera(const ::android::sp<IEvsCamera>& carCamera)  override;
     Return<sp<IEvsDisplay>> openDisplay()  override;
     Return<void> closeDisplay(const ::android::sp<IEvsDisplay>& display)  override;
+    Return<DisplayState> getDisplayState()  override;
 
     // Implementation details
     EvsEnumerator();
@@ -50,7 +51,7 @@
     };
     std::list<CameraRecord> mCameraList;
 
-    sp<IEvsDisplay>         mActiveDisplay;
+    wp<IEvsDisplay>         mActiveDisplay; // Weak pointer -> object destructs if client dies
 };
 
 } // namespace implementation
diff --git a/evs/1.0/types.hal b/evs/1.0/types.hal
index fd9dcdc..6b580cf 100644
--- a/evs/1.0/types.hal
+++ b/evs/1.0/types.hal
@@ -72,6 +72,29 @@
 
 
 /*
+ * Structure representing an image buffer through our APIs
+ *
+ * In addition to the handle to the graphics memory, we need to retain
+ * the properties of the buffer for easy reference and reconstruction of
+ * an ANativeWindowBuffer object on the remote side of API calls.
+ * (Not least because OpenGL expect an ANativeWindowBuffer* for us as a
+ * texture via eglCreateImageKHR().
+ * See also related types from android.hardware.graphics.common
+ * TODO:  b/34722508  Review details of interaction of this structure with gralloc and OpenGL.
+ *        Specifically consider if format and/or usage should become enumerated types.
+ */
+struct BufferDesc {
+    uint32_t    width;      // Units of pixels
+    uint32_t    height;     // Units of pixels
+    uint32_t    stride;     // Units of bytes
+    uint32_t    format;     // May contain values from android_pixel_format_t
+    uint32_t    usage;      // May contain values from from Gralloc.h
+    uint32_t    bufferId;   // Opaque value from driver
+    handle      memHandle;  // gralloc memory buffer handle
+};
+
+
+/*
  * States for control of the EVS display
  *
  * The DisplayInfo structure describes the basic properties of an EVS display. Any EVS
@@ -81,7 +104,8 @@
  * presentation device.
  */
 enum DisplayState : uint32_t {
-    NOT_VISIBLE = 0,        // Display is inhibited
+    NOT_OPEN = 0,           // Display has not been requested by any application
+    NOT_VISIBLE,            // Display is inhibited
     VISIBLE_ON_NEXT_FRAME,  // Will become visible with next frame
     VISIBLE,                // Display is currently active
     NUM_STATES              // Must be last
@@ -94,4 +118,5 @@
     INVALID_ARG,
     STREAM_ALREADY_RUNNING,
     BUFFER_NOT_AVAILABLE,
+    UNDERLYING_SERVICE_ERROR,
 };
\ No newline at end of file
diff --git a/gatekeeper/1.0/vts/functional/gatekeeper_hidl_hal_test.cpp b/gatekeeper/1.0/vts/functional/gatekeeper_hidl_hal_test.cpp
index 09690f8..67b4482 100644
--- a/gatekeeper/1.0/vts/functional/gatekeeper_hidl_hal_test.cpp
+++ b/gatekeeper/1.0/vts/functional/gatekeeper_hidl_hal_test.cpp
@@ -187,7 +187,7 @@
   GatekeeperHidlTest() : uid_(0) {}
   virtual void SetUp() override {
     GatekeeperResponse rsp;
-    gatekeeper_ = IGatekeeper::getService("gatekeeper", false);
+    gatekeeper_ = IGatekeeper::getService("gatekeeper");
     ASSERT_NE(nullptr, gatekeeper_.get());
     doDeleteAllUsers(rsp);
   }
diff --git a/ir/1.0/vts/functional/ir_hidl_hal_test.cpp b/ir/1.0/vts/functional/ir_hidl_hal_test.cpp
index 57d0b73..08c7974 100644
--- a/ir/1.0/vts/functional/ir_hidl_hal_test.cpp
+++ b/ir/1.0/vts/functional/ir_hidl_hal_test.cpp
@@ -34,7 +34,7 @@
 class ConsumerIrHidlTest : public ::testing::Test {
  public:
   virtual void SetUp() override {
-    ir = IConsumerIr::getService(false);
+    ir = IConsumerIr::getService();
     ASSERT_NE(ir, nullptr);
   }
 
diff --git a/ir/1.0/vts/functional/vts/testcases/hal/ir/hidl/target/AndroidTest.xml b/ir/1.0/vts/functional/vts/testcases/hal/ir/hidl/target/AndroidTest.xml
index 3ad7e45..bf3d236 100644
--- a/ir/1.0/vts/functional/vts/testcases/hal/ir/hidl/target/AndroidTest.xml
+++ b/ir/1.0/vts/functional/vts/testcases/hal/ir/hidl/target/AndroidTest.xml
@@ -25,7 +25,7 @@
             _64bit::DATA/nativetest64/ir_hidl_hal_test/ir_hidl_hal_test,
             "/>
         <option name="binary-test-type" value="hal_hidl_gtest" />
-        <option name="hwbinder-service" value="android.hardware.ir" />
+        <option name="precondition-hwbinder-service" value="android.hardware.ir" />
         <option name="test-timeout" value="1m" />
     </test>
 </configuration>
diff --git a/keymaster/3.0/IKeymasterDevice.hal b/keymaster/3.0/IKeymasterDevice.hal
index 19669c8..50a41ec 100644
--- a/keymaster/3.0/IKeymasterDevice.hal
+++ b/keymaster/3.0/IKeymasterDevice.hal
@@ -209,6 +209,21 @@
     deleteAllKeys() generates(ErrorCode error);
 
     /**
+     * Destroys knowledge of the device's ids. This prevents all device id attestation in the
+     * future. The destruction must be permanent so that not even a factory reset will restore the
+     * device ids.
+     *
+     * Device id attestation may be provided only if this method is fully implemented, allowing the
+     * user to permanently disable device id attestation. If this cannot be guaranteed, the device
+     * must never attest any device ids.
+     *
+     * This is a NOP if device id attestation is not supported.
+     *
+     * @return error See the ErrorCode enum.
+     */
+    destroyAttestationIds() generates(ErrorCode error);
+
+    /**
      * Begins a cryptographic operation using the specified key. If all is well, begin() will return
      * ErrorCode::OK and create an operation handle which must be passed to subsequent calls to
      * update(), finish() or abort().
diff --git a/keymaster/3.0/default/KeymasterDevice.cpp b/keymaster/3.0/default/KeymasterDevice.cpp
index 1208b8d..563ff84 100644
--- a/keymaster/3.0/default/KeymasterDevice.cpp
+++ b/keymaster/3.0/default/KeymasterDevice.cpp
@@ -516,6 +516,24 @@
 
     hidl_vec<hidl_vec<uint8_t>> resultCertChain;
 
+    for (size_t i = 0; i < attestParams.size(); ++i) {
+        switch (attestParams[i].tag) {
+            case Tag::ATTESTATION_ID_BRAND:
+            case Tag::ATTESTATION_ID_DEVICE:
+            case Tag::ATTESTATION_ID_PRODUCT:
+            case Tag::ATTESTATION_ID_SERIAL:
+            case Tag::ATTESTATION_ID_IMEI:
+            case Tag::ATTESTATION_ID_MEID:
+                // Device id attestation may only be supported if the device is able to permanently
+                // destroy its knowledge of the ids. This device is unable to do this, so it must
+                // never perform any device id attestation.
+                _hidl_cb(ErrorCode::CANNOT_ATTEST_IDS, resultCertChain);
+                return Void();
+            default:
+                break;
+        }
+    }
+
     keymaster_cert_chain_t cert_chain{nullptr, 0};
 
     auto kmKeyToAttest = hidlVec2KmKeyBlob(keyToAttest);
@@ -569,9 +587,16 @@
 }
 
 Return<ErrorCode> KeymasterDevice::deleteAllKeys() {
+    if (keymaster_device_->delete_all_keys == nullptr) {
+        return ErrorCode::UNIMPLEMENTED;
+    }
     return legacy_enum_conversion(keymaster_device_->delete_all_keys(keymaster_device_));
 }
 
+Return<ErrorCode> KeymasterDevice::destroyAttestationIds() {
+    return ErrorCode::UNIMPLEMENTED;
+}
+
 Return<void> KeymasterDevice::begin(KeyPurpose purpose, const hidl_vec<uint8_t>& key,
                                     const hidl_vec<KeyParameter>& inParams, begin_cb _hidl_cb) {
 
diff --git a/keymaster/3.0/default/KeymasterDevice.h b/keymaster/3.0/default/KeymasterDevice.h
index 23767ef..382f45f 100644
--- a/keymaster/3.0/default/KeymasterDevice.h
+++ b/keymaster/3.0/default/KeymasterDevice.h
@@ -71,6 +71,7 @@
                             upgradeKey_cb _hidl_cb) override;
     Return<ErrorCode> deleteKey(const hidl_vec<uint8_t>& keyBlob) override;
     Return<ErrorCode> deleteAllKeys() override;
+    Return<ErrorCode> destroyAttestationIds() override;
     Return<void> begin(KeyPurpose purpose, const hidl_vec<uint8_t>& key,
                        const hidl_vec<KeyParameter>& inParams, begin_cb _hidl_cb) override;
     Return<void> update(uint64_t operationHandle, const hidl_vec<KeyParameter>& inParams,
diff --git a/keymaster/3.0/types.hal b/keymaster/3.0/types.hal
index 7123e57..9f29b6a 100644
--- a/keymaster/3.0/types.hal
+++ b/keymaster/3.0/types.hal
@@ -123,6 +123,19 @@
     ATTESTATION_APPLICATION_ID = TagType:BYTES | 709, /* Used to identify the set of possible
                                                        * applications of which one has initiated a
                                                        * key attestation */
+    ATTESTATION_ID_BRAND = TagType:BYTES | 710,  /* Used to provide the device's brand name to be
+                                                    included in attestation */
+    ATTESTATION_ID_DEVICE = TagType:BYTES | 711, /* Used to provide the device's device name to be
+                                                    included in attestation */
+    ATTESTATION_ID_PRODUCT = TagType:BYTES | 712, /* Used to provide the device's product name to be
+                                                     included in attestation */
+    ATTESTATION_ID_SERIAL = TagType:BYTES | 713, /* Used to provide the device's serial number to be
+                                                    included in attestation */
+    ATTESTATION_ID_IMEI = TagType:BYTES | 714,   /* Used to provide the device's IMEI to be included
+                                                    in attestation */
+    ATTESTATION_ID_MEID = TagType:BYTES | 715,   /* Used to provide the device's MEID to be included
+                                                    in attestation */
+
 
     /* Tags used only to provide data to or receive data from operations */
     ASSOCIATED_DATA = TagType:BYTES | 1000, /* Used to provide associated data for AEAD modes. */
@@ -312,6 +325,7 @@
     ATTESTATION_CHALLENGE_MISSING = -63,
     KEYMASTER_NOT_CONFIGURED = -64,
     ATTESTATION_APPLICATION_ID_MISSING = -65,
+    CANNOT_ATTEST_IDS = -66,
 
     UNIMPLEMENTED = -100,
     VERSION_MISMATCH = -101,
diff --git a/memtrack/1.0/default/Memtrack.cpp b/memtrack/1.0/default/Memtrack.cpp
index fa09c25..33a6906 100644
--- a/memtrack/1.0/default/Memtrack.cpp
+++ b/memtrack/1.0/default/Memtrack.cpp
@@ -29,7 +29,7 @@
 namespace V1_0 {
 namespace implementation {
 
-Memtrack::Memtrack(memtrack_module_t *module) : mModule(module) {
+Memtrack::Memtrack(const memtrack_module_t *module) : mModule(module) {
     if (mModule)
         mModule->init(mModule);
 }
@@ -73,26 +73,26 @@
 }
 
 
-IMemtrack* HIDL_FETCH_IMemtrack(const char* name) {
-    int ret = 0;
-    const hw_module_t* hw_module = NULL;
-    memtrack_module_t *memtrack_module = NULL;
+IMemtrack* HIDL_FETCH_IMemtrack(const char* /* name */) {
+    const hw_module_t* hw_module = nullptr;
+    const memtrack_module_t* memtrack_module = nullptr;
+    int err = hw_get_module(MEMTRACK_HARDWARE_MODULE_ID, &hw_module);
+    if (err) {
+        ALOGE ("hw_get_module %s failed: %d", MEMTRACK_HARDWARE_MODULE_ID, err);
+        return nullptr;
+    }
 
-    ret = hw_get_module(name, &hw_module);
-    if (ret == 0 && hw_module->methods->open)
-    {
-        ret = hw_module->methods->open(hw_module, name,
-                reinterpret_cast<hw_device_t**>(&memtrack_module));
-        if (ret == 0)
-                return new Memtrack(memtrack_module);
-        else {
+    if (!hw_module->methods || !hw_module->methods->open) {
+        memtrack_module = reinterpret_cast<const memtrack_module_t*>(hw_module);
+    } else {
+        err = hw_module->methods->open(hw_module, MEMTRACK_HARDWARE_MODULE_ID,
+                reinterpret_cast<hw_device_t**>(const_cast<memtrack_module_t**>(&memtrack_module)));
+        if (err) {
             ALOGE("Passthrough failed to load legacy HAL.");
+            return nullptr;
         }
     }
-    else {
-        ALOGE ("hw_get_module %s failed: %d", name, ret);
-    }
-    return nullptr;
+    return new Memtrack(memtrack_module);
 }
 
 } // namespace implementation
diff --git a/memtrack/1.0/default/Memtrack.h b/memtrack/1.0/default/Memtrack.h
index a3c55e4..0adba76 100644
--- a/memtrack/1.0/default/Memtrack.h
+++ b/memtrack/1.0/default/Memtrack.h
@@ -38,12 +38,12 @@
 using ::android::sp;
 
 struct Memtrack : public IMemtrack {
-    Memtrack(memtrack_module_t* module);
+    Memtrack(const memtrack_module_t* module);
     ~Memtrack();
     Return<void> getMemory(int32_t pid, MemtrackType type, getMemory_cb _hidl_cb)  override;
 
   private:
-    memtrack_module_t* mModule;
+    const memtrack_module_t* mModule;
 };
 
 extern "C" IMemtrack* HIDL_FETCH_IMemtrack(const char* name);
diff --git a/memtrack/1.0/default/service.cpp b/memtrack/1.0/default/service.cpp
index f705b15..f079743 100644
--- a/memtrack/1.0/default/service.cpp
+++ b/memtrack/1.0/default/service.cpp
@@ -23,5 +23,5 @@
 using android::hardware::defaultPassthroughServiceImplementation;
 
 int main() {
-    return defaultPassthroughServiceImplementation<IMemtrack>("memtrack");
+    return defaultPassthroughServiceImplementation<IMemtrack>();
 }
diff --git a/memtrack/1.0/vts/functional/memtrack_hidl_hal_test.cpp b/memtrack/1.0/vts/functional/memtrack_hidl_hal_test.cpp
index 597b5da..a4b4fa9 100644
--- a/memtrack/1.0/vts/functional/memtrack_hidl_hal_test.cpp
+++ b/memtrack/1.0/vts/functional/memtrack_hidl_hal_test.cpp
@@ -37,7 +37,7 @@
 class MemtrackHidlTest : public ::testing::Test {
  public:
   virtual void SetUp() override {
-    memtrack = IMemtrack::getService("memtrack");
+    memtrack = IMemtrack::getService();
     ASSERT_NE(memtrack, nullptr);
   }
 
diff --git a/nfc/1.0/vts/functional/nfc_hidl_hal_test.cpp b/nfc/1.0/vts/functional/nfc_hidl_hal_test.cpp
index a50d88f..a0c5f1a 100644
--- a/nfc/1.0/vts/functional/nfc_hidl_hal_test.cpp
+++ b/nfc/1.0/vts/functional/nfc_hidl_hal_test.cpp
@@ -40,6 +40,8 @@
 /* NCI Commands */
 #define CORE_RESET_CMD \
   { 0x20, 0x00, 0x01, 0x00 }
+#define CORE_RESET_CMD_CONFIG_RESET \
+  { 0x20, 0x00, 0x01, 0x01 }
 #define CORE_CONN_CREATE_CMD \
   { 0x20, 0x04, 0x02, 0x01, 0x00 }
 #define INVALID_COMMAND \
@@ -166,7 +168,7 @@
  * WriteCoreReset:
  * Sends CORE_RESET_CMD
  * Waits for CORE_RESET_RSP
- * Checks the status and the version number
+ * Checks the status, version number and configuration status
  */
 TEST_F(NfcHidlTest, WriteCoreReset) {
   std::vector<uint8_t> cmd = CORE_RESET_CMD;
@@ -178,6 +180,26 @@
   EXPECT_EQ(6ul, last_data_[0].size());
   EXPECT_EQ((int)NfcStatus::OK, last_data_[0][3]);
   EXPECT_GE(VERSION, last_data_[0][4]);
+  EXPECT_EQ(0ul, last_data_[0][5]);
+}
+
+/*
+ * WriteCoreResetConfigReset:
+ * Sends CORE_RESET_CMD_CONFIG_RESET
+ * Waits for CORE_RESET_RSP
+ * Checks the status, version number and configuration status
+ */
+TEST_F(NfcHidlTest, WriteCoreResetConfigReset) {
+  std::vector<uint8_t> cmd = CORE_RESET_CMD_CONFIG_RESET;
+  NfcData data = cmd;
+  EXPECT_EQ(data.size(), nfc_->write(data));
+  // Wait for CORE_RESET_RSP
+  EXPECT_EQ(std::cv_status::no_timeout, wait());
+  EXPECT_EQ(1ul, last_data_.size());
+  EXPECT_EQ(6ul, last_data_[0].size());
+  EXPECT_EQ((int)NfcStatus::OK, last_data_[0][3]);
+  EXPECT_GE(VERSION, last_data_[0][4]);
+  EXPECT_EQ(1ul, last_data_[0][5]);
 }
 
 /*
@@ -273,14 +295,18 @@
     EXPECT_EQ(std::cv_status::no_timeout, wait());
     // Check if the same data was recieved back
     EXPECT_EQ(2ul, last_data_.size());
-    EXPECT_EQ(data.size(), last_data_[0].size());
+
+    /* It is possible that CORE_CONN_CREDITS_NTF is received before data,
+     * Find the order and do further checks depending on that */
+    uint8_t data_index = last_data_[0].size() == data.size() ? 0 : 1;
+    EXPECT_EQ(data.size(), last_data_[data_index].size());
     for (size_t i = 0; i < data.size(); i++) {
-      EXPECT_EQ(data[i], last_data_[0][i]);
+      EXPECT_EQ(data[i], last_data_[data_index][i]);
     }
 
-    EXPECT_EQ(6ul, last_data_[1].size());
+    EXPECT_EQ(6ul, last_data_[!data_index].size());
     // Check if the credit is refilled to 1
-    EXPECT_EQ(1, last_data_[1][5]);
+    EXPECT_EQ(1, last_data_[!data_index][5]);
   }
 }
 
diff --git a/nfc/1.0/vts/functional/vts/testcases/hal/nfc/hidl/target_profiling/AndroidTest.xml b/nfc/1.0/vts/functional/vts/testcases/hal/nfc/hidl/target_profiling/AndroidTest.xml
index 42c7e22..3b570f9 100644
--- a/nfc/1.0/vts/functional/vts/testcases/hal/nfc/hidl/target_profiling/AndroidTest.xml
+++ b/nfc/1.0/vts/functional/vts/testcases/hal/nfc/hidl/target_profiling/AndroidTest.xml
@@ -25,7 +25,7 @@
             _64bit::DATA/nativetest64/nfc_hidl_hal_test/nfc_hidl_hal_test,
             "/>
         <option name="binary-test-type" value="gtest" />
-        <option name="test-timeout" value="20m" />
+        <option name="test-timeout" value="25m" />
     <option name="enable-profiling" value="true" />
     </test>
 </configuration>
diff --git a/power/1.0/default/Power.cpp b/power/1.0/default/Power.cpp
index 6233a14..2ddac0a 100644
--- a/power/1.0/default/Power.cpp
+++ b/power/1.0/default/Power.cpp
@@ -144,24 +144,24 @@
     return Void();
 }
 
-IPower* HIDL_FETCH_IPower(const char* name) {
+IPower* HIDL_FETCH_IPower(const char* /* name */) {
     int ret = 0;
     const hw_module_t* hw_module = NULL;
     power_module_t *power_module;
-    ret = hw_get_module(name, &hw_module);
+    ret = hw_get_module(POWER_HARDWARE_MODULE_ID, &hw_module);
     if (ret == 0 && hw_module->methods->open) {
-        ret = hw_module->methods->open(hw_module, name,
+        ret = hw_module->methods->open(hw_module, POWER_HARDWARE_MODULE_ID,
                 reinterpret_cast<hw_device_t**>(&power_module));
         if (ret == 0) {
             return new Power(power_module);
         }
         else {
-            ALOGE("Passthrough failed to load legacy HAL.");
+            ALOGE("Passthrough failed to load legacy power HAL.");
             return nullptr;
         }
     }
     else {
-        ALOGE ("hw_get_module %s failed: %d", name, ret);
+        ALOGE ("hw_get_module %s failed: %d", POWER_HARDWARE_MODULE_ID, ret);
         return nullptr;
     }
 }
diff --git a/power/1.0/default/service.cpp b/power/1.0/default/service.cpp
index f77ff5b..e8618b8 100644
--- a/power/1.0/default/service.cpp
+++ b/power/1.0/default/service.cpp
@@ -23,5 +23,5 @@
 using android::hardware::defaultPassthroughServiceImplementation;
 
 int main() {
-    return defaultPassthroughServiceImplementation<IPower>("power");
+    return defaultPassthroughServiceImplementation<IPower>();
 }
diff --git a/power/1.0/vts/functional/power_hidl_hal_test.cpp b/power/1.0/vts/functional/power_hidl_hal_test.cpp
index 36bdb0a..3f0ef56 100644
--- a/power/1.0/vts/functional/power_hidl_hal_test.cpp
+++ b/power/1.0/vts/functional/power_hidl_hal_test.cpp
@@ -35,7 +35,7 @@
 class PowerHidlTest : public ::testing::Test {
  public:
   virtual void SetUp() override {
-    power = IPower::getService("power");
+    power = IPower::getService();
     ASSERT_NE(power, nullptr);
   }
 
diff --git a/sensors/1.0/vts/functional/vts/testcases/hal/sensors/hidl/host/SensorsHidlTest.py b/sensors/1.0/vts/functional/vts/testcases/hal/sensors/hidl/host/SensorsHidlTest.py
index db210d9..3c7fbbb 100644
--- a/sensors/1.0/vts/functional/vts/testcases/hal/sensors/hidl/host/SensorsHidlTest.py
+++ b/sensors/1.0/vts/functional/vts/testcases/hal/sensors/hidl/host/SensorsHidlTest.py
@@ -84,7 +84,7 @@
         logging.info("PERMISSION_DENIED: %s", sensors_types.PERMISSION_DENIED)
         logging.info("INVALID_OPERATION: %s", sensors_types.INVALID_OPERATION)
         asserts.assertEqual(sensors_types.OK, 0);
-        asserts.assertEqual(sensors_types.BAD_VALUE, 1);
+        asserts.assertEqual(sensors_types.BAD_VALUE, -22);
 
         logging.info("sensor types:")
         logging.info("SENSOR_TYPE_ACCELEROMETER: %s", sensors_types.SENSOR_TYPE_ACCELEROMETER)
diff --git a/soundtrigger/2.0/vts/functional/vts/testcases/hal/soundtrigger/hidl/target/AndroidTest.xml b/soundtrigger/2.0/vts/functional/vts/testcases/hal/soundtrigger/hidl/target/AndroidTest.xml
index ca8ecdb..9339165 100644
--- a/soundtrigger/2.0/vts/functional/vts/testcases/hal/soundtrigger/hidl/target/AndroidTest.xml
+++ b/soundtrigger/2.0/vts/functional/vts/testcases/hal/soundtrigger/hidl/target/AndroidTest.xml
@@ -25,7 +25,8 @@
             _64bit::DATA/nativetest64/soundtrigger_hidl_hal_test/soundtrigger_hidl_hal_test,
             "/>
         <option name="test-config-path" value="vts/testcases/hal/soundtrigger/hidl/target/HalSoundTriggerHidlTargetBasicTest.config" />
-        <option name="binary-test-type" value="gtest" />
+        <option name="binary-test-type" value="hal_hidl_gtest" />
+        <option name="precondition-file-path-prefix" value="*/lib/hw/sound_trigger.primary." />
         <option name="test-timeout" value="1m" />
     </test>
 </configuration>
diff --git a/soundtrigger/2.0/vts/functional/vts/testcases/hal/soundtrigger/hidl/target_profiling/AndroidTest.xml b/soundtrigger/2.0/vts/functional/vts/testcases/hal/soundtrigger/hidl/target_profiling/AndroidTest.xml
index e95a406..cd95b5f 100644
--- a/soundtrigger/2.0/vts/functional/vts/testcases/hal/soundtrigger/hidl/target_profiling/AndroidTest.xml
+++ b/soundtrigger/2.0/vts/functional/vts/testcases/hal/soundtrigger/hidl/target_profiling/AndroidTest.xml
@@ -19,12 +19,13 @@
     </target_preparer>
     <target_preparer class="com.android.tradefed.targetprep.VtsPythonVirtualenvPreparer" />
     <test class="com.android.tradefed.testtype.VtsMultiDeviceTest">
-        <option name="test-module-name" value="HalSoundTriggerHidlTargetBasicTest" />
+        <option name="test-module-name" value="HalSoundTriggerHidlTargetBasicProfilingTest" />
         <option name="binary-test-sources" value="
             _32bit::DATA/nativetest/soundtrigger_hidl_hal_test/soundtrigger_hidl_hal_test,
             _64bit::DATA/nativetest64/soundtrigger_hidl_hal_test/soundtrigger_hidl_hal_test,
             "/>
-        <option name="binary-test-type" value="gtest" />
+        <option name="binary-test-type" value="hal_hidl_gtest" />
+        <option name="precondition-file-path-prefix" value="*/lib/hw/sound_trigger.primary." />
         <option name="test-timeout" value="1m" />
         <option name="enable-profiling" value="true" />
     </test>
diff --git a/thermal/1.0/vts/functional/thermal_hidl_hal_test.cpp b/thermal/1.0/vts/functional/thermal_hidl_hal_test.cpp
index d922169..3c887c8 100644
--- a/thermal/1.0/vts/functional/thermal_hidl_hal_test.cpp
+++ b/thermal/1.0/vts/functional/thermal_hidl_hal_test.cpp
@@ -50,7 +50,7 @@
 class ThermalHidlTest : public ::testing::Test {
  public:
   virtual void SetUp() override {
-    thermal_ = IThermal::getService(THERMAL_SERVICE_NAME, false);
+    thermal_ = IThermal::getService(THERMAL_SERVICE_NAME);
     ASSERT_NE(thermal_, nullptr);
     baseSize_ = 0;
     names_.clear();
diff --git a/usb/1.0/Android.bp b/usb/1.0/Android.bp
new file mode 100644
index 0000000..8b84a4a
--- /dev/null
+++ b/usb/1.0/Android.bp
@@ -0,0 +1,64 @@
+// This file is autogenerated by hidl-gen. Do not edit manually.
+
+genrule {
+    name: "android.hardware.usb@1.0_genc++",
+    tools: ["hidl-gen"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lc++ -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.usb@1.0",
+    srcs: [
+        "types.hal",
+        "IUsb.hal",
+        "IUsbCallback.hal",
+    ],
+    out: [
+        "android/hardware/usb/1.0/types.cpp",
+        "android/hardware/usb/1.0/UsbAll.cpp",
+        "android/hardware/usb/1.0/UsbCallbackAll.cpp",
+    ],
+}
+
+genrule {
+    name: "android.hardware.usb@1.0_genc++_headers",
+    tools: ["hidl-gen"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lc++ -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.usb@1.0",
+    srcs: [
+        "types.hal",
+        "IUsb.hal",
+        "IUsbCallback.hal",
+    ],
+    out: [
+        "android/hardware/usb/1.0/types.h",
+        "android/hardware/usb/1.0/IUsb.h",
+        "android/hardware/usb/1.0/IHwUsb.h",
+        "android/hardware/usb/1.0/BnHwUsb.h",
+        "android/hardware/usb/1.0/BpHwUsb.h",
+        "android/hardware/usb/1.0/BsUsb.h",
+        "android/hardware/usb/1.0/IUsbCallback.h",
+        "android/hardware/usb/1.0/IHwUsbCallback.h",
+        "android/hardware/usb/1.0/BnHwUsbCallback.h",
+        "android/hardware/usb/1.0/BpHwUsbCallback.h",
+        "android/hardware/usb/1.0/BsUsbCallback.h",
+    ],
+}
+
+cc_library_shared {
+    name: "android.hardware.usb@1.0",
+    generated_sources: ["android.hardware.usb@1.0_genc++"],
+    generated_headers: ["android.hardware.usb@1.0_genc++_headers"],
+    export_generated_headers: ["android.hardware.usb@1.0_genc++_headers"],
+    shared_libs: [
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "liblog",
+        "libutils",
+        "libcutils",
+        "android.hidl.base@1.0",
+    ],
+    export_shared_lib_headers: [
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "libutils",
+        "android.hidl.base@1.0",
+    ],
+}
diff --git a/usb/1.0/Android.mk b/usb/1.0/Android.mk
new file mode 100644
index 0000000..0eded5b
--- /dev/null
+++ b/usb/1.0/Android.mk
@@ -0,0 +1,427 @@
+# This file is autogenerated by hidl-gen. Do not edit manually.
+
+LOCAL_PATH := $(call my-dir)
+
+################################################################################
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := android.hardware.usb@1.0-java
+LOCAL_MODULE_CLASS := JAVA_LIBRARIES
+
+intermediates := $(local-generated-sources-dir)
+
+HIDL := $(HOST_OUT_EXECUTABLES)/hidl-gen$(HOST_EXECUTABLE_SUFFIX)
+
+LOCAL_JAVA_LIBRARIES := \
+    android.hidl.base@1.0-java \
+
+
+#
+# Build types.hal (PortDataRole)
+#
+GEN := $(intermediates)/android/hardware/usb/V1_0/PortDataRole.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.usb@1.0::types.PortDataRole
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (PortMode)
+#
+GEN := $(intermediates)/android/hardware/usb/V1_0/PortMode.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.usb@1.0::types.PortMode
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (PortPowerRole)
+#
+GEN := $(intermediates)/android/hardware/usb/V1_0/PortPowerRole.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.usb@1.0::types.PortPowerRole
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (PortRole)
+#
+GEN := $(intermediates)/android/hardware/usb/V1_0/PortRole.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.usb@1.0::types.PortRole
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (PortRoleType)
+#
+GEN := $(intermediates)/android/hardware/usb/V1_0/PortRoleType.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.usb@1.0::types.PortRoleType
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (PortStatus)
+#
+GEN := $(intermediates)/android/hardware/usb/V1_0/PortStatus.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.usb@1.0::types.PortStatus
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (Status)
+#
+GEN := $(intermediates)/android/hardware/usb/V1_0/Status.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.usb@1.0::types.Status
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build IUsb.hal
+#
+GEN := $(intermediates)/android/hardware/usb/V1_0/IUsb.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/IUsb.hal
+$(GEN): PRIVATE_DEPS += $(LOCAL_PATH)/IUsbCallback.hal
+$(GEN): $(LOCAL_PATH)/IUsbCallback.hal
+$(GEN): PRIVATE_DEPS += $(LOCAL_PATH)/types.hal
+$(GEN): $(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.usb@1.0::IUsb
+
+$(GEN): $(LOCAL_PATH)/IUsb.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build IUsbCallback.hal
+#
+GEN := $(intermediates)/android/hardware/usb/V1_0/IUsbCallback.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/IUsbCallback.hal
+$(GEN): PRIVATE_DEPS += $(LOCAL_PATH)/types.hal
+$(GEN): $(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.usb@1.0::IUsbCallback
+
+$(GEN): $(LOCAL_PATH)/IUsbCallback.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+include $(BUILD_JAVA_LIBRARY)
+
+
+################################################################################
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := android.hardware.usb@1.0-java-static
+LOCAL_MODULE_CLASS := JAVA_LIBRARIES
+
+intermediates := $(local-generated-sources-dir)
+
+HIDL := $(HOST_OUT_EXECUTABLES)/hidl-gen$(HOST_EXECUTABLE_SUFFIX)
+
+LOCAL_STATIC_JAVA_LIBRARIES := \
+    android.hidl.base@1.0-java-static \
+
+
+#
+# Build types.hal (PortDataRole)
+#
+GEN := $(intermediates)/android/hardware/usb/V1_0/PortDataRole.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.usb@1.0::types.PortDataRole
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (PortMode)
+#
+GEN := $(intermediates)/android/hardware/usb/V1_0/PortMode.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.usb@1.0::types.PortMode
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (PortPowerRole)
+#
+GEN := $(intermediates)/android/hardware/usb/V1_0/PortPowerRole.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.usb@1.0::types.PortPowerRole
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (PortRole)
+#
+GEN := $(intermediates)/android/hardware/usb/V1_0/PortRole.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.usb@1.0::types.PortRole
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (PortRoleType)
+#
+GEN := $(intermediates)/android/hardware/usb/V1_0/PortRoleType.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.usb@1.0::types.PortRoleType
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (PortStatus)
+#
+GEN := $(intermediates)/android/hardware/usb/V1_0/PortStatus.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.usb@1.0::types.PortStatus
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (Status)
+#
+GEN := $(intermediates)/android/hardware/usb/V1_0/Status.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.usb@1.0::types.Status
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build IUsb.hal
+#
+GEN := $(intermediates)/android/hardware/usb/V1_0/IUsb.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/IUsb.hal
+$(GEN): PRIVATE_DEPS += $(LOCAL_PATH)/IUsbCallback.hal
+$(GEN): $(LOCAL_PATH)/IUsbCallback.hal
+$(GEN): PRIVATE_DEPS += $(LOCAL_PATH)/types.hal
+$(GEN): $(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.usb@1.0::IUsb
+
+$(GEN): $(LOCAL_PATH)/IUsb.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build IUsbCallback.hal
+#
+GEN := $(intermediates)/android/hardware/usb/V1_0/IUsbCallback.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/IUsbCallback.hal
+$(GEN): PRIVATE_DEPS += $(LOCAL_PATH)/types.hal
+$(GEN): $(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.usb@1.0::IUsbCallback
+
+$(GEN): $(LOCAL_PATH)/IUsbCallback.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+include $(BUILD_STATIC_JAVA_LIBRARY)
+
+
+################################################################################
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := android.hardware.usb@1.0-java-constants
+LOCAL_MODULE_CLASS := JAVA_LIBRARIES
+
+intermediates := $(local-generated-sources-dir)
+
+HIDL := $(HOST_OUT_EXECUTABLES)/hidl-gen$(HOST_EXECUTABLE_SUFFIX)
+#
+GEN := $(intermediates)/android/hardware/usb/V1_0/Constants.java
+$(GEN): $(HIDL)
+$(GEN): $(LOCAL_PATH)/types.hal
+$(GEN): $(LOCAL_PATH)/IUsb.hal
+$(GEN): $(LOCAL_PATH)/IUsbCallback.hal
+
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava-constants \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.usb@1.0
+
+$(GEN):
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+# Avoid dependency cycle of framework.jar -> this-library -> framework.jar
+LOCAL_NO_STANDARD_LIBRARIES := true
+LOCAL_JAVA_LIBRARIES := core-oj
+
+include $(BUILD_STATIC_JAVA_LIBRARY)
+
+
+
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/usb/1.0/IUsb.hal b/usb/1.0/IUsb.hal
new file mode 100644
index 0000000..965326a
--- /dev/null
+++ b/usb/1.0/IUsb.hal
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.usb@1.0;
+
+import IUsbCallback;
+
+interface IUsb {
+    /*
+     * This function is used to change the port role of a specific port.
+     * For example, when PD_SWAP or PR_SWAP is supported.
+     * This is function is asynchronous. The status of the role switch
+     * will be informed through IUsbCallback object's notifyPortStatusChange
+     * method.
+     *
+     * @param portName name of the port for which the role has to be changed
+     * @param role the new port role.
+     */
+    oneway switchRole(string portName, PortRole role);
+
+    /*
+     * This function is used to register a callback function which is
+     * called by the HAL whenever there is a change in the port state.
+     * i.e. DATA_ROLE, POWER_ROLE or MODE.
+     *
+     * Also the same callback object would be called to inform the caller
+     * of the roleSwitch status.
+     *
+     * @param callback IUsbCallback object used to convey status to the
+     * userspace.
+     */
+    oneway setCallback(IUsbCallback callback);
+
+    /*
+     * This functions is used to request the hal for the current status
+     * status of the Type-C ports. This method is async/oneway. The result of the
+     * query would be sent through the IUsbCallback object's notifyRoleSwitchStatus
+     * to the caller. This api would would let the caller know of the number
+     * of type-c ports that are present and their connection status through the
+     * PortStatus type.
+     */
+    oneway queryPortStatus();
+};
+
diff --git a/usb/1.0/IUsbCallback.hal b/usb/1.0/IUsbCallback.hal
new file mode 100644
index 0000000..b665ba3
--- /dev/null
+++ b/usb/1.0/IUsbCallback.hal
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.usb@1.0;
+
+/*
+ * Callback object used for all the IUsb async methods which expects a result.
+ * Caller is expected to register the callback object using setCallback method
+ * to receive updates on the PortStatus.
+ */
+interface IUsbCallback {
+    /*
+     * Used to convey the current port status to the caller.
+     * Called either when PortState changes due to the port partner (or)
+     * when caller requested for the PortStatus update through queryPortStatus.
+     *
+     * @param currentPortStatus vector object of current status of all the
+     * typeC ports in the device.
+     * @param retval SUCCESS when query was done successfully.
+     * ERROR otherwise.
+     */
+    oneway notifyPortStatusChange(vec<PortStatus> currentPortStatus, Status retval);
+
+    /*
+     * Used to notify the result of the switchRole call to the caller.
+     *
+     * @param portName name of the port for which the roleswap is requested.
+     * @param newRole the new role requested by the caller.
+     * @param retval SUCCESS if the role switch succeeded. FAILURE otherwise.
+     */
+    oneway notifyRoleSwitchStatus(string portName, PortRole newRole, Status retval);
+};
diff --git a/usb/1.0/default/Android.mk b/usb/1.0/default/Android.mk
new file mode 100644
index 0000000..09d7ce7
--- /dev/null
+++ b/usb/1.0/default/Android.mk
@@ -0,0 +1,21 @@
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE_RELATIVE_PATH := hw
+LOCAL_MODULE := android.hardware.usb@1.0-service
+LOCAL_INIT_RC := android.hardware.usb@1.0-service.rc
+LOCAL_SRC_FILES := \
+    service.cpp \
+    Usb.cpp
+
+LOCAL_SHARED_LIBRARIES := \
+    libcutils \
+    libhidlbase \
+    libhidltransport \
+    liblog \
+    libhwbinder \
+    libutils \
+    libhardware \
+    android.hardware.usb@1.0 \
+
+include $(BUILD_EXECUTABLE)
diff --git a/usb/1.0/default/Usb.cpp b/usb/1.0/default/Usb.cpp
new file mode 100644
index 0000000..f46ff66
--- /dev/null
+++ b/usb/1.0/default/Usb.cpp
@@ -0,0 +1,428 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <dirent.h>
+#include <iostream>
+#include <fstream>
+#include <pthread.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <cutils/uevent.h>
+#include <sys/epoll.h>
+#include <utils/Errors.h>
+#include <utils/StrongPointer.h>
+
+#include "Usb.h"
+
+namespace android {
+namespace hardware {
+namespace usb {
+namespace V1_0 {
+namespace implementation {
+
+int32_t readFile(std::string filename, std::string& contents) {
+    std::ifstream file(filename);
+
+    if (file.is_open()) {
+        getline(file, contents);
+        file.close();
+        return 0;
+    }
+    return -1;
+}
+
+std::string appendRoleNodeHelper(const std::string portName, PortRoleType type) {
+    std::string node("/sys/class/dual_role_usb/" + portName);
+
+    switch(type) {
+        case PortRoleType::DATA_ROLE:
+            return node + "/data_role";
+        case PortRoleType::POWER_ROLE:
+            return node + "/power_role";
+        default:
+            return node + "/mode";
+    }
+}
+
+std::string convertRoletoString(PortRole role) {
+    if (role.type == PortRoleType::POWER_ROLE) {
+        if (role.role == static_cast<uint32_t> (PortPowerRole::SOURCE))
+            return "source";
+        else if (role.role ==  static_cast<uint32_t> (PortPowerRole::SINK))
+            return "sink";
+    } else if (role.type == PortRoleType::DATA_ROLE) {
+        if (role.role == static_cast<uint32_t> (PortDataRole::HOST))
+            return "host";
+        if (role.role == static_cast<uint32_t> (PortDataRole::DEVICE))
+            return "device";
+    } else if (role.type == PortRoleType::MODE) {
+        if (role.role == static_cast<uint32_t> (PortMode::UFP))
+            return "ufp";
+        if (role.role == static_cast<uint32_t> (PortMode::DFP))
+            return "dfp";
+    }
+    return "none";
+}
+
+Return<void> Usb::switchRole(const hidl_string& portName,
+        const PortRole& newRole) {
+    std::string filename = appendRoleNodeHelper(std::string(portName.c_str()),
+        newRole.type);
+    std::ofstream file(filename);
+    std::string written;
+
+    ALOGI("filename write: %s role:%d", filename.c_str(), newRole.role);
+
+    if (file.is_open()) {
+        file << convertRoletoString(newRole).c_str();
+        file.close();
+        if (!readFile(filename, written)) {
+            ALOGI("written: %s", written.c_str());
+            if (written == convertRoletoString(newRole)) {
+                ALOGI("Role switch successfull");
+                Return<void> ret =
+                    mCallback->notifyRoleSwitchStatus(portName, newRole,
+                    Status::SUCCESS);
+                if (!ret.isOk())
+                    ALOGE("RoleSwitchStatus error %s",
+                        ret.description().c_str());
+            }
+        }
+    }
+
+    Return<void> ret = mCallback->notifyRoleSwitchStatus(portName, newRole, Status::ERROR);
+    if (!ret.isOk())
+        ALOGE("RoleSwitchStatus error %s", ret.description().c_str());
+
+    return Void();
+}
+
+Status getCurrentRoleHelper(std::string portName,
+        PortRoleType type, uint32_t &currentRole)  {
+    std::string filename;
+    std::string roleName;
+
+    if (type == PortRoleType::POWER_ROLE) {
+        filename = "/sys/class/dual_role_usb/" +
+            portName + "/power_role";
+        currentRole = static_cast<uint32_t>(PortPowerRole::NONE);
+    } else if (type == PortRoleType::DATA_ROLE) {
+        filename = "/sys/class/dual_role_usb/" +
+            portName + "/data_role";
+        currentRole = static_cast<uint32_t> (PortDataRole::NONE);
+    } else if (type == PortRoleType::MODE) {
+        filename = "/sys/class/dual_role_usb/" +
+            portName + "/mode";
+        currentRole = static_cast<uint32_t> (PortMode::NONE);
+    }
+
+    if (readFile(filename, roleName)) {
+        ALOGE("getCurrentRole: Failed to open filesystem node");
+        return Status::ERROR;
+    }
+
+    if (roleName == "dfp")
+        currentRole = static_cast<uint32_t> (PortMode::DFP);
+    else if (roleName == "ufp")
+        currentRole = static_cast<uint32_t> (PortMode::UFP);
+    else if (roleName == "source")
+        currentRole = static_cast<uint32_t> (PortPowerRole::SOURCE);
+    else if (roleName == "sink")
+        currentRole = static_cast<uint32_t> (PortPowerRole::SINK);
+    else if (roleName == "host")
+        currentRole = static_cast<uint32_t> (PortDataRole::HOST);
+    else if (roleName == "device")
+        currentRole = static_cast<uint32_t> (PortDataRole::DEVICE);
+    else if (roleName != "none") {
+         /* case for none has already been addressed.
+          * so we check if the role isnt none.
+          */
+        return Status::UNRECOGNIZED_ROLE;
+    }
+    return Status::SUCCESS;
+}
+
+Status getTypeCPortNamesHelper(std::vector<std::string>& names) {
+    DIR *dp;
+
+    dp = opendir("/sys/class/dual_role_usb");
+    if (dp != NULL)
+    {
+rescan:
+        int32_t ports = 0;
+        int32_t current = 0;
+        struct dirent *ep;
+
+        while ((ep = readdir (dp))) {
+            if (ep->d_type == DT_LNK) {
+                ports++;
+            }
+        }
+        names.resize(ports);
+        rewinddir(dp);
+
+        while ((ep = readdir (dp))) {
+            /* Check to see if new ports were added since the first pass. */
+            if (current >= ports) {
+               rewinddir(dp);
+               goto rescan;
+            }
+
+            if (ep->d_type == DT_LNK) {
+                names[current++] = ep->d_name;
+            }
+        }
+
+        closedir (dp);
+        return Status::SUCCESS;
+    }
+
+    ALOGE("Failed to open /sys/class/dual_role_usb");
+    return Status::ERROR;
+}
+
+bool canSwitchRoleHelper(const std::string portName, PortRoleType type)  {
+    std::string filename = appendRoleNodeHelper(portName, type);
+    std::ofstream file(filename);
+
+    if (file.is_open()) {
+        file.close();
+        return true;
+    }
+    return false;
+}
+
+Status getPortModeHelper(const std::string portName, PortMode& portMode)  {
+    std::string filename = "/sys/class/dual_role_usb/" +
+    std::string(portName.c_str()) + "/supported_modes";
+    std::string modes;
+
+    if (readFile(filename, modes)) {
+        ALOGE("getSupportedRoles: Failed to open filesystem node");
+        return Status::ERROR;
+    }
+
+    if (modes == "ufp dfp")
+        portMode = PortMode::DRP;
+    else  if (modes == "ufp")
+        portMode = PortMode::UFP;
+    else if  (modes == "dfp")
+        portMode = PortMode::DFP;
+    else
+        return Status::UNRECOGNIZED_ROLE;
+
+        return Status::SUCCESS;
+}
+
+Status getPortStatusHelper (hidl_vec<PortStatus>& currentPortStatus) {
+    std::vector<std::string> names;
+    Status result = getTypeCPortNamesHelper(names);
+
+    if (result == Status::SUCCESS) {
+        currentPortStatus.resize(names.size());
+        for(std::vector<std::string>::size_type i = 0; i != names.size(); i++) {
+            ALOGI("%s", names[i].c_str());
+            currentPortStatus[i].portName = names[i];
+
+            uint32_t currentRole;
+            if (getCurrentRoleHelper(names[i], PortRoleType::POWER_ROLE,
+                    currentRole) == Status::SUCCESS) {
+                currentPortStatus[i].currentPowerRole =
+                static_cast<PortPowerRole> (currentRole);
+            } else {
+                ALOGE("Error while retreiving portNames");
+                goto done;
+            }
+
+            if (getCurrentRoleHelper(names[i],
+                    PortRoleType::DATA_ROLE, currentRole) == Status::SUCCESS) {
+                currentPortStatus[i].currentDataRole =
+                        static_cast<PortDataRole> (currentRole);
+            } else {
+                ALOGE("Error while retreiving current port role");
+                goto done;
+            }
+
+            if (getCurrentRoleHelper(names[i], PortRoleType::MODE,
+                    currentRole) == Status::SUCCESS) {
+                currentPortStatus[i].currentMode =
+                    static_cast<PortMode> (currentRole);
+            } else {
+                ALOGE("Error while retreiving current data role");
+                goto done;
+            }
+
+            currentPortStatus[i].canChangeMode =
+                canSwitchRoleHelper(names[i], PortRoleType::MODE);
+            currentPortStatus[i].canChangeDataRole =
+                canSwitchRoleHelper(names[i], PortRoleType::DATA_ROLE);
+            currentPortStatus[i].canChangePowerRole =
+                canSwitchRoleHelper(names[i], PortRoleType::POWER_ROLE);
+
+            ALOGI("canChangeMode: %d canChagedata: %d canChangePower:%d",
+                currentPortStatus[i].canChangeMode,
+                currentPortStatus[i].canChangeDataRole,
+                currentPortStatus[i].canChangePowerRole);
+
+            if (getPortModeHelper(names[i], currentPortStatus[i].supportedModes)
+                  != Status::SUCCESS) {
+                ALOGE("Error while retrieving port modes");
+                goto done;
+            }
+        }
+        return Status::SUCCESS;
+    }
+done:
+    return Status::ERROR;
+}
+
+Return<void> Usb::queryPortStatus() {
+    hidl_vec<PortStatus> currentPortStatus;
+    Status status;
+
+    status = getPortStatusHelper(currentPortStatus);
+    Return<void> ret = mCallback->notifyPortStatusChange(currentPortStatus,
+       status);
+    if (!ret.isOk())
+        ALOGE("queryPortStatus error %s", ret.description().c_str());
+
+    return Void();
+}
+struct data {
+    int uevent_fd;
+    android::hardware::usb::V1_0::implementation::Usb *usb;
+};
+
+static void uevent_event(uint32_t /*epevents*/, struct data *payload) {
+    char msg[UEVENT_MSG_LEN + 2];
+    char *cp;
+    int n;
+
+    n = uevent_kernel_multicast_recv(payload->uevent_fd, msg, UEVENT_MSG_LEN);
+    if (n <= 0)
+        return;
+    if (n >= UEVENT_MSG_LEN)   /* overflow -- discard */
+        return;
+
+    msg[n] = '\0';
+    msg[n + 1] = '\0';
+    cp = msg;
+
+    while (*cp) {
+        if (!strcmp(cp, "SUBSYSTEM=dual_role_usb")) {
+            ALOGE("uevent received %s", cp);
+            if (payload->usb->mCallback != NULL) {
+                hidl_vec<PortStatus> currentPortStatus;
+                Status status = getPortStatusHelper(currentPortStatus);
+                Return<void> ret =
+                    payload->usb->mCallback->notifyPortStatusChange(currentPortStatus, status);
+                if (!ret.isOk())
+                    ALOGE("error %s", ret.description().c_str());
+            }
+            break;
+        }
+        /* advance to after the next \0 */
+        while (*cp++);
+    }
+}
+
+void* work(void* param) {
+    int epoll_fd, uevent_fd;
+    struct epoll_event ev;
+    int nevents = 0;
+    struct data payload;
+
+    ALOGE("creating thread");
+
+    uevent_fd = uevent_open_socket(64*1024, true);
+
+    if (uevent_fd < 0) {
+        ALOGE("uevent_init: uevent_open_socket failed\n");
+        return NULL;
+    }
+
+    payload.uevent_fd = uevent_fd;
+    payload.usb = (android::hardware::usb::V1_0::implementation::Usb *)param;
+
+    fcntl(uevent_fd, F_SETFL, O_NONBLOCK);
+
+    ev.events = EPOLLIN;
+    ev.data.ptr = (void *)uevent_event;
+
+    epoll_fd = epoll_create(64);
+    if (epoll_fd == -1) {
+        ALOGE("epoll_create failed; errno=%d", errno);
+        goto error;
+    }
+
+    if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, uevent_fd, &ev) == -1) {
+        ALOGE("epoll_ctl failed; errno=%d", errno);
+        goto error;
+    }
+
+    while (1) {
+        struct epoll_event events[64];
+
+        nevents = epoll_wait(epoll_fd, events, 64, -1);
+        if (nevents == -1) {
+            if (errno == EINTR)
+                continue;
+            ALOGE("usb epoll_wait failed; errno=%d", errno);
+            break;
+        }
+
+        for (int n = 0; n < nevents; ++n) {
+            if (events[n].data.ptr)
+                (*(void (*)(int, struct data *payload))events[n].data.ptr)
+                    (events[n].events, &payload);
+        }
+    }
+
+error:
+    close(uevent_fd);
+
+    if (epoll_fd >= 0)
+        close(epoll_fd);
+
+    return NULL;
+}
+
+
+Return<void> Usb::setCallback(const sp<IUsbCallback>& callback) {
+
+    if (mCallback != NULL) {
+        ALOGE("Callback already registered");
+        return Void();
+    }
+
+    mCallback = callback;
+    ALOGI("registering callback");
+
+    if (pthread_create(&mPoll, NULL, work, this)) {
+        ALOGE("pthread creation failed %d", errno);
+        mCallback = NULL;
+        return Void();
+    }
+
+    return Void();
+}
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace usb
+}  // namespace hardware
+}  // namespace android
diff --git a/usb/1.0/default/Usb.h b/usb/1.0/default/Usb.h
new file mode 100644
index 0000000..cf418f4
--- /dev/null
+++ b/usb/1.0/default/Usb.h
@@ -0,0 +1,50 @@
+#ifndef ANDROID_HARDWARE_USB_V1_0_USB_H
+#define ANDROID_HARDWARE_USB_V1_0_USB_H
+
+#include <android/hardware/usb/1.0/IUsb.h>
+#include <hidl/MQDescriptor.h>
+#include <hidl/Status.h>
+#include <utils/Log.h>
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#endif
+
+#define LOG_TAG "android.hardware.usb@1.0-service"
+#define UEVENT_MSG_LEN 2048
+
+namespace android {
+namespace hardware {
+namespace usb {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::usb::V1_0::IUsb;
+using ::android::hardware::usb::V1_0::IUsbCallback;
+using ::android::hardware::usb::V1_0::PortRole;
+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 Usb : public IUsb {
+    Return<void> switchRole(const hidl_string& portName, const PortRole& role) override;
+    Return<void> setCallback(const sp<IUsbCallback>& callback) override;
+    Return<void> queryPortStatus() override;
+
+    sp<IUsbCallback> mCallback;
+    private:
+        pthread_t mPoll;
+};
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace usb
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_USB_V1_0_USB_H
diff --git a/usb/1.0/default/android.hardware.usb@1.0-service.rc b/usb/1.0/default/android.hardware.usb@1.0-service.rc
new file mode 100644
index 0000000..77dfc93
--- /dev/null
+++ b/usb/1.0/default/android.hardware.usb@1.0-service.rc
@@ -0,0 +1,4 @@
+service usb-hal-1-0 /system/bin/hw/android.hardware.usb@1.0-service
+    class hal
+    user system
+    group system
diff --git a/usb/1.0/default/service.cpp b/usb/1.0/default/service.cpp
new file mode 100644
index 0000000..b4db241
--- /dev/null
+++ b/usb/1.0/default/service.cpp
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <hidl/HidlTransportSupport.h>
+#include "Usb.h"
+
+using android::sp;
+
+// libhwbinder:
+using android::hardware::configureRpcThreadpool;
+using android::hardware::joinRpcThreadpool;
+
+// Generated HIDL files
+using android::hardware::usb::V1_0::IUsb;
+using android::hardware::usb::V1_0::implementation::Usb;
+
+int main() {
+    const char instance[] = "usb_hal";
+
+    android::sp<IUsb> service = new Usb();
+
+    configureRpcThreadpool(1, true /*callerWillJoin*/);
+    service->registerAsService(instance);
+
+    ALOGI("USB HAL Ready.");
+    joinRpcThreadpool();
+}
diff --git a/usb/1.0/types.hal b/usb/1.0/types.hal
new file mode 100644
index 0000000..17cd8c7
--- /dev/null
+++ b/usb/1.0/types.hal
@@ -0,0 +1,214 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.hardware.usb@1.0;
+
+
+enum Status : uint32_t {
+    SUCCESS = 0,
+
+    /*
+     * error value when the HAL operation fails for reasons not listed here.
+     */
+    ERROR = 1,
+
+    /*
+     * error value returned when input argument is invalid.
+     */
+    INVALID_ARGUMENT = 2,
+
+    /*
+     * error value returned when role string is unrecognized.
+     */
+    UNRECOGNIZED_ROLE = 3,
+};
+
+/*
+ * Denotes the Port role type.
+ * Passed as an argument for functions used to query or change port roles.
+ */
+enum PortRoleType : uint32_t {
+    /*
+     * Denotes the data role of the port.
+     * The port can either be a "host" or a "device" for data.
+     * This maps to the PortDataRole enum.
+     */
+    DATA_ROLE = 0,
+
+    /*
+     * Denotes the power role of the port.
+     * The port can either be a "source" or "sink" for power.
+     * This maps to PortPowerRole enum.
+     */
+    POWER_ROLE = 1,
+
+    /*
+     * USB ports can be a pure DFP port which can only act
+     * as a host. A UFP port which can only act as a device.
+     * Or a dual role ports which can either can as a host or
+     * a device. This property is used to mention them.
+     */
+    MODE = 2,
+};
+
+@export
+enum PortDataRole : uint32_t {
+    /*
+     * Indicates that the port does not have a data role.
+     * In case of DRP, the current data role of the port is only resolved
+     * when the type-c handshake happens.
+     */
+    NONE = 0,
+
+    /*
+     * Indicates that the port is acting as a host for data.
+     */
+    HOST = 1,
+
+    /*
+     * Indicated that the port is acting as a device for data.
+     */
+    DEVICE = 2,
+
+    NUM_DATA_ROLES = 3,
+};
+
+@export
+enum PortPowerRole : uint32_t {
+    /*
+     * Indicates that the port does not have a power role.
+     * In case of DRP, the current power role of the port is only resolved
+     * when the type-c handshake happens.
+     */
+    NONE = 0,
+
+    /*
+     * Indicates that the port is supplying power to the other port.
+     */
+    SOURCE = 1,
+
+    /*
+     * Indicates that the port is sinking power from the other port.
+     */
+    SINK = 2,
+
+    NUM_POWER_ROLES = 3,
+};
+
+@export
+enum PortMode : uint32_t {
+    /*
+     * Indicates that the port does not have a mode.
+     * In case of DRP, the current mode of the port is only resolved
+     * when the type-c handshake happens.
+     */
+    NONE = 0,
+    /*
+     * Indicates that port can only act as device for data and sink for power.
+     */
+    UFP = 1,
+
+    /*
+     * Indicates the port can only act as host for data and source for power.
+     */
+    DFP = 2,
+
+    /*
+     * Indicates can either act as UFP or DFP at a given point of time.
+     */
+    DRP = 3,
+
+    NUM_MODES = 4,
+};
+
+/*
+ * Used as a container to send port role information.
+ */
+struct PortRole {
+    /*
+     * Indicates the type of Port Role.
+     * Maps to the PortRoleType enum.
+     */
+    PortRoleType type;
+
+    /*
+     * when type is HAL_USB_DATA_ROLE pass values from enum PortDataRole.
+     * when type is HAL_USB_POWER_ROLE pass values from enum PortPowerRole.
+     * when type is HAL_USB_MODE pass values from enum PortMode.
+     */
+    uint32_t role;
+};
+
+/*
+ * Used as the container to report data back to the caller.
+ * Represents the current connection status of a single USB port.
+ */
+struct PortStatus {
+     /*
+      * Name of the port.
+      * Used as the port's id by the caller.
+      */
+     string portName;
+
+     /*
+      * Data role of the port.
+      */
+     PortDataRole currentDataRole;
+
+     /*
+      * Power Role of thte port.
+      */
+     PortPowerRole currentPowerRole;
+
+     /*
+      * Mode in which the port is connected.
+      * Can be UFP or DFP.
+      */
+     PortMode currentMode;
+
+     /*
+      * True indicates that the port's mode can
+      * be changed. False otherwise.
+      */
+     bool canChangeMode;
+
+     /*
+      * True indicates that the port's data role
+      * can be changed. False otherwise.
+      * For example, true if Type-C PD PD_SWAP
+      * is supported.
+      */
+     bool canChangeDataRole;
+
+     /*
+      * True indicates that the port's power role
+      * can be changed. False otherwise.
+      * For example, true if Type-C PD PR_SWAP
+      * is supported.
+      */
+     bool canChangePowerRole;
+
+     /*
+      * Identifies the type of the local port.
+      *
+      * UFP - Indicates that port can only act as device for
+      *       data and sink for power.
+      * DFP - Indicates the port can only act as host for data
+      *       and source for power.
+      * DRP - Indicates can either act as UFP or DFP at a
+      *       given point of time.
+      */
+      PortMode supportedModes;
+};
diff --git a/usb/Android.bp b/usb/Android.bp
new file mode 100644
index 0000000..bbb3e4b
--- /dev/null
+++ b/usb/Android.bp
@@ -0,0 +1,4 @@
+// This is an autogenerated file, do not edit.
+subdirs = [
+    "1.0",
+]
diff --git a/vehicle/2.0/types.hal b/vehicle/2.0/types.hal
index a9b706d..aaaa06f 100644
--- a/vehicle/2.0/types.hal
+++ b/vehicle/2.0/types.hal
@@ -964,6 +964,7 @@
      *
      * @change_mode VehiclePropertyChangeMode:ON_CHANGE
      * @access VehiclePropertyAccess:READ_WRITE
+     */
     AUDIO_PARAMETERS = (
         0x907
         | VehiclePropertyGroup:SYSTEM
diff --git a/vehicle/2.0/vts/functional/vts/testcases/hal/vehicle/hidl/host/VehicleHidlTest.py b/vehicle/2.0/vts/functional/vts/testcases/hal/vehicle/hidl/host/VehicleHidlTest.py
index cd52abf..8d786e7 100644
--- a/vehicle/2.0/vts/functional/vts/testcases/hal/vehicle/hidl/host/VehicleHidlTest.py
+++ b/vehicle/2.0/vts/functional/vts/testcases/hal/vehicle/hidl/host/VehicleHidlTest.py
@@ -130,5 +130,39 @@
         if isFreezeSupported:
             checkFreezeFrameRead()
 
+    def createVehiclePropValue(self, propId):
+        value = {
+            "int32Values" : [],
+            "floatValues" : [],
+            "int64Values" : [],
+            "bytes": [],
+            "stringValue": ""
+        }
+        propValue = {
+            "prop": propId,
+            "timestamp": 0,
+            "areaId": 0,
+            "value": value
+        }
+        return self.vtypes.Py2Pb("VehiclePropValue", propValue)
+
+    def testDrivingStatus(self):
+        """Checks that DRIVING_STATUS property returns correct result."""
+        request = self.createVehiclePropValue(self.vtypes.DRIVING_STATUS)
+        logging.info("Driving status request: %s", request)
+        response = self.vehicle.get(request)
+        logging.info("Driving status response: %s", response)
+        status = response[0]
+        asserts.assertEqual(self.vtypes.OK, status)
+        propValue = response[1]
+        assertEqual(1, len(propValue.value.int32Values))
+        drivingStatus = propValue.value.int32Values[0]
+
+        allStatuses = (self.vtypes.UNRESTRICTED | self.vtypes.NO_VIDEO
+               | self.vtypes.NO_KEYBOARD_INPUT | self.vtypes.NO_VOICE_INPUT
+               | self.vtypes.NO_CONFIG | self.vtypes.LIMIT_MESSAGE_LEN)
+
+        assertEqual(allStatuses, allStatuses | drivingStatus)
+
 if __name__ == "__main__":
     test_runner.main()
diff --git a/vibrator/1.0/vts/functional/vibrator_hidl_hal_test.cpp b/vibrator/1.0/vts/functional/vibrator_hidl_hal_test.cpp
index 782a763..435b002 100644
--- a/vibrator/1.0/vts/functional/vibrator_hidl_hal_test.cpp
+++ b/vibrator/1.0/vts/functional/vibrator_hidl_hal_test.cpp
@@ -32,7 +32,7 @@
 class VibratorHidlTest : public ::testing::Test {
  public:
   virtual void SetUp() override {
-    vibrator = IVibrator::getService(false);
+    vibrator = IVibrator::getService();
     ASSERT_NE(vibrator, nullptr);
   }
 
diff --git a/vr/1.0/vts/functional/vr_hidl_hal_test.cpp b/vr/1.0/vts/functional/vr_hidl_hal_test.cpp
index 85ecbdc..7e85337 100644
--- a/vr/1.0/vts/functional/vr_hidl_hal_test.cpp
+++ b/vr/1.0/vts/functional/vr_hidl_hal_test.cpp
@@ -32,8 +32,7 @@
 class VrHidlTest : public ::testing::Test {
  public:
   void SetUp() override {
-    // currently test passthrough mode only
-    vr = IVr::getService(VR_SERVICE_NAME, true);
+    vr = IVr::getService(VR_SERVICE_NAME);
     ASSERT_NE(vr, nullptr);
     ASSERT_TRUE(!vr->isRemote());
   }
diff --git a/vr/1.0/vts/functional/vts/testcases/hal/vr/hidl/target/AndroidTest.xml b/vr/1.0/vts/functional/vts/testcases/hal/vr/hidl/target/AndroidTest.xml
index aa5a48f..8c7a9b7 100644
--- a/vr/1.0/vts/functional/vts/testcases/hal/vr/hidl/target/AndroidTest.xml
+++ b/vr/1.0/vts/functional/vts/testcases/hal/vr/hidl/target/AndroidTest.xml
@@ -25,9 +25,11 @@
             _64bit::DATA/nativetest64/vr_hidl_hal_test/vr_hidl_hal_test,
             "/>
         <option name="binary-test-type" value="hal_hidl_gtest" />
-        <option name="hwbinder-service" value="android.hardware.vr" />
+        <!-- Uncomment this and comment 'precondition-feature' to run this test
+             only on devices using binderized VR HALs.
+        <option name="precondition-hwbinder-service" value="android.hardware.vr" /> -->
+        <option name="precondition-feature" value="android.hardware.vr.high_performance" />
         <option name="test-timeout" value="1m" />
         <option name="test-config-path" value="vts/testcases/hal/vr/hidl/target/VrHidlTargetTest.config" />
 </test>
 </configuration>
-
diff --git a/wifi/supplicant/1.0/ISupplicantIface.hal b/wifi/supplicant/1.0/ISupplicantIface.hal
index c0058a0..8bb8c97 100644
--- a/wifi/supplicant/1.0/ISupplicantIface.hal
+++ b/wifi/supplicant/1.0/ISupplicantIface.hal
@@ -138,6 +138,19 @@
   setWpsDeviceName(string name) generates (SupplicantStatus status);
 
   /**
+   * Set the device type for WPS operations.
+   *
+   * @parm type Type of device. Refer to section B.1 of Wifi P2P
+   *       Technical specification v1.2.
+   * @return status Status of the operation.
+   *         Possible status codes:
+   *         |SupplicantStatusCode.SUCCESS|,
+   *         |SupplicantStatusCode.FAILURE_IFACE_INVALID|,
+   *         |SupplicantStatusCode.FAILURE_UNKNOWN|
+   */
+  setWpsDeviceType(uint8_t[8] type) generates (SupplicantStatus status);
+
+  /**
    * Set the manufacturer for WPS operations.
    * The manufacturer of the device (up to |WPS_MANUFACTURER_MAX_LEN| ASCII
    * characters).
diff --git a/wifi/supplicant/1.0/ISupplicantStaIface.hal b/wifi/supplicant/1.0/ISupplicantStaIface.hal
index c9d9ee6..68eb179 100644
--- a/wifi/supplicant/1.0/ISupplicantStaIface.hal
+++ b/wifi/supplicant/1.0/ISupplicantStaIface.hal
@@ -67,6 +67,10 @@
     SENSE = 2
   };
 
+  enum ExtRadioWorkDefaults : uint32_t {
+    TIMEOUT_IN_SECS = 10
+  };
+
   /**
    * Register for callbacks from this interface.
    *
@@ -405,4 +409,55 @@
    *         |SupplicantStatusCode.FAILURE_IFACE_INVALID|
    */
   setExternalSim(bool useExternalSim) generates (SupplicantStatus status);
+
+  /**
+   * External programs can request supplicant to not start offchannel
+   * operations during other tasks that may need exclusive control of the
+   * radio.
+   *
+   * This method can be used to reserve a slot for radio access. If freq is
+   * specified, other radio work items on the same channel can be completed in
+   * parallel. Otherwise, all other radio work items are blocked during
+   * execution. Timeout must be set to |ExtRadioWorkDefaults.TIMEOUT_IN_SECS|
+   * seconds by default to avoid blocking supplicant operations on the iface
+   * for excessive time. If a longer (or shorter) safety timeout is needed,
+   * that may be specified with the optional timeout parameter. This command
+   * returns an identifier for the radio work item.
+   *
+   * Once the radio work item has been started,
+   * |ISupplicant.onExtRadioWorkStart| callback is indicated that the external
+   * processing can start.
+   *
+   * @param name Name for the radio work being added.
+   * @param freqInMhz Frequency to specify. Set to 0 for all channels.
+   * @param timeoutInSec Timeout tospecify. Set to 0 for default timeout.
+   * @return status Status of the operation.
+   *         Possible status codes:
+   *         |SupplicantStatusCode.SUCCESS|,
+   *         |SupplicantStatusCode.FAILURE_UNKNOWN|
+   * @return id Identifier for this radio work.
+   */
+  addExtRadioWork(string name, uint32_t freqInMhz, uint32_t timeoutInSec)
+      generates (SupplicantStatus status, uint32_t id);
+
+  /**
+   * Indicates to supplicant that the external radio work has completed.
+   * This allows other radio works to be performed. If this method is not
+   * invoked (e.g., due to the external program terminating), supplicant
+   * must time out the radio work item on the iface and send
+   * |ISupplicantCallback.onExtRadioWorkTimeout| event to indicate
+   * that this has happened.
+   *
+   * This method may also be used to cancel items that have been scheduled
+   * via |addExtRadioWork|, but have not yet been started (notified via
+   * |ISupplicantCallback.onExtRadioWorkStart|).
+   *
+   * @return id Identifier generated for the radio work addition
+   *         (using |addExtRadioWork|).
+   * @return status Status of the operation.
+   *         Possible status codes:
+   *         |SupplicantStatusCode.SUCCESS|,
+   *         |SupplicantStatusCode.FAILURE_UNKNOWN|
+   */
+  removeExtRadioWork(uint32_t id) generates (SupplicantStatus status);
 };
diff --git a/wifi/supplicant/1.0/ISupplicantStaIfaceCallback.hal b/wifi/supplicant/1.0/ISupplicantStaIfaceCallback.hal
index 4b201d4..c3ec060 100644
--- a/wifi/supplicant/1.0/ISupplicantStaIfaceCallback.hal
+++ b/wifi/supplicant/1.0/ISupplicantStaIfaceCallback.hal
@@ -326,4 +326,18 @@
    * Used to indicate the overlap of a WPS PBC connection attempt.
    */
   oneway onWpsEventPbcOverlap();
+
+  /**
+   * Used to indicate that the external radio work can start now.
+   *
+   * @return id Identifier generated for the radio work request.
+   */
+  oneway onExtRadioWorkStart(uint32_t id);
+
+  /**
+   * Used to indicate that the external radio work request has timed out.
+   *
+   * @return id Identifier generated for the radio work request.
+   */
+  oneway onExtRadioWorkTimeout(uint32_t id);
 };
diff --git a/wifi/supplicant/1.0/ISupplicantStaNetwork.hal b/wifi/supplicant/1.0/ISupplicantStaNetwork.hal
index b347c1d..deaad5d 100644
--- a/wifi/supplicant/1.0/ISupplicantStaNetwork.hal
+++ b/wifi/supplicant/1.0/ISupplicantStaNetwork.hal
@@ -508,8 +508,30 @@
    */
   setEapDomainSuffixMatch(string match)
       generates (SupplicantStatus status);
+
   /**
-   * Get ID string set for this network.
+   * This field can be used to enable proactive key caching which is also
+   * known as opportunistic PMKSA caching for WPA2. This is disabled (0)
+   * by default unless default value is changed with the global okc=1
+   * parameter.
+   *
+   * Proactive key caching is used to make supplicant assume that the APs
+   * are using the same PMK and generate PMKSA cache entries without
+   * doing RSN pre-authentication. This requires support from the AP side
+   * and is normally used with wireless switches that co-locate the
+   * authenticator.
+   *
+   * @param enable true to set, false otherwise.
+   * @return status Status of the operation.
+   *         Possible status codes:
+   *         |SupplicantStatusCode.SUCCESS|,
+   *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+   *         |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+   */
+  setProactiveKeyCaching(bool enable) generates (SupplicantStatus status);
+
+  /**
+   * Set ID string for this network.
    * Network identifier string for external scripts.
    *
    * @return idStr ID string value to set.
@@ -523,6 +545,20 @@
   setIdStr(string idStr) generates (SupplicantStatus status);
 
   /**
+   * Set PPS MO ID for this network.
+   * (Hotspot 2.0 PerProviderSubscription/UpdateIdentifier)
+   *
+   * @return id ID value to set.
+   * @return status Status of the operation.
+   *         Possible status codes:
+   *         |SupplicantStatusCode.SUCCESS|,
+   *         |SupplicantStatusCode.FAILURE_ARGS_INVALID|,
+   *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+   *         |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+   */
+  setUpdateIdentifier(uint32_t id) generates (SupplicantStatus status);
+
+  /**
    * Getters for the various network params.
    */
   /**
@@ -912,11 +948,23 @@
    *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
    *         |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
    */
-  sendNetworkEapSimGsmAuthResponse(NetworkResponseEapSimGsmAuthParams params)
+  sendNetworkEapSimGsmAuthResponse(vec<NetworkResponseEapSimGsmAuthParams> params)
       generates (SupplicantStatus status);
 
   /**
    * Used to send a response to the
+   * |ISupplicantNetworkCallback.onNetworkEapSimGsmAuthRequest| request.
+   *
+   * @return status Status of the operation.
+   *         Possible status codes:
+   *         |SupplicantStatusCode.SUCCESS|,
+   *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+   *         |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+   */
+  sendNetworkEapSimGsmAuthFailure() generates (SupplicantStatus status);
+
+  /**
+   * Used to send a response to the
    * |ISupplicantNetworkCallback.onNetworkEapSimUmtsAuthRequest| request.
    *
    * @param params Params to be used for EAP UMTS authentication.
@@ -931,6 +979,32 @@
 
   /**
    * Used to send a response to the
+   * |ISupplicantNetworkCallback.onNetworkEapSimUmtsAuthRequest| request.
+   *
+   * @param auts Params to be used for EAP UMTS authentication.
+   * @return status Status of the operation.
+   *         Possible status codes:
+   *         |SupplicantStatusCode.SUCCESS|,
+   *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+   *         |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+   */
+  sendNetworkEapSimUmtsAutsResponse(uint8_t[14] auts)
+      generates (SupplicantStatus status);
+
+  /**
+   * Used to send a response to the
+   * |ISupplicantNetworkCallback.onNetworkEapSimUmtsAuthRequest| request.
+   *
+   * @return status Status of the operation.
+   *         Possible status codes:
+   *         |SupplicantStatusCode.SUCCESS|,
+   *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+   *         |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+   */
+  sendNetworkEapSimUmtsAuthFailure() generates (SupplicantStatus status);
+
+  /**
+   * Used to send a response to the
    * |ISupplicantNetworkCallback.onNetworkEapIdentityRequest| request.
    *
    * @param identity Identity to be used for the network.