Merge "drm+crypto HAL default implementation"
diff --git a/keymaster/3.0/Android.bp b/keymaster/3.0/Android.bp
new file mode 100644
index 0000000..3c2034b
--- /dev/null
+++ b/keymaster/3.0/Android.bp
@@ -0,0 +1,56 @@
+// This file is autogenerated by hidl-gen. Do not edit manually.
+
+genrule {
+    name: "android.hardware.keymaster@3.0_genc++",
+    tools: ["hidl-gen"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lc++ -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.keymaster@3.0",
+    srcs: [
+        "types.hal",
+        "IKeymasterDevice.hal",
+    ],
+    out: [
+        "android/hardware/keymaster/3.0/types.cpp",
+        "android/hardware/keymaster/3.0/KeymasterDeviceAll.cpp",
+    ],
+}
+
+genrule {
+    name: "android.hardware.keymaster@3.0_genc++_headers",
+    tools: ["hidl-gen"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lc++ -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.keymaster@3.0",
+    srcs: [
+        "types.hal",
+        "IKeymasterDevice.hal",
+    ],
+    out: [
+        "android/hardware/keymaster/3.0/types.h",
+        "android/hardware/keymaster/3.0/IKeymasterDevice.h",
+        "android/hardware/keymaster/3.0/IHwKeymasterDevice.h",
+        "android/hardware/keymaster/3.0/BnKeymasterDevice.h",
+        "android/hardware/keymaster/3.0/BpKeymasterDevice.h",
+        "android/hardware/keymaster/3.0/BsKeymasterDevice.h",
+    ],
+}
+
+cc_library_shared {
+    name: "android.hardware.keymaster@3.0",
+    generated_sources: ["android.hardware.keymaster@3.0_genc++"],
+    generated_headers: ["android.hardware.keymaster@3.0_genc++_headers"],
+    export_generated_headers: ["android.hardware.keymaster@3.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/keymaster/3.0/IKeymasterDevice.hal b/keymaster/3.0/IKeymasterDevice.hal
new file mode 100644
index 0000000..19669c8
--- /dev/null
+++ b/keymaster/3.0/IKeymasterDevice.hal
@@ -0,0 +1,324 @@
+/*
+ * 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.keymaster@3.0;
+
+/**
+ * Keymaster device definition.  For thorough documentation see the implementer's reference, at
+ * https://source.android.com/security/keystore/implementer-ref.html
+ */
+interface IKeymasterDevice {
+
+    /**
+     * Returns information about the underlying keymaster hardware.
+     *
+     * @return isSecure is true if keys are stored and never leave secure hardware (Trusted
+     *             Execution Environment or similar). CDD requires that all devices initially
+     *             launched with Marshmallow or later must have secure hardware.
+     *
+     * @return supportsEllipticCurve is true if the hardware supports Elliptic Curve cryptography
+     *             with the NIST curves (P-224, P-256, P-384, and P-521). CDD requires that all
+     *             devices initially launched with Nougat or later must support Elliptic Curve
+     *             cryptography.
+     *
+     * @return supportsSymmetricCryptography is true if the hardware supports symmetric
+     *             cryptography, including AES and HMAC. CDD requires that all devices initially
+     *             launched with Nougat or later must support hardware enforcement of Keymaster
+     *             authorizations.
+     *
+     * @return supportsAttestation is true if the hardware supports generation of Keymaster public
+     *             key attestation certificates, signed with a key injected in a secure
+     *             environment. CDD requires that all devices initially launched with Android O or
+     *             later must support hardware attestation.
+     */
+    getHardwareFeatures()
+        generates(bool isSecure, bool supportsEllipticCurve,
+                  bool supportsSymmetricCryptography, bool supportsAttestation);
+
+    /**
+     * Adds entropy to the RNG used by keymaster. Entropy added through this method is guaranteed
+     * not to be the only source of entropy used, and the mixing function is required to be secure,
+     * in the sense that if the RNG is seeded (from any source) with any data the attacker cannot
+     * predict (or control), then the RNG output is indistinguishable from random. Thus, if the
+     * entropy from any source is good, the output must be good.
+     *
+     * @param data Bytes to be mixed into the RNG.
+     *
+     * @return error See the ErrorCode enum in types.hal.
+     */
+    addRngEntropy(vec<uint8_t> data) generates(ErrorCode error);
+
+    /**
+     * Generates a key, or key pair, returning a key blob and/or a description of the key.
+     *
+     * @param keyParams Key generation parameters are defined as keymaster tag/value pairs, provided
+     *             in params. See Tag in types.hal for the full list.
+     *
+     * @return error See the ErrorCode enum in types.hal.
+     *
+     * @return keyBlob Opaque, encrypted descriptor of the generated key, which generally contains a
+     *             copy of the key material, wrapped in a key unavailable outside secure hardware.
+     *
+     * @return keyCharacteristics Description of the generated key.  See KeyCharacteristis in
+     *             types.hal.
+     */
+    generateKey(vec<KeyParameter> keyParams)
+        generates(ErrorCode error, vec<uint8_t> keyBlob, KeyCharacteristics keyCharacteristics);
+
+    /**
+     * Imports a key, or key pair, returning a key blob and/or a description of the key.
+     *
+     * @param keyParams Key generation parameters are defined as keymaster tag/value pairs, provided
+     *             in params.  See Tag for the full list.
+     *
+     * @param keyFormat The format of the key material to import. See KeyFormat in types.hal.
+     *
+     * @pram keyData The key material to import, in the format specifed in keyFormat.
+     *
+     * @return error See the ErrorCode enum.
+     *
+     * @return keyBlob Opaque, encrypted descriptor of the generated key, which will generally
+     *             contain a copy of the key material, wrapped in a key unavailable outside secure
+     *             hardware.
+     *
+     * @return keyCharacteristics Decription of the generated key.  See KeyCharacteristis.
+     *
+     * @return error See the ErrorCode enum.
+     */
+    importKey(vec<KeyParameter> params, KeyFormat keyFormat, vec<uint8_t> keyData)
+        generates(ErrorCode error, vec<uint8_t> keyBlob, KeyCharacteristics keyCharacteristics);
+
+    /**
+     * Returns the characteristics of the specified key, if the keyBlob is valid (implementations
+     * must fully validate the integrity of the key).
+     *
+     * @param keyBlob The opaque descriptor returned by generateKey() or importKey();
+     *
+     * @param clientId An opaque byte string identifying the client. This value must match the
+     *             Tag::APPLICATION_ID data provided during key generation/import.  Without the
+     *             correct value it must be cryptographically impossible for the secure hardware to
+     *             obtain the key material.
+     *
+     * @param appData An opaque byte string provided by the application. This value must match the
+     *             Tag::APPLICATION_DATA data provided during key generation/import.  Without the
+     *             correct value it must be cryptographically impossible for the secure hardware to
+     *             obtain the key material.
+     *
+     * @return error See the ErrorCode enum in types.hal.
+     *
+     * @return keyCharacteristics Decription of the generated key.  See KeyCharacteristis in
+     *             types.hal.
+     */
+    getKeyCharacteristics(vec<uint8_t> keyBlob, vec<uint8_t> clientId, vec<uint8_t> appData)
+        generates(ErrorCode error, KeyCharacteristics keyCharacteristics);
+
+    /**
+     * Exports a public key, returning the key in the specified format.
+     *
+     * @parm keyFormat The format used for export. See KeyFormat in types.hal.
+     *
+     * @param keyBlob The opaque descriptor returned by generateKey() or importKey().  The
+     *             referenced key must be asymmetric.
+     *
+     * @param clientId An opaque byte string identifying the client. This value must match the
+     *             Tag::APPLICATION_ID data provided during key generation/import.  Without the
+     *             correct value it must be cryptographically impossible for the secure hardware to
+     *             obtain the key material.
+     *
+     * @param appData An opaque byte string provided by the application. This value must match the
+     *             Tag::APPLICATION_DATA data provided during key generation/import.  Without the
+     *             correct value it must be cryptographically impossible for the secure hardware to
+     *             obtain the key material.
+     *
+     * @return error See the ErrorCode enum in types.hal.
+     *
+     * @return keyMaterial The public key material in PKCS#8 format.
+     */
+    exportKey(KeyFormat keyFormat, vec<uint8_t> keyBlob, vec<uint8_t> clientId,
+              vec<uint8_t> appData) generates(ErrorCode error, vec<uint8_t> keyMaterial);
+
+    /**
+     * Generates a signed X.509 certificate chain attesting to the presence of keyToAttest in
+     * keymaster. The certificate will contain an extension with OID 1.3.6.1.4.1.11129.2.1.17 and
+     * value defined in:
+     *
+     *     https://developer.android.com/training/articles/security-key-attestation.html.
+     *
+     * @param keyToAttest The opaque descriptor returned by generateKey() or importKey().  The
+     *             referenced key must be asymmetric.
+     *
+     * @param attestParams Parameters for the attestation, notably Tag::ATTESTATION_CHALLENGE.
+     *
+     * @return error See the ErrorCode enum in types.hal.
+     */
+    attestKey(vec<uint8_t> keyToAttest, vec<KeyParameter> attestParams)
+        generates(ErrorCode error, vec<vec<uint8_t>> certChain);
+
+    /**
+     * Upgrades an old key. Keys can become "old" in two ways: Keymaster can be upgraded to a new
+     * version, or the system can be updated to invalidate the OS version and/or patch level. In
+     * either case, attempts to use an old key with getKeyCharacteristics(), exportKey(),
+     * attestKey() or begin() will result in keymaster returning
+     * ErrorCode::KEY_REQUIRES_UPGRADE. This method must then be called to upgrade the key.
+     *
+     * @param keyBlobToUpgrade The opaque descriptor returned by generateKey() or importKey();
+     *
+     * @param upgradeParams A parameter list containing any parameters needed to complete the
+     *             upgrade, including Tag::APPLICATION_ID and Tag::APPLICATION_DATA.
+     *
+     * @return error See the ErrorCode enum.
+     */
+    upgradeKey(vec<uint8_t> keyBlobToUpgrade, vec<KeyParameter> upgradeParams)
+        generates(ErrorCode error, vec<uint8_t> upgradedKeyBlob);
+
+    /**
+     * Deletes the key, or key pair, associated with the key blob. After calling this function it
+     * will be impossible to use the key for any other operations. May be applied to keys from
+     * foreign roots of trust (keys not usable under the current root of trust).
+     *
+     * This is a NOP for keys that don't have rollback protection.
+     *
+     * @param keyBlobToUpgrade The opaque descriptor returned by generateKey() or importKey();
+     *
+     * @return error See the ErrorCode enum.
+     */
+    deleteKey(vec<uint8_t> keyBlob) generates(ErrorCode error);
+
+    /**
+     * Deletes all keys in the hardware keystore. Used when keystore is reset completely. After
+     * calling this function it will be impossible to use any previously generated or imported key
+     * blobs for any operations.
+     *
+     * This is a NOP if keys don't have rollback protection.
+     *
+     * @return error See the ErrorCode enum.
+     */
+    deleteAllKeys() 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().
+     *
+     * It is critical that each call to begin() be paired with a subsequent call to finish() or
+     * abort(), to allow the keymaster implementation to clean up any internal operation state.
+     * Failure to do this may leak internal state space or other internal resources and may
+     * eventually cause begin() to return ErrorCode::TOO_MANY_OPERATIONS when it runs out of space
+     * for operations. Any result other than ErrorCode::OK from begin(), update() or finish()
+     * implicitly aborts the operation, in which case abort() need not be called (and will return
+     * ErrorCode::INVALID_OPERATION_HANDLE if called).
+     *
+     * @param purpose The purpose of the operation, one of KeyPurpose::ENCRYPT, KeyPurpose::DECRYPT,
+     *             KeyPurpose::SIGN or KeyPurpose::VERIFY. Note that for AEAD modes, encryption and
+     *             decryption imply signing and verification, respectively, but must be specified as
+     *             KeyPurpose::ENCRYPT and KeyPurpose::DECRYPT.
+     *
+     * @param keyBlob The opaque key descriptor returned by generateKey() or importKey().  The key
+     *             must have a purpose compatible with purpose and all of its usage requirements
+     *             must be satisfied, or begin() will return an appropriate error code.
+     *
+     * @param inParams Additional parameters for the operation. This is typically used to provide
+     *             authentication data, with Tag::AUTH_TOKEN. If Tag::APPLICATION_ID or
+     *             Tag::APPLICATION_DATA were provided during generation, they must be provided
+     *             here, or the operation will fail with ErrorCode::INVALID_KEY_BLOB. For operations
+     *             that require a nonce or IV, on keys that were generated with Tag::CALLER_NONCE,
+     *             inParams may contain a tag Tag::NONCE.
+     *
+     * @return error See the ErrorCode enum in types.hal.
+     *
+     * @return outParams Output parameters. Used to return additional data from the operation
+     *             initialization, notably to return the IV or nonce from operations that generate
+     *             an IV or nonce.
+     *
+     * @return operationHandle The newly-created operation handle which must be passed to update(),
+     *             finish() or abort().
+     */
+    begin(KeyPurpose purpose, vec<uint8_t> key, vec<KeyParameter> inParams)
+        generates(ErrorCode error, vec<KeyParameter> outParams, OperationHandle operationHandle);
+
+    /**
+     * Provides data to, and possibly receives output from, an ongoing cryptographic operation begun
+     * with begin().
+     *
+     * If operationHandle is invalid, update() will return ErrorCode::INVALID_OPERATION_HANDLE.
+     *
+     * update() may not consume all of the data provided in the data buffer. update() will return
+     * the amount consumed in inputConsumed. The caller may provide the unconsumed data in a
+     * subsequent call.
+     *
+     * @param operationHandle The operation handle returned by begin().
+     *
+     * @param inParams Additional parameters for the operation. For AEAD modes, this is used to
+     *             specify Tag::ADDITIONAL_DATA. Note that additional data may be provided in
+     *             multiple calls to update(), but only until input data has been provided.
+     *
+     * @param input Data to be processed, per the parameters established in the call to begin().
+     *             Note that update() may or may not consume all of the data provided. See
+     *             inputConsumed.
+     *
+     * @return error See the ErrorCode enum in types.hal.
+     *
+     * @return inputConsumed Amount of data that was consumed by update(). If this is less than the
+     *             amount provided, the caller may provide the remainder in a subsequent call to
+     *             update() or finish().
+     *
+     * @return outParams Output parameters, used to return additional data from the operation The
+     *             caller takes ownership of the output parameters array and must free it with
+     *             keymaster_free_param_set().
+     *
+     * @return output The output data, if any.
+     */
+    update(OperationHandle operationHandle, vec<KeyParameter> inParams, vec<uint8_t> input)
+        generates(ErrorCode error, uint32_t inputConsumed, vec<KeyParameter> outParams,
+                  vec<uint8_t> output);
+
+    /**
+     * Finalizes a cryptographic operation begun with begin() and invalidates operationHandle.
+     *
+     * @param operationHandle The operation handle returned by begin(). This handle will be
+     *             invalid when finish() returns.
+     *
+     * @param inParams Additional parameters for the operation. For AEAD modes, this is used to
+     *             specify Tag::ADDITIONAL_DATA, but only if no input data was provided to update().
+     *
+     * @param input Data to be processed, per the parameters established in the call to
+     *             begin(). finish() must consume all provided data or return
+     *             ErrorCode::INVALID_INPUT_LENGTH.
+     *
+     * @param signature The signature to be verified if the purpose specified in the begin() call
+     *             was KeyPurpose::VERIFY.
+     *
+     * @return error See the ErrorCode enum in types.hal.
+     *
+     * @return outParams Any output parameters generated by finish().
+     *
+     * @return output The output data, if any.
+     */
+    finish(OperationHandle operationHandle, vec<KeyParameter> inParams, vec<uint8_t> input,
+           vec<uint8_t> signature)
+        generates(ErrorCode error, vec<KeyParameter> outParams, vec<uint8_t> output);
+
+    /**
+     * Aborts a cryptographic operation begun with begin(), freeing all internal resources and
+     * invalidating operationHandle.
+     *
+     * @param operationHandle The operation handle returned by begin(). This handle will be
+     *             invalid when abort() returns.
+     *
+     * @return error See the ErrorCode enum in types.hal.
+     */
+    abort(OperationHandle operationHandle) generates(ErrorCode error);
+};
diff --git a/keymaster/3.0/default/Android.mk b/keymaster/3.0/default/Android.mk
new file mode 100644
index 0000000..36d8890
--- /dev/null
+++ b/keymaster/3.0/default/Android.mk
@@ -0,0 +1,43 @@
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := android.hardware.keymaster@3.0-impl
+LOCAL_MODULE_RELATIVE_PATH := hw
+LOCAL_SRC_FILES := \
+    KeymasterDevice.cpp \
+
+LOCAL_SHARED_LIBRARIES := \
+    liblog \
+    libsoftkeymasterdevice \
+    libcrypto \
+    libkeymaster1 \
+    libhidlbase \
+    libhidltransport \
+    libhwbinder \
+    libutils \
+    libhardware \
+    android.hardware.keymaster@3.0
+
+include $(BUILD_SHARED_LIBRARY)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE_RELATIVE_PATH := hw
+LOCAL_MODULE := android.hardware.keymaster@3.0-service
+LOCAL_INIT_RC := android.hardware.keymaster@3.0-service.rc
+LOCAL_SRC_FILES := \
+    service.cpp
+
+LOCAL_SHARED_LIBRARIES := \
+    liblog \
+    libcutils \
+    libdl \
+    libbase \
+    libutils \
+    libhardware_legacy \
+    libhardware \
+    libhwbinder \
+    libhidlbase \
+    libhidltransport \
+    android.hardware.keymaster@3.0
+
+include $(BUILD_EXECUTABLE)
diff --git a/keymaster/3.0/default/KeymasterDevice.cpp b/keymaster/3.0/default/KeymasterDevice.cpp
new file mode 100644
index 0000000..1208b8d
--- /dev/null
+++ b/keymaster/3.0/default/KeymasterDevice.cpp
@@ -0,0 +1,691 @@
+/*
+ **
+ ** Copyright 2016, The Android Open Source Project
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ **     http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ** See the License for the specific language governing permissions and
+ ** limitations under the License.
+ */
+
+#define LOG_TAG "android.hardware.keymaster@3.0-impl"
+
+#include "KeymasterDevice.h"
+
+#include <cutils/log.h>
+
+#include <hardware/keymaster_defs.h>
+#include <keymaster/keymaster_configuration.h>
+#include <keymaster/soft_keymaster_device.h>
+
+namespace android {
+namespace hardware {
+namespace keymaster {
+namespace V3_0 {
+namespace implementation {
+
+using ::keymaster::SoftKeymasterDevice;
+
+class SoftwareOnlyHidlKeymasterEnforcement : public ::keymaster::KeymasterEnforcement {
+  public:
+    SoftwareOnlyHidlKeymasterEnforcement() : KeymasterEnforcement(64, 64) {}
+
+    uint32_t get_current_time() const override {
+        struct timespec tp;
+        int err = clock_gettime(CLOCK_MONOTONIC, &tp);
+        if (err || tp.tv_sec < 0) return 0;
+        return static_cast<uint32_t>(tp.tv_sec);
+    }
+
+    bool activation_date_valid(uint64_t) const override { return true; }
+    bool expiration_date_passed(uint64_t) const override { return false; }
+    bool auth_token_timed_out(const hw_auth_token_t&, uint32_t) const override { return false; }
+    bool ValidateTokenSignature(const hw_auth_token_t&) const override { return true; }
+};
+
+class SoftwareOnlyHidlKeymasterContext : public ::keymaster::SoftKeymasterContext {
+  public:
+    SoftwareOnlyHidlKeymasterContext() : enforcement_(new SoftwareOnlyHidlKeymasterEnforcement) {}
+
+    ::keymaster::KeymasterEnforcement* enforcement_policy() override { return enforcement_.get(); }
+
+  private:
+    std::unique_ptr<::keymaster::KeymasterEnforcement> enforcement_;
+};
+
+static int keymaster0_device_initialize(const hw_module_t* mod, keymaster2_device_t** dev) {
+    assert(mod->module_api_version < KEYMASTER_MODULE_API_VERSION_1_0);
+    ALOGI("Found keymaster0 module %s, version %x", mod->name, mod->module_api_version);
+
+    UniquePtr<SoftKeymasterDevice> soft_keymaster(new SoftKeymasterDevice);
+    keymaster0_device_t* km0_device = NULL;
+    keymaster_error_t error = KM_ERROR_OK;
+
+    int rc = keymaster0_open(mod, &km0_device);
+    if (rc) {
+        ALOGE("Error opening keystore keymaster0 device.");
+        goto err;
+    }
+
+    if (km0_device->flags & KEYMASTER_SOFTWARE_ONLY) {
+        ALOGI("Keymaster0 module is software-only.  Using SoftKeymasterDevice instead.");
+        km0_device->common.close(&km0_device->common);
+        km0_device = NULL;
+        // SoftKeymasterDevice will be deleted by keymaster_device_release()
+        *dev = soft_keymaster.release()->keymaster2_device();
+        return 0;
+    }
+
+    ALOGD("Wrapping keymaster0 module %s with SoftKeymasterDevice", mod->name);
+    error = soft_keymaster->SetHardwareDevice(km0_device);
+    km0_device = NULL;  // SoftKeymasterDevice has taken ownership.
+    if (error != KM_ERROR_OK) {
+        ALOGE("Got error %d from SetHardwareDevice", error);
+        rc = error;
+        goto err;
+    }
+
+    // SoftKeymasterDevice will be deleted by  keymaster_device_release()
+    *dev = soft_keymaster.release()->keymaster2_device();
+    return 0;
+
+err:
+    if (km0_device) km0_device->common.close(&km0_device->common);
+    *dev = NULL;
+    return rc;
+}
+
+static int keymaster1_device_initialize(const hw_module_t* mod, keymaster2_device_t** dev) {
+    assert(mod->module_api_version >= KEYMASTER_MODULE_API_VERSION_1_0);
+    ALOGI("Found keymaster1 module %s, version %x", mod->name, mod->module_api_version);
+
+    UniquePtr<SoftKeymasterDevice> soft_keymaster(new SoftKeymasterDevice);
+    keymaster1_device_t* km1_device = nullptr;
+    keymaster_error_t error = KM_ERROR_OK;
+
+    int rc = keymaster1_open(mod, &km1_device);
+    if (rc) {
+        ALOGE("Error %d opening keystore keymaster1 device", rc);
+        goto err;
+    }
+
+    ALOGD("Wrapping keymaster1 module %s with SofKeymasterDevice", mod->name);
+    error = soft_keymaster->SetHardwareDevice(km1_device);
+    km1_device = nullptr;  // SoftKeymasterDevice has taken ownership.
+    if (error != KM_ERROR_OK) {
+        ALOGE("Got error %d from SetHardwareDevice", error);
+        rc = error;
+        goto err;
+    }
+
+    // SoftKeymasterDevice will be deleted by keymaster_device_release()
+    *dev = soft_keymaster.release()->keymaster2_device();
+    return 0;
+
+err:
+    if (km1_device) km1_device->common.close(&km1_device->common);
+    *dev = NULL;
+    return rc;
+}
+
+static int keymaster2_device_initialize(const hw_module_t* mod, keymaster2_device_t** dev) {
+    assert(mod->module_api_version >= KEYMASTER_MODULE_API_VERSION_2_0);
+    ALOGI("Found keymaster2 module %s, version %x", mod->name, mod->module_api_version);
+
+    keymaster2_device_t* km2_device = nullptr;
+
+    int rc = keymaster2_open(mod, &km2_device);
+    if (rc) {
+        ALOGE("Error %d opening keystore keymaster2 device", rc);
+        goto err;
+    }
+
+    *dev = km2_device;
+    return 0;
+
+err:
+    if (km2_device) km2_device->common.close(&km2_device->common);
+    *dev = nullptr;
+    return rc;
+}
+
+static int keymaster_device_initialize(keymaster2_device_t** dev, uint32_t* version,
+                                       bool* supports_ec) {
+    const hw_module_t* mod;
+
+    *supports_ec = true;
+
+    int rc = hw_get_module_by_class(KEYSTORE_HARDWARE_MODULE_ID, NULL, &mod);
+    if (rc) {
+        ALOGI("Could not find any keystore module, using software-only implementation.");
+        // SoftKeymasterDevice will be deleted by keymaster_device_release()
+        *dev = (new SoftKeymasterDevice(new SoftwareOnlyHidlKeymasterContext))->keymaster2_device();
+        *version = -1;
+        return 0;
+    }
+
+    if (mod->module_api_version < KEYMASTER_MODULE_API_VERSION_1_0) {
+        *version = 0;
+        int rc = keymaster0_device_initialize(mod, dev);
+        if (rc == 0 && ((*dev)->flags & KEYMASTER_SUPPORTS_EC) == 0) {
+            *supports_ec = false;
+        }
+        return rc;
+    } else if (mod->module_api_version == KEYMASTER_MODULE_API_VERSION_1_0) {
+        *version = 1;
+        return keymaster1_device_initialize(mod, dev);
+    } else {
+        *version = 2;
+        return keymaster2_device_initialize(mod, dev);
+    }
+}
+
+KeymasterDevice::~KeymasterDevice() {
+    if (keymaster_device_) keymaster_device_->common.close(&keymaster_device_->common);
+}
+
+static inline keymaster_tag_type_t typeFromTag(const keymaster_tag_t tag) {
+    return keymaster_tag_get_type(tag);
+}
+
+/**
+ * legacy_enum_conversion converts enums from hidl to keymaster and back. Currently, this is just a
+ * cast to make the compiler happy. One of two thigs should happen though:
+ * TODO The keymaster enums should become aliases for the hidl generated enums so that we have a
+ *      single point of truth. Then this cast function can go away.
+ */
+inline static keymaster_tag_t legacy_enum_conversion(const Tag value) {
+    return keymaster_tag_t(value);
+}
+inline static Tag legacy_enum_conversion(const keymaster_tag_t value) {
+    return Tag(value);
+}
+inline static keymaster_purpose_t legacy_enum_conversion(const KeyPurpose value) {
+    return keymaster_purpose_t(value);
+}
+inline static keymaster_key_format_t legacy_enum_conversion(const KeyFormat value) {
+    return keymaster_key_format_t(value);
+}
+inline static ErrorCode legacy_enum_conversion(const keymaster_error_t value) {
+    return ErrorCode(value);
+}
+
+class KmParamSet : public keymaster_key_param_set_t {
+  public:
+    KmParamSet(const hidl_vec<KeyParameter>& keyParams) {
+        params = new keymaster_key_param_t[keyParams.size()];
+        length = keyParams.size();
+        for (size_t i = 0; i < keyParams.size(); ++i) {
+            auto tag = legacy_enum_conversion(keyParams[i].tag);
+            switch (typeFromTag(tag)) {
+            case KM_ENUM:
+            case KM_ENUM_REP:
+                params[i] = keymaster_param_enum(tag, keyParams[i].f.integer);
+                break;
+            case KM_UINT:
+            case KM_UINT_REP:
+                params[i] = keymaster_param_int(tag, keyParams[i].f.integer);
+                break;
+            case KM_ULONG:
+            case KM_ULONG_REP:
+                params[i] = keymaster_param_long(tag, keyParams[i].f.longInteger);
+                break;
+            case KM_DATE:
+                params[i] = keymaster_param_date(tag, keyParams[i].f.dateTime);
+                break;
+            case KM_BOOL:
+                if (keyParams[i].f.boolValue)
+                    params[i] = keymaster_param_bool(tag);
+                else
+                    params[i].tag = KM_TAG_INVALID;
+                break;
+            case KM_BIGNUM:
+            case KM_BYTES:
+                params[i] =
+                    keymaster_param_blob(tag, &keyParams[i].blob[0], keyParams[i].blob.size());
+                break;
+            case KM_INVALID:
+            default:
+                params[i].tag = KM_TAG_INVALID;
+                /* just skip */
+                break;
+            }
+        }
+    }
+    KmParamSet(KmParamSet&& other) : keymaster_key_param_set_t{other.params, other.length} {
+        other.length = 0;
+        other.params = nullptr;
+    }
+    KmParamSet(const KmParamSet&) = delete;
+    ~KmParamSet() { delete[] params; }
+};
+
+inline static KmParamSet hidlParams2KmParamSet(const hidl_vec<KeyParameter>& params) {
+    return KmParamSet(params);
+}
+
+inline static keymaster_blob_t hidlVec2KmBlob(const hidl_vec<uint8_t>& blob) {
+    /* hidl unmarshals funny pointers if the the blob is empty */
+    if (blob.size()) return {&blob[0], blob.size()};
+    return {nullptr, 0};
+}
+
+inline static keymaster_key_blob_t hidlVec2KmKeyBlob(const hidl_vec<uint8_t>& blob) {
+    /* hidl unmarshals funny pointers if the the blob is empty */
+    if (blob.size()) return {&blob[0], blob.size()};
+    return {nullptr, 0};
+}
+
+inline static hidl_vec<uint8_t> kmBlob2hidlVec(const keymaster_key_blob_t& blob) {
+    hidl_vec<uint8_t> result;
+    result.setToExternal(const_cast<unsigned char*>(blob.key_material), blob.key_material_size);
+    return result;
+}
+inline static hidl_vec<uint8_t> kmBlob2hidlVec(const keymaster_blob_t& blob) {
+    hidl_vec<uint8_t> result;
+    result.setToExternal(const_cast<unsigned char*>(blob.data), blob.data_length);
+    return result;
+}
+
+inline static hidl_vec<hidl_vec<uint8_t>>
+kmCertChain2Hidl(const keymaster_cert_chain_t* cert_chain) {
+    hidl_vec<hidl_vec<uint8_t>> result;
+    if (!cert_chain || cert_chain->entry_count == 0 || !cert_chain->entries) return result;
+
+    result.resize(cert_chain->entry_count);
+    for (size_t i = 0; i < cert_chain->entry_count; ++i) {
+        auto& entry = cert_chain->entries[i];
+        result[i] = kmBlob2hidlVec(entry);
+    }
+
+    return result;
+}
+
+static inline hidl_vec<KeyParameter> kmParamSet2Hidl(const keymaster_key_param_set_t& set) {
+    hidl_vec<KeyParameter> result;
+    if (set.length == 0 || set.params == nullptr) return result;
+
+    result.resize(set.length);
+    keymaster_key_param_t* params = set.params;
+    for (size_t i = 0; i < set.length; ++i) {
+        auto tag = params[i].tag;
+        result[i].tag = legacy_enum_conversion(tag);
+        switch (typeFromTag(tag)) {
+        case KM_ENUM:
+        case KM_ENUM_REP:
+            result[i].f.integer = params[i].enumerated;
+            break;
+        case KM_UINT:
+        case KM_UINT_REP:
+            result[i].f.integer = params[i].integer;
+            break;
+        case KM_ULONG:
+        case KM_ULONG_REP:
+            result[i].f.longInteger = params[i].long_integer;
+            break;
+        case KM_DATE:
+            result[i].f.dateTime = params[i].date_time;
+            break;
+        case KM_BOOL:
+            result[i].f.boolValue = params[i].boolean;
+            break;
+        case KM_BIGNUM:
+        case KM_BYTES:
+            result[i].blob.setToExternal(const_cast<unsigned char*>(params[i].blob.data),
+                                         params[i].blob.data_length);
+            break;
+        case KM_INVALID:
+        default:
+            params[i].tag = KM_TAG_INVALID;
+            /* just skip */
+            break;
+        }
+    }
+    return result;
+}
+
+// Methods from ::android::hardware::keymaster::V3_0::IKeymasterDevice follow.
+Return<void> KeymasterDevice::getHardwareFeatures(getHardwareFeatures_cb _hidl_cb) {
+    bool is_secure = false;
+    bool supports_symmetric_cryptography = false;
+    bool supports_attestation = false;
+
+    switch (hardware_version_) {
+    case 2:
+        supports_attestation = true;
+    /* Falls through */
+    case 1:
+        supports_symmetric_cryptography = true;
+    /* Falls through */
+    case 0:
+        is_secure = true;
+        break;
+    };
+
+    _hidl_cb(is_secure, hardware_supports_ec_, supports_symmetric_cryptography,
+             supports_attestation);
+    return Void();
+}
+
+Return<ErrorCode> KeymasterDevice::addRngEntropy(const hidl_vec<uint8_t>& data) {
+    return legacy_enum_conversion(
+        keymaster_device_->add_rng_entropy(keymaster_device_, &data[0], data.size()));
+}
+
+Return<void> KeymasterDevice::generateKey(const hidl_vec<KeyParameter>& keyParams,
+                                          generateKey_cb _hidl_cb) {
+    // result variables for the wire
+    KeyCharacteristics resultCharacteristics;
+    hidl_vec<uint8_t> resultKeyBlob;
+
+    // result variables the backend understands
+    keymaster_key_blob_t key_blob{nullptr, 0};
+    keymaster_key_characteristics_t key_characteristics{{nullptr, 0}, {nullptr, 0}};
+
+    // convert the parameter set to something our backend understands
+    auto kmParams = hidlParams2KmParamSet(keyParams);
+
+    auto rc = keymaster_device_->generate_key(keymaster_device_, &kmParams, &key_blob,
+                                              &key_characteristics);
+
+    if (rc == KM_ERROR_OK) {
+        // on success convert the result to wire format
+        resultKeyBlob = kmBlob2hidlVec(key_blob);
+        resultCharacteristics.softwareEnforced = kmParamSet2Hidl(key_characteristics.sw_enforced);
+        resultCharacteristics.teeEnforced = kmParamSet2Hidl(key_characteristics.hw_enforced);
+    }
+
+    // send results off to the client
+    _hidl_cb(legacy_enum_conversion(rc), resultKeyBlob, resultCharacteristics);
+
+    // free buffers that we are responsible for
+    if (key_blob.key_material) free(const_cast<uint8_t*>(key_blob.key_material));
+    keymaster_free_characteristics(&key_characteristics);
+
+    return Void();
+}
+
+Return<void> KeymasterDevice::getKeyCharacteristics(const hidl_vec<uint8_t>& keyBlob,
+                                                    const hidl_vec<uint8_t>& clientId,
+                                                    const hidl_vec<uint8_t>& appData,
+                                                    getKeyCharacteristics_cb _hidl_cb) {
+    // result variables for the wire
+    KeyCharacteristics resultCharacteristics;
+
+    // result variables the backend understands
+    keymaster_key_characteristics_t key_characteristics{{nullptr, 0}, {nullptr, 0}};
+
+    auto kmKeyBlob = hidlVec2KmKeyBlob(keyBlob);
+    auto kmClientId = hidlVec2KmBlob(clientId);
+    auto kmAppData = hidlVec2KmBlob(appData);
+
+    auto rc = keymaster_device_->get_key_characteristics(
+        keymaster_device_, keyBlob.size() ? &kmKeyBlob : nullptr,
+        clientId.size() ? &kmClientId : nullptr, appData.size() ? &kmAppData : nullptr,
+        &key_characteristics);
+
+    if (rc == KM_ERROR_OK) {
+        resultCharacteristics.softwareEnforced = kmParamSet2Hidl(key_characteristics.sw_enforced);
+        resultCharacteristics.teeEnforced = kmParamSet2Hidl(key_characteristics.hw_enforced);
+    }
+
+    _hidl_cb(legacy_enum_conversion(rc), resultCharacteristics);
+
+    keymaster_free_characteristics(&key_characteristics);
+
+    return Void();
+}
+
+Return<void> KeymasterDevice::importKey(const hidl_vec<KeyParameter>& params, KeyFormat keyFormat,
+                                        const hidl_vec<uint8_t>& keyData, importKey_cb _hidl_cb) {
+    // result variables for the wire
+    KeyCharacteristics resultCharacteristics;
+    hidl_vec<uint8_t> resultKeyBlob;
+
+    // result variables the backend understands
+    keymaster_key_blob_t key_blob{nullptr, 0};
+    keymaster_key_characteristics_t key_characteristics{{nullptr, 0}, {nullptr, 0}};
+
+    auto kmParams = hidlParams2KmParamSet(params);
+    auto kmKeyData = hidlVec2KmBlob(keyData);
+
+    auto rc = keymaster_device_->import_key(keymaster_device_, &kmParams,
+                                            legacy_enum_conversion(keyFormat), &kmKeyData,
+                                            &key_blob, &key_characteristics);
+
+    if (rc == KM_ERROR_OK) {
+        // on success convert the result to wire format
+        // (Can we assume that key_blob is {nullptr, 0} or a valid buffer description?)
+        resultKeyBlob = kmBlob2hidlVec(key_blob);
+        resultCharacteristics.softwareEnforced = kmParamSet2Hidl(key_characteristics.sw_enforced);
+        resultCharacteristics.teeEnforced = kmParamSet2Hidl(key_characteristics.hw_enforced);
+    }
+
+    _hidl_cb(legacy_enum_conversion(rc), resultKeyBlob, resultCharacteristics);
+
+    // free buffers that we are responsible for
+    if (key_blob.key_material) free(const_cast<uint8_t*>(key_blob.key_material));
+    keymaster_free_characteristics(&key_characteristics);
+
+    return Void();
+}
+
+Return<void> KeymasterDevice::exportKey(KeyFormat exportFormat, const hidl_vec<uint8_t>& keyBlob,
+                                        const hidl_vec<uint8_t>& clientId,
+                                        const hidl_vec<uint8_t>& appData, exportKey_cb _hidl_cb) {
+
+    // result variables for the wire
+    hidl_vec<uint8_t> resultKeyBlob;
+
+    // result variables the backend understands
+    keymaster_blob_t out_blob{nullptr, 0};
+
+    auto kmKeyBlob = hidlVec2KmKeyBlob(keyBlob);
+    auto kmClientId = hidlVec2KmBlob(clientId);
+    auto kmAppData = hidlVec2KmBlob(appData);
+
+    auto rc = keymaster_device_->export_key(keymaster_device_, legacy_enum_conversion(exportFormat),
+                                            keyBlob.size() ? &kmKeyBlob : nullptr,
+                                            clientId.size() ? &kmClientId : nullptr,
+                                            appData.size() ? &kmAppData : nullptr, &out_blob);
+
+    if (rc == KM_ERROR_OK) {
+        // on success convert the result to wire format
+        // (Can we assume that key_blob is {nullptr, 0} or a valid buffer description?)
+        resultKeyBlob = kmBlob2hidlVec(out_blob);
+    }
+
+    _hidl_cb(legacy_enum_conversion(rc), resultKeyBlob);
+
+    // free buffers that we are responsible for
+    if (out_blob.data) free(const_cast<uint8_t*>(out_blob.data));
+
+    return Void();
+}
+
+Return<void> KeymasterDevice::attestKey(const hidl_vec<uint8_t>& keyToAttest,
+                                        const hidl_vec<KeyParameter>& attestParams,
+                                        attestKey_cb _hidl_cb) {
+
+    hidl_vec<hidl_vec<uint8_t>> resultCertChain;
+
+    keymaster_cert_chain_t cert_chain{nullptr, 0};
+
+    auto kmKeyToAttest = hidlVec2KmKeyBlob(keyToAttest);
+    auto kmAttestParams = hidlParams2KmParamSet(attestParams);
+
+    auto rc = keymaster_device_->attest_key(keymaster_device_, &kmKeyToAttest, &kmAttestParams,
+                                            &cert_chain);
+
+    if (rc == KM_ERROR_OK) {
+        resultCertChain = kmCertChain2Hidl(&cert_chain);
+    }
+
+    _hidl_cb(legacy_enum_conversion(rc), resultCertChain);
+
+    keymaster_free_cert_chain(&cert_chain);
+
+    return Void();
+}
+
+Return<void> KeymasterDevice::upgradeKey(const hidl_vec<uint8_t>& keyBlobToUpgrade,
+                                         const hidl_vec<KeyParameter>& upgradeParams,
+                                         upgradeKey_cb _hidl_cb) {
+
+    // result variables for the wire
+    hidl_vec<uint8_t> resultKeyBlob;
+
+    // result variables the backend understands
+    keymaster_key_blob_t key_blob{nullptr, 0};
+
+    auto kmKeyBlobToUpgrade = hidlVec2KmKeyBlob(keyBlobToUpgrade);
+    auto kmUpgradeParams = hidlParams2KmParamSet(upgradeParams);
+
+    auto rc = keymaster_device_->upgrade_key(keymaster_device_, &kmKeyBlobToUpgrade,
+                                             &kmUpgradeParams, &key_blob);
+
+    if (rc == KM_ERROR_OK) {
+        // on success convert the result to wire format
+        resultKeyBlob = kmBlob2hidlVec(key_blob);
+    }
+
+    _hidl_cb(legacy_enum_conversion(rc), resultKeyBlob);
+
+    if (key_blob.key_material) free(const_cast<uint8_t*>(key_blob.key_material));
+
+    return Void();
+}
+
+Return<ErrorCode> KeymasterDevice::deleteKey(const hidl_vec<uint8_t>& keyBlob) {
+    auto kmKeyBlob = hidlVec2KmKeyBlob(keyBlob);
+    return legacy_enum_conversion(keymaster_device_->delete_key(keymaster_device_, &kmKeyBlob));
+}
+
+Return<ErrorCode> KeymasterDevice::deleteAllKeys() {
+    return legacy_enum_conversion(keymaster_device_->delete_all_keys(keymaster_device_));
+}
+
+Return<void> KeymasterDevice::begin(KeyPurpose purpose, const hidl_vec<uint8_t>& key,
+                                    const hidl_vec<KeyParameter>& inParams, begin_cb _hidl_cb) {
+
+    // result variables for the wire
+    hidl_vec<KeyParameter> resultParams;
+    uint64_t resultOpHandle = 0;
+
+    // result variables the backend understands
+    keymaster_key_param_set_t out_params{nullptr, 0};
+    keymaster_operation_handle_t& operation_handle = resultOpHandle;
+
+    auto kmKey = hidlVec2KmKeyBlob(key);
+    auto kmInParams = hidlParams2KmParamSet(inParams);
+
+    auto rc = keymaster_device_->begin(keymaster_device_, legacy_enum_conversion(purpose), &kmKey,
+                                       &kmInParams, &out_params, &operation_handle);
+
+    if (rc == KM_ERROR_OK) resultParams = kmParamSet2Hidl(out_params);
+
+    _hidl_cb(legacy_enum_conversion(rc), resultParams, resultOpHandle);
+
+    keymaster_free_param_set(&out_params);
+
+    return Void();
+}
+
+Return<void> KeymasterDevice::update(uint64_t operationHandle,
+                                     const hidl_vec<KeyParameter>& inParams,
+                                     const hidl_vec<uint8_t>& input, update_cb _hidl_cb) {
+    // result variables for the wire
+    uint32_t resultConsumed = 0;
+    hidl_vec<KeyParameter> resultParams;
+    hidl_vec<uint8_t> resultBlob;
+
+    // result variables the backend understands
+    size_t consumed = 0;
+    keymaster_key_param_set_t out_params{nullptr, 0};
+    keymaster_blob_t out_blob{nullptr, 0};
+
+    auto kmInParams = hidlParams2KmParamSet(inParams);
+    auto kmInput = hidlVec2KmBlob(input);
+
+    auto rc = keymaster_device_->update(keymaster_device_, operationHandle, &kmInParams, &kmInput,
+                                        &consumed, &out_params, &out_blob);
+
+    if (rc == KM_ERROR_OK) {
+        resultConsumed = consumed;
+        resultParams = kmParamSet2Hidl(out_params);
+        resultBlob = kmBlob2hidlVec(out_blob);
+    }
+
+    _hidl_cb(legacy_enum_conversion(rc), resultConsumed, resultParams, resultBlob);
+
+    keymaster_free_param_set(&out_params);
+    if (out_blob.data) free(const_cast<uint8_t*>(out_blob.data));
+
+    return Void();
+}
+
+Return<void> KeymasterDevice::finish(uint64_t operationHandle,
+                                     const hidl_vec<KeyParameter>& inParams,
+                                     const hidl_vec<uint8_t>& input,
+                                     const hidl_vec<uint8_t>& signature, finish_cb _hidl_cb) {
+    // result variables for the wire
+    hidl_vec<KeyParameter> resultParams;
+    hidl_vec<uint8_t> resultBlob;
+
+    // result variables the backend understands
+    keymaster_key_param_set_t out_params{nullptr, 0};
+    keymaster_blob_t out_blob{nullptr, 0};
+
+    auto kmInParams = hidlParams2KmParamSet(inParams);
+    auto kmInput = hidlVec2KmBlob(input);
+    auto kmSignature = hidlVec2KmBlob(signature);
+
+    auto rc = keymaster_device_->finish(keymaster_device_, operationHandle, &kmInParams, &kmInput,
+                                        &kmSignature, &out_params, &out_blob);
+
+    if (rc == KM_ERROR_OK) {
+        resultParams = kmParamSet2Hidl(out_params);
+        resultBlob = kmBlob2hidlVec(out_blob);
+    }
+
+    _hidl_cb(legacy_enum_conversion(rc), resultParams, resultBlob);
+
+    keymaster_free_param_set(&out_params);
+    if (out_blob.data) free(const_cast<uint8_t*>(out_blob.data));
+
+    return Void();
+}
+
+Return<ErrorCode> KeymasterDevice::abort(uint64_t operationHandle) {
+    return legacy_enum_conversion(keymaster_device_->abort(keymaster_device_, operationHandle));
+}
+
+IKeymasterDevice* HIDL_FETCH_IKeymasterDevice(const char* /* name */) {
+    keymaster2_device_t* dev = nullptr;
+
+    uint32_t version;
+    bool supports_ec;
+    auto rc = keymaster_device_initialize(&dev, &version, &supports_ec);
+    if (rc) return nullptr;
+
+    auto kmrc = ::keymaster::ConfigureDevice(dev);
+    if (kmrc != KM_ERROR_OK) {
+        dev->common.close(&dev->common);
+        return nullptr;
+    }
+
+    return new KeymasterDevice(dev, version, supports_ec);
+}
+
+}  // namespace implementation
+}  // namespace V3_0
+}  // namespace keymaster
+}  // namespace hardware
+}  // namespace android
diff --git a/keymaster/3.0/default/KeymasterDevice.h b/keymaster/3.0/default/KeymasterDevice.h
new file mode 100644
index 0000000..23767ef
--- /dev/null
+++ b/keymaster/3.0/default/KeymasterDevice.h
@@ -0,0 +1,97 @@
+/*
+ **
+ ** Copyright 2016, The Android Open Source Project
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ **     http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ** See the License for the specific language governing permissions and
+ ** limitations under the License.
+ */
+
+#ifndef HIDL_GENERATED_android_hardware_keymaster_V3_0_KeymasterDevice_H_
+#define HIDL_GENERATED_android_hardware_keymaster_V3_0_KeymasterDevice_H_
+
+#include <hardware/keymaster2.h>
+
+#include <android/hardware/keymaster/3.0/IKeymasterDevice.h>
+#include <hidl/Status.h>
+
+#include <hidl/MQDescriptor.h>
+namespace android {
+namespace hardware {
+namespace keymaster {
+namespace V3_0 {
+namespace implementation {
+
+using ::android::hardware::keymaster::V3_0::ErrorCode;
+using ::android::hardware::keymaster::V3_0::IKeymasterDevice;
+using ::android::hardware::keymaster::V3_0::KeyCharacteristics;
+using ::android::hardware::keymaster::V3_0::KeyFormat;
+using ::android::hardware::keymaster::V3_0::KeyParameter;
+using ::android::hardware::keymaster::V3_0::KeyPurpose;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+class KeymasterDevice : public IKeymasterDevice {
+  public:
+    KeymasterDevice(keymaster2_device_t* dev, uint32_t hardware_version, bool hardware_supports_ec)
+        : keymaster_device_(dev), hardware_version_(hardware_version),
+          hardware_supports_ec_(hardware_supports_ec) {}
+    virtual ~KeymasterDevice();
+
+    // Methods from ::android::hardware::keymaster::V3_0::IKeymasterDevice follow.
+    Return<void> getHardwareFeatures(getHardwareFeatures_cb _hidl_cb);
+    Return<ErrorCode> addRngEntropy(const hidl_vec<uint8_t>& data) override;
+    Return<void> generateKey(const hidl_vec<KeyParameter>& keyParams,
+                             generateKey_cb _hidl_cb) override;
+    Return<void> getKeyCharacteristics(const hidl_vec<uint8_t>& keyBlob,
+                                       const hidl_vec<uint8_t>& clientId,
+                                       const hidl_vec<uint8_t>& appData,
+                                       getKeyCharacteristics_cb _hidl_cb) override;
+    Return<void> importKey(const hidl_vec<KeyParameter>& params, KeyFormat keyFormat,
+                           const hidl_vec<uint8_t>& keyData, importKey_cb _hidl_cb) override;
+    Return<void> exportKey(KeyFormat exportFormat, const hidl_vec<uint8_t>& keyBlob,
+                           const hidl_vec<uint8_t>& clientId, const hidl_vec<uint8_t>& appData,
+                           exportKey_cb _hidl_cb) override;
+    Return<void> attestKey(const hidl_vec<uint8_t>& keyToAttest,
+                           const hidl_vec<KeyParameter>& attestParams,
+                           attestKey_cb _hidl_cb) override;
+    Return<void> upgradeKey(const hidl_vec<uint8_t>& keyBlobToUpgrade,
+                            const hidl_vec<KeyParameter>& upgradeParams,
+                            upgradeKey_cb _hidl_cb) override;
+    Return<ErrorCode> deleteKey(const hidl_vec<uint8_t>& keyBlob) override;
+    Return<ErrorCode> deleteAllKeys() 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,
+                        const hidl_vec<uint8_t>& input, update_cb _hidl_cb) override;
+    Return<void> finish(uint64_t operationHandle, const hidl_vec<KeyParameter>& inParams,
+                        const hidl_vec<uint8_t>& input, const hidl_vec<uint8_t>& signature,
+                        finish_cb _hidl_cb) override;
+    Return<ErrorCode> abort(uint64_t operationHandle) override;
+
+  private:
+    keymaster2_device_t* keymaster_device_;
+    uint32_t hardware_version_;
+    bool hardware_supports_ec_;
+};
+
+extern "C" IKeymasterDevice* HIDL_FETCH_IKeymasterDevice(const char* name);
+
+}  // namespace implementation
+}  // namespace V3_0
+}  // namespace keymaster
+}  // namespace hardware
+}  // namespace android
+
+#endif  // HIDL_GENERATED_android_hardware_keymaster_V3_0_KeymasterDevice_H_
diff --git a/keymaster/3.0/default/android.hardware.keymaster@3.0-service.rc b/keymaster/3.0/default/android.hardware.keymaster@3.0-service.rc
new file mode 100644
index 0000000..86ed1e7
--- /dev/null
+++ b/keymaster/3.0/default/android.hardware.keymaster@3.0-service.rc
@@ -0,0 +1,4 @@
+service keymaster-3-0 /system/bin/hw/android.hardware.keymaster@3.0-service
+    class hal
+    user system
+    group system drmrpc
diff --git a/keymaster/3.0/default/service.cpp b/keymaster/3.0/default/service.cpp
new file mode 100644
index 0000000..038bf31
--- /dev/null
+++ b/keymaster/3.0/default/service.cpp
@@ -0,0 +1,33 @@
+/*
+**
+** Copyright 2016, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+#define LOG_TAG "android.hardware.keymaster@3.0-service"
+
+#include <android/hardware/keymaster/3.0/IKeymasterDevice.h>
+
+#include <hidl/LegacySupport.h>
+
+using android::sp;
+
+using android::hardware::keymaster::V3_0::IKeymasterDevice;
+using android::hardware::registerPassthroughServiceImplementation;
+using android::hardware::launchRpcServer;
+
+int main() {
+    registerPassthroughServiceImplementation<IKeymasterDevice>("keymaster");
+    return launchRpcServer(1);
+}
diff --git a/keymaster/3.0/types.hal b/keymaster/3.0/types.hal
new file mode 100644
index 0000000..e99e9c8
--- /dev/null
+++ b/keymaster/3.0/types.hal
@@ -0,0 +1,414 @@
+/*
+ * 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.keymaster@3.0;
+
+enum TagType : uint32_t {
+    INVALID = 0 << 28, /* Invalid type, used to designate a tag as uninitialized */
+    ENUM = 1 << 28,
+    ENUM_REP = 2 << 28, /* Repeatable enumeration value. */
+    UINT = 3 << 28,
+    UINT_REP = 4 << 28, /* Repeatable integer value */
+    ULONG = 5 << 28,
+    DATE = 6 << 28,
+    BOOL = 7 << 28,
+    BIGNUM = 8 << 28,
+    BYTES = 9 << 28,
+    ULONG_REP = 10 << 28, /* Repeatable long value */
+};
+
+enum Tag : uint32_t {
+    INVALID = TagType:INVALID | 0,
+
+    /*
+     * Tags that must be semantically enforced by hardware and software implementations.
+     */
+
+    /* Crypto parameters */
+    PURPOSE = TagType:ENUM_REP | 1,    /* KeyPurpose. */
+    ALGORITHM = TagType:ENUM | 2,      /* Algorithm. */
+    KEY_SIZE = TagType:UINT | 3,       /* Key size in bits. */
+    BLOCK_MODE = TagType:ENUM_REP | 4, /* BlockMode. */
+    DIGEST = TagType:ENUM_REP | 5,     /* Digest. */
+    PADDING = TagType:ENUM_REP | 6,    /* PaddingMode. */
+    CALLER_NONCE = TagType:BOOL | 7,   /* Allow caller to specify nonce or IV. */
+    MIN_MAC_LENGTH = TagType:UINT | 8, /* Minimum length of MAC or AEAD authentication tag in
+                                        * bits. */
+    KDF = TagType:ENUM_REP | 9,        /* KeyDerivationFunction. */
+    EC_CURVE = TagType:ENUM | 10,      /* EcCurve. */
+
+    /* Algorithm-specific. */
+    RSA_PUBLIC_EXPONENT = TagType:ULONG | 200,
+    ECIES_SINGLE_HASH_MODE = TagType:BOOL | 201, /* Whether the ephemeral public key is fed into the
+                                                  * KDF. */
+    INCLUDE_UNIQUE_ID = TagType:BOOL | 202,      /* If true, attestation certificates for this key
+                                                  * will contain an application-scoped and
+                                                  * time-bounded device-unique ID.*/
+
+    /* Other hardware-enforced. */
+    BLOB_USAGE_REQUIREMENTS = TagType:ENUM | 301, /* KeyBlobUsageRequirements. */
+    BOOTLOADER_ONLY = TagType:BOOL | 302,         /* Usable only by bootloader. */
+
+    /*
+     * Tags that should be semantically enforced by hardware if possible and will otherwise be
+     * enforced by software (keystore).
+     */
+
+    /* Key validity period */
+    ACTIVE_DATETIME = TagType:DATE | 400,             /* Start of validity. */
+    ORIGINATION_EXPIRE_DATETIME = TagType:DATE | 401, /* Date when new "messages" should no longer
+                                                       * be created. */
+    USAGE_EXPIRE_DATETIME = TagType:DATE | 402,       /* Date when existing "messages" should no
+                                                       * longer be trusted. */
+    MIN_SECONDS_BETWEEN_OPS = TagType:UINT | 403,     /* Minimum elapsed time between
+                                                       * cryptographic operations with the key. */
+    MAX_USES_PER_BOOT = TagType:UINT | 404,           /* Number of times the key can be used per
+                                                       * boot. */
+
+    /* User authentication */
+    ALL_USERS = TagType:BOOL | 500,           /* Reserved for future use -- ignore. */
+    USER_ID = TagType:UINT | 501,             /* Reserved for future use -- ignore. */
+    USER_SECURE_ID = TagType:ULONG_REP | 502, /* Secure ID of authorized user or authenticator(s).
+                                               * Disallowed if ALL_USERS or NO_AUTH_REQUIRED is
+                                               * present. */
+    NO_AUTH_REQUIRED = TagType:BOOL | 503,    /* If key is usable without authentication. */
+    USER_AUTH_TYPE = TagType:ENUM | 504,      /* Bitmask of authenticator types allowed when
+                                               * USER_SECURE_ID contains a secure user ID, rather
+                                               * than a secure authenticator ID.  Defined in
+                                               * HardwareAuthenticatorType. */
+    AUTH_TIMEOUT = TagType:UINT | 505,        /* Required freshness of user authentication for
+                                               * private/secret key operations, in seconds.  Public
+                                               * key operations require no authentication.  If
+                                               * absent, authentication is required for every use.
+                                               * Authentication state is lost when the device is
+                                               * powered off. */
+    ALLOW_WHILE_ON_BODY = TagType:BOOL | 506, /* Allow key to be used after authentication timeout
+                                               * if device is still on-body (requires secure on-body
+                                               * sensor. */
+
+    /* Application access control */
+    ALL_APPLICATIONS = TagType:BOOL | 600, /* Specified to indicate key is usable by all
+                                            * applications. */
+    APPLICATION_ID = TagType:BYTES | 601,  /* Byte string identifying the authorized application. */
+    EXPORTABLE = TagType:BOOL | 602,       /* If true, private/secret key can be exported, but only
+                                            * if all access control requirements for use are
+                                            * met. (keymaster2) */
+
+    /*
+     * Semantically unenforceable tags, either because they have no specific meaning or because
+     * they're informational only.
+     */
+    APPLICATION_DATA = TagType:BYTES | 700,      /* Data provided by authorized application. */
+    CREATION_DATETIME = TagType:DATE | 701,      /* Key creation time */
+    ORIGIN = TagType:ENUM | 702,                 /* keymaster_key_origin_t. */
+    ROLLBACK_RESISTANT = TagType:BOOL | 703,     /* Whether key is rollback-resistant. */
+    ROOT_OF_TRUST = TagType:BYTES | 704,         /* Root of trust ID. */
+    OS_VERSION = TagType:UINT | 705,             /* Version of system (keymaster2) */
+    OS_PATCHLEVEL = TagType:UINT | 706,          /* Patch level of system (keymaster2) */
+    UNIQUE_ID = TagType:BYTES | 707,             /* Used to provide unique ID in attestation */
+    ATTESTATION_CHALLENGE = TagType:BYTES | 708, /* Used to provide challenge in attestation */
+    ATTESTATION_APPLICATION_ID = TagType:BYTES | 709, /* Used to identify the set of possible
+                                                       * applications of which one has initiated a
+                                                       * key 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. */
+    NONCE = TagType:BYTES | 1001,           /* Nonce or Initialization Vector */
+    AUTH_TOKEN = TagType:BYTES | 1002,      /* Authentication token that proves secure user
+                                             * authentication has been performed.  Structure defined
+                                             * in hw_auth_token_t in hw_auth_token.h. */
+    MAC_LENGTH = TagType:UINT | 1003,       /* MAC or AEAD authentication tag length in bits. */
+
+    RESET_SINCE_ID_ROTATION = TagType:BOOL | 1004, /* Whether the device has beeen factory reset
+                                                    * since the last unique ID rotation.  Used for
+                                                    * key attestation. */
+};
+
+enum Algorithm : uint32_t {
+    /* Asymmetric algorithms. */
+    RSA = 1,
+    // DSA = 2, -- Removed, do not re-use value 2.
+    EC = 3,
+
+    /* Block ciphers algorithms */
+    AES = 32,
+
+    /* MAC algorithms */
+    HMAC = 128,
+};
+
+/**
+ * Symmetric block cipher modes provided by keymaster implementations.
+ */
+enum BlockMode : uint32_t {
+    /* Unauthenticated modes, usable only for encryption/decryption and not generally recommended
+     * except for compatibility with existing other protocols. */
+    ECB = 1,
+    CBC = 2,
+    CTR = 3,
+
+    /* Authenticated modes, usable for encryption/decryption and signing/verification.  Recommended
+     * over unauthenticated modes for all purposes. */
+    GCM = 32,
+};
+
+/**
+ * Padding modes that may be applied to plaintext for encryption operations.  This list includes
+ * padding modes for both symmetric and asymmetric algorithms.  Note that implementations should not
+ * provide all possible combinations of algorithm and padding, only the
+ * cryptographically-appropriate pairs.
+ */
+enum PaddingMode : uint32_t {
+    NONE = 1, /* deprecated */
+    RSA_OAEP = 2,
+    RSA_PSS = 3,
+    RSA_PKCS1_1_5_ENCRYPT = 4,
+    RSA_PKCS1_1_5_SIGN = 5,
+    PKCS7 = 64,
+};
+
+/**
+ * Digests provided by keymaster implementations.
+ */
+enum Digest : uint32_t {
+    NONE = 0,
+    MD5 = 1, /* Optional, may not be implemented in hardware, will be handled in software if
+              * needed. */
+    SHA1 = 2,
+    SHA_2_224 = 3,
+    SHA_2_256 = 4,
+    SHA_2_384 = 5,
+    SHA_2_512 = 6,
+};
+
+/**
+ * Supported EC curves, used in ECDSA
+ */
+enum EcCurve : uint32_t {
+    P_224 = 0,
+    P_256 = 1,
+    P_384 = 2,
+    P_521 = 3,
+};
+
+/**
+ * The origin of a key (or pair), i.e. where it was generated.  Note that ORIGIN can be found in
+ * either the hardware-enforced or software-enforced list for a key, indicating whether the key is
+ * hardware or software-based.  Specifically, a key with GENERATED in the hardware-enforced list is
+ * guaranteed never to have existed outide the secure hardware.
+ */
+enum KeyOrigin : uint32_t {
+    GENERATED = 0, /* Generated in keymaster.  Should not exist outside the TEE. */
+    DERIVED = 1,   /* Derived inside keymaster.  Likely exists off-device. */
+    IMPORTED = 2,  /* Imported into keymaster.  Existed as cleartext in Android. */
+    UNKNOWN = 3,   /* Keymaster did not record origin.  This value can only be seen on keys in a
+                    * keymaster0 implementation.  The keymaster0 adapter uses this value to document
+                    * the fact that it is unkown whether the key was generated inside or imported
+                    * into keymaster. */
+};
+
+/**
+ * Usability requirements of key blobs.  This defines what system functionality must be available
+ * for the key to function.  For example, key "blobs" which are actually handles referencing
+ * encrypted key material stored in the file system cannot be used until the file system is
+ * available, and should have BLOB_REQUIRES_FILE_SYSTEM.  Other requirements entries will be added
+ * as needed for implementations.
+ */
+enum KeyBlobUsageRequirements : uint32_t {
+    STANDALONE = 0,
+    REQUIRES_FILE_SYSTEM = 1,
+};
+
+/**
+ * Possible purposes of a key (or pair).
+ */
+enum KeyPurpose : uint32_t {
+    ENCRYPT = 0,    /* Usable with RSA, EC and AES keys. */
+    DECRYPT = 1,    /* Usable with RSA, EC and AES keys. */
+    SIGN = 2,       /* Usable with RSA, EC and HMAC keys. */
+    VERIFY = 3,     /* Usable with RSA, EC and HMAC keys. */
+    DERIVE_KEY = 4, /* Usable with EC keys. */
+};
+
+/**
+ * Keymaster error codes.
+ */
+enum ErrorCode : uint32_t {
+    OK = 0,
+    ROOT_OF_TRUST_ALREADY_SET = -1,
+    UNSUPPORTED_PURPOSE = -2,
+    INCOMPATIBLE_PURPOSE = -3,
+    UNSUPPORTED_ALGORITHM = -4,
+    INCOMPATIBLE_ALGORITHM = -5,
+    UNSUPPORTED_KEY_SIZE = -6,
+    UNSUPPORTED_BLOCK_MODE = -7,
+    INCOMPATIBLE_BLOCK_MODE = -8,
+    UNSUPPORTED_MAC_LENGTH = -9,
+    UNSUPPORTED_PADDING_MODE = -10,
+    INCOMPATIBLE_PADDING_MODE = -11,
+    UNSUPPORTED_DIGEST = -12,
+    INCOMPATIBLE_DIGEST = -13,
+    INVALID_EXPIRATION_TIME = -14,
+    INVALID_USER_ID = -15,
+    INVALID_AUTHORIZATION_TIMEOUT = -16,
+    UNSUPPORTED_KEY_FORMAT = -17,
+    INCOMPATIBLE_KEY_FORMAT = -18,
+    UNSUPPORTED_KEY_ENCRYPTION_ALGORITHM = -19,   /* For PKCS8 & PKCS12 */
+    UNSUPPORTED_KEY_VERIFICATION_ALGORITHM = -20, /* For PKCS8 & PKCS12 */
+    INVALID_INPUT_LENGTH = -21,
+    KEY_EXPORT_OPTIONS_INVALID = -22,
+    DELEGATION_NOT_ALLOWED = -23,
+    KEY_NOT_YET_VALID = -24,
+    KEY_EXPIRED = -25,
+    KEY_USER_NOT_AUTHENTICATED = -26,
+    OUTPUT_PARAMETER_NULL = -27,
+    INVALID_OPERATION_HANDLE = -28,
+    INSUFFICIENT_BUFFER_SPACE = -29,
+    VERIFICATION_FAILED = -30,
+    TOO_MANY_OPERATIONS = -31,
+    UNEXPECTED_NULL_POINTER = -32,
+    INVALID_KEY_BLOB = -33,
+    IMPORTED_KEY_NOT_ENCRYPTED = -34,
+    IMPORTED_KEY_DECRYPTION_FAILED = -35,
+    IMPORTED_KEY_NOT_SIGNED = -36,
+    IMPORTED_KEY_VERIFICATION_FAILED = -37,
+    INVALID_ARGUMENT = -38,
+    UNSUPPORTED_TAG = -39,
+    INVALID_TAG = -40,
+    MEMORY_ALLOCATION_FAILED = -41,
+    IMPORT_PARAMETER_MISMATCH = -44,
+    SECURE_HW_ACCESS_DENIED = -45,
+    OPERATION_CANCELLED = -46,
+    CONCURRENT_ACCESS_CONFLICT = -47,
+    SECURE_HW_BUSY = -48,
+    SECURE_HW_COMMUNICATION_FAILED = -49,
+    UNSUPPORTED_EC_FIELD = -50,
+    MISSING_NONCE = -51,
+    INVALID_NONCE = -52,
+    MISSING_MAC_LENGTH = -53,
+    KEY_RATE_LIMIT_EXCEEDED = -54,
+    CALLER_NONCE_PROHIBITED = -55,
+    KEY_MAX_OPS_EXCEEDED = -56,
+    INVALID_MAC_LENGTH = -57,
+    MISSING_MIN_MAC_LENGTH = -58,
+    UNSUPPORTED_MIN_MAC_LENGTH = -59,
+    UNSUPPORTED_KDF = -60,
+    UNSUPPORTED_EC_CURVE = -61,
+    KEY_REQUIRES_UPGRADE = -62,
+    ATTESTATION_CHALLENGE_MISSING = -63,
+    KEYMASTER_NOT_CONFIGURED = -64,
+    ATTESTATION_APPLICATION_ID_MISSING = -65,
+
+    UNIMPLEMENTED = -100,
+    VERSION_MISMATCH = -101,
+
+    UNKNOWN_ERROR = -1000,
+};
+
+/**
+ * Key derivation functions, mostly used in ECIES.
+ */
+enum KeyDerivationFunction : uint32_t {
+    /* Do not apply a key derivation function; use the raw agreed key */
+    NONE = 0,
+    /* HKDF defined in RFC 5869 with SHA256 */
+    RFC5869_SHA256 = 1,
+    /* KDF1 defined in ISO 18033-2 with SHA1 */
+    ISO18033_2_KDF1_SHA1 = 2,
+    /* KDF1 defined in ISO 18033-2 with SHA256 */
+    ISO18033_2_KDF1_SHA256 = 3,
+    /* KDF2 defined in ISO 18033-2 with SHA1 */
+    ISO18033_2_KDF2_SHA1 = 4,
+    /* KDF2 defined in ISO 18033-2 with SHA256 */
+    ISO18033_2_KDF2_SHA256 = 5,
+};
+
+/**
+ * Hardware authentication type, used by HardwareAuthTokens to specify the mechanism used to
+ * authentiate the user, and in KeyCharacteristics to specify the allowable mechanisms for
+ * authenticating to activate a key.
+ */
+enum HardwareAuthenticatorType : uint32_t {
+    NONE = 0,
+    PASSWORD = 1 << 0,
+    FINGERPRINT = 1 << 1,
+    // Additional entries must be powers of 2.
+    ANY = 0xFFFFFFFF,
+};
+
+struct KeyParameter {
+    /* Discriminates the uinon/blob field used.  The blob cannot be coincided with the union, but
+     * only one of "f" and "blob" is ever used at a time. */
+    Tag tag;
+    union IntegerParams {
+        /* Enum types */
+        Algorithm algorithm;
+        BlockMode blockMode;
+        PaddingMode paddingMode;
+        Digest digest;
+        EcCurve ecCurve;
+        KeyOrigin origin;
+        KeyBlobUsageRequirements keyBlobUsageRequirements;
+        KeyPurpose purpose;
+        KeyDerivationFunction keyDerivationFunction;
+        HardwareAuthenticatorType hardwareAuthenticatorType;
+
+        /* Other types */
+        bool boolValue;  // Always true, if a boolean tag is present.
+        uint32_t integer;
+        uint64_t longInteger;
+        uint64_t dateTime;
+    };
+    IntegerParams f;  // Hidl does not support anonymous unions, so we have to name it.
+    vec<uint8_t> blob;
+};
+
+struct KeyCharacteristics {
+    vec<KeyParameter> softwareEnforced;
+    vec<KeyParameter> teeEnforced;
+};
+
+/**
+ * Data used to prove successful authentication.
+ */
+struct HardwareAuthToken {
+    uint64_t challenge;
+    uint64_t userId;             // Secure User ID, not Android user ID.
+    uint64_t authenticatorId;    // Secure authenticator ID.
+    uint32_t authenticatorType;  // HardwareAuthenticatorType, in network order.
+    uint64_t timestamp;          // In network order.
+    uint8_t[32] hmac;            // HMAC is computed over 0 || challenge || user_id ||
+                                 // authenticator_id || authenticator_type || timestamp, with a
+                                 // prefixed 0 byte (which was a version field in Keymaster1 and
+                                 // Keymaster2) and the fields packed (no padding; so you probably
+                                 // can't just compute over the bytes of the struct).
+};
+
+enum SecurityLevel : uint32_t {
+    SOFTWARE = 0,
+    TRUSTED_ENVIRONMENT = 1,
+};
+
+/**
+ * Formats for key import and export.
+ */
+enum KeyFormat : uint32_t {
+    X509 = 0,  /* for public key export */
+    PKCS8 = 1, /* for asymmetric key pair import */
+    RAW = 3,   /* for symmetric key import and export*/
+};
+
+typedef uint64_t OperationHandle;
diff --git a/keymaster/Android.bp b/keymaster/Android.bp
new file mode 100644
index 0000000..09b8cb2
--- /dev/null
+++ b/keymaster/Android.bp
@@ -0,0 +1,4 @@
+// This is an autogenerated file, do not edit.
+subdirs = [
+    "3.0",
+]
diff --git a/memtrack/1.0/vts/Android.mk b/memtrack/1.0/vts/Android.mk
index 4a5ca4f..7b2400f 100644
--- a/memtrack/1.0/vts/Android.mk
+++ b/memtrack/1.0/vts/Android.mk
@@ -48,3 +48,4 @@
 
 include $(BUILD_SHARED_LIBRARY)
 
+include $(LOCAL_PATH)/functional/vts/testcases/hal/memtrack/hidl/target/Android.mk
diff --git a/memtrack/1.0/vts/functional/Android.bp b/memtrack/1.0/vts/functional/Android.bp
new file mode 100644
index 0000000..b3e560a
--- /dev/null
+++ b/memtrack/1.0/vts/functional/Android.bp
@@ -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.
+//
+
+cc_test {
+    name: "memtrack_hidl_hal_test",
+    gtest: true,
+    srcs: ["memtrack_hidl_hal_test.cpp"],
+    shared_libs: [
+        "libbase",
+        "liblog",
+        "libcutils",
+        "libhardware",
+        "libhidlbase",
+        "libhwbinder",
+        "libutils",
+        "android.hardware.memtrack@1.0",
+    ],
+    static_libs: ["libgtest"],
+    cflags: [
+        "--coverage",
+        "-O0",
+        "-g",
+    ],
+    ldflags: [
+        "--coverage"
+    ]
+}
diff --git a/memtrack/1.0/vts/functional/memtrack_hidl_hal_test.cpp b/memtrack/1.0/vts/functional/memtrack_hidl_hal_test.cpp
new file mode 100644
index 0000000..597b5da
--- /dev/null
+++ b/memtrack/1.0/vts/functional/memtrack_hidl_hal_test.cpp
@@ -0,0 +1,198 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "memtrack_hidl_hal_test"
+#include <android-base/logging.h>
+#include <android/hardware/memtrack/1.0/IMemtrack.h>
+
+#include <gtest/gtest.h>
+
+#include <algorithm>
+#include <vector>
+
+using ::android::hardware::memtrack::V1_0::IMemtrack;
+using ::android::hardware::memtrack::V1_0::MemtrackRecord;
+using ::android::hardware::memtrack::V1_0::MemtrackFlag;
+using ::android::hardware::memtrack::V1_0::MemtrackType;
+using ::android::hardware::memtrack::V1_0::MemtrackStatus;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::sp;
+using std::vector;
+using std::count_if;
+
+class MemtrackHidlTest : public ::testing::Test {
+ public:
+  virtual void SetUp() override {
+    memtrack = IMemtrack::getService("memtrack");
+    ASSERT_NE(memtrack, nullptr);
+  }
+
+  virtual void TearDown() override {}
+
+  sp<IMemtrack> memtrack;
+};
+
+/* Returns true if flags contains at least min, and no more than max,
+ * of the flags in flagSet. Returns false otherwise.
+ */
+bool rightFlagCount(uint32_t flags, vector<MemtrackFlag> flagSet, uint32_t min,
+                    uint32_t max) {
+  uint32_t count =
+      count_if(flagSet.begin(), flagSet.end(),
+               [&](MemtrackFlag f) { return flags & (uint32_t)f; });
+  return (min <= count && count <= max);
+}
+
+/* Returns true when passed a valid, defined status, false otherwise.
+ */
+bool validStatus(MemtrackStatus s) {
+  vector<MemtrackStatus> statusVec = {
+      MemtrackStatus::SUCCESS, MemtrackStatus::MEMORY_TRACKING_NOT_SUPPORTED,
+      MemtrackStatus::TYPE_NOT_SUPPORTED};
+  return std::find(statusVec.begin(), statusVec.end(), s) != statusVec.end();
+}
+
+/* Returns a pid found in /proc for which the string read from
+ * /proc/[pid]/cmdline matches cmd, or -1 if no such pid exists.
+ */
+pid_t getPidFromCmd(const char cmd[], uint32_t len) {
+  const char procs[] = "/proc/";
+  DIR *dir = opendir(procs);
+  if (!dir) {
+    return -1;
+  }
+
+  struct dirent *proc;
+  while ((proc = readdir(dir)) != NULL) {
+    if (!isdigit(proc->d_name[0])) {
+      continue;
+    }
+    char line[len];
+    char fname[PATH_MAX];
+    snprintf(fname, PATH_MAX, "/proc/%s/cmdline", proc->d_name);
+
+    FILE *file = fopen(fname, "r");
+    if (!file) {
+      continue;
+    }
+    char *str = fgets(line, len, file);
+    fclose(file);
+    if (!str || strcmp(str, cmd)) {
+      continue;
+    } else {
+      closedir(dir);
+      return atoi(proc->d_name);
+    }
+  }
+  closedir(dir);
+  return -1;
+}
+
+auto generate_cb(MemtrackStatus *s, hidl_vec<MemtrackRecord> *v) {
+  return [=](MemtrackStatus status, hidl_vec<MemtrackRecord> vec) {
+    *s = status;
+    *v = vec;
+  };
+}
+
+/* Sanity check results when getMemory() is passed a negative PID
+ */
+TEST_F(MemtrackHidlTest, BadPidTest) {
+  MemtrackStatus s;
+  hidl_vec<MemtrackRecord> v;
+  auto cb = generate_cb(&s, &v);
+  for (uint32_t i = 0; i < static_cast<uint32_t>(MemtrackType::NUM_TYPES);
+       i++) {
+    Return<void> ret =
+        memtrack->getMemory(-1, static_cast<MemtrackType>(i), cb);
+    ASSERT_TRUE(ret.isOk());
+    ASSERT_TRUE(validStatus(s));
+  }
+}
+
+/* Sanity check results when getMemory() is passed a bad memory usage type
+ */
+TEST_F(MemtrackHidlTest, BadTypeTest) {
+  MemtrackStatus s;
+  hidl_vec<MemtrackRecord> v;
+  auto cb = generate_cb(&s, &v);
+  Return<void> ret = memtrack->getMemory(getpid(), MemtrackType::NUM_TYPES, cb);
+  ASSERT_TRUE(ret.isOk());
+  ASSERT_TRUE(validStatus(s));
+}
+
+/* Call memtrack on the surfaceflinger process and check that the results are
+ * reasonable for all memory types, including valid flag combinations for
+ * every MemtrackRecord returned.
+ */
+TEST_F(MemtrackHidlTest, SurfaceflingerTest) {
+  const char cmd[] = "/system/bin/surfaceflinger";
+  const uint32_t len = sizeof(cmd);
+  pid_t pid = getPidFromCmd(cmd, len);
+  ASSERT_LE(0, pid) << "Surfaceflinger process not found";
+
+  MemtrackStatus s;
+  hidl_vec<MemtrackRecord> v;
+  auto cb = generate_cb(&s, &v);
+  uint32_t unsupportedCount = 0;
+  for (uint32_t i = 0; i < static_cast<uint32_t>(MemtrackType::NUM_TYPES);
+       i++) {
+    Return<void> ret =
+        memtrack->getMemory(pid, static_cast<MemtrackType>(i), cb);
+    ASSERT_TRUE(ret.isOk());
+
+    switch (s) {
+      case MemtrackStatus::MEMORY_TRACKING_NOT_SUPPORTED:
+        unsupportedCount++;
+        break;
+      case MemtrackStatus::TYPE_NOT_SUPPORTED:
+        break;
+      case MemtrackStatus::SUCCESS: {
+        for (uint32_t j = 0; j < v.size(); j++) {
+          // Enforce flag constraints
+          vector<MemtrackFlag> smapFlags = {MemtrackFlag::SMAPS_ACCOUNTED,
+                                            MemtrackFlag::SMAPS_UNACCOUNTED};
+          EXPECT_TRUE(rightFlagCount(v[j].flags, smapFlags, 1, 1));
+          vector<MemtrackFlag> shareFlags = {MemtrackFlag::SHARED,
+                                             MemtrackFlag::SHARED_PSS,
+                                             MemtrackFlag::PRIVATE};
+          EXPECT_TRUE(rightFlagCount(v[j].flags, shareFlags, 0, 1));
+          vector<MemtrackFlag> systemFlags = {MemtrackFlag::SYSTEM,
+                                              MemtrackFlag::DEDICATED};
+          EXPECT_TRUE(rightFlagCount(v[j].flags, systemFlags, 0, 1));
+          vector<MemtrackFlag> secureFlags = {MemtrackFlag::SECURE,
+                                              MemtrackFlag::NONSECURE};
+          EXPECT_TRUE(rightFlagCount(v[j].flags, secureFlags, 0, 1));
+        }
+        break;
+      }
+      default:
+        FAIL();
+    }
+  }
+  // If tracking is not supported this should be returned for all types.
+  ASSERT_TRUE(unsupportedCount == 0 ||
+              unsupportedCount ==
+                  static_cast<uint32_t>(MemtrackType::NUM_TYPES));
+}
+
+int main(int argc, char **argv) {
+  ::testing::InitGoogleTest(&argc, argv);
+  int status = RUN_ALL_TESTS();
+  LOG(INFO) << "Test result = " << status;
+  return status;
+}
diff --git a/memtrack/1.0/vts/functional/vts/testcases/hal/memtrack/hidl/target/Android.mk b/memtrack/1.0/vts/functional/vts/testcases/hal/memtrack/hidl/target/Android.mk
new file mode 100644
index 0000000..8dcaabb
--- /dev/null
+++ b/memtrack/1.0/vts/functional/vts/testcases/hal/memtrack/hidl/target/Android.mk
@@ -0,0 +1,25 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(call all-subdir-makefiles)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := HalMemtrackHidlTargetTest
+VTS_CONFIG_SRC_DIR := testcases/hal/memtrack/hidl/target
+include test/vts/tools/build/Android.host_config.mk
diff --git a/memtrack/1.0/vts/functional/vts/testcases/hal/memtrack/hidl/target/AndroidTest.xml b/memtrack/1.0/vts/functional/vts/testcases/hal/memtrack/hidl/target/AndroidTest.xml
new file mode 100644
index 0000000..7fb286b
--- /dev/null
+++ b/memtrack/1.0/vts/functional/vts/testcases/hal/memtrack/hidl/target/AndroidTest.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<configuration description="Config for VTS Memtrack 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="HalMemtrackHidlTargetTest"/>
+        <option name="binary-test-sources" value="
+            _32bit::DATA/nativetest/memtrack_hidl_hal_test/memtrack_hidl_hal_test,
+            _64bit::DATA/nativetest64/memtrack_hidl_hal_test/memtrack_hidl_hal_test,
+            "/>
+        <option name="test-config-path" value="vts/testcases/hal/memtrack/hidl/target/HalMemtrackHidlTargetTest.config" />
+        <option name="binary-test-type" value="gtest" />
+        <option name="test-timeout" value="5m" />
+    </test>
+</configuration>
diff --git a/memtrack/1.0/vts/functional/vts/testcases/hal/memtrack/hidl/target/HalMemtrackHidlTargetTest.config b/memtrack/1.0/vts/functional/vts/testcases/hal/memtrack/hidl/target/HalMemtrackHidlTargetTest.config
new file mode 100644
index 0000000..d2597a2
--- /dev/null
+++ b/memtrack/1.0/vts/functional/vts/testcases/hal/memtrack/hidl/target/HalMemtrackHidlTargetTest.config
@@ -0,0 +1,20 @@
+{
+    "use_gae_db": true,
+    "coverage": true,
+    "modules": [
+        {
+            "module_name": "system/lib64/hw/memtrack.msm8992",
+            "git_project": {
+                "name": "platform/hardware/qcom/display",
+                "path": "hardware/qcom/display"
+            }
+        },
+        {
+            "module_name": "system/lib64/hw/android.hardware.memtrack@1.0-impl",
+            "git_project": {
+                "name": "platform/hardware/interfaces",
+                "path": "hardware/interfaces"
+            }
+        }
+    ]
+}
diff --git a/memtrack/Android.bp b/memtrack/Android.bp
index ba90f2c..ed19a37 100644
--- a/memtrack/Android.bp
+++ b/memtrack/Android.bp
@@ -2,4 +2,5 @@
 subdirs = [
     "1.0",
     "1.0/default",
+    "1.0/vts/functional",
 ]
diff --git a/sensors/1.0/Android.bp b/sensors/1.0/Android.bp
index ed65265..437b545 100644
--- a/sensors/1.0/Android.bp
+++ b/sensors/1.0/Android.bp
@@ -54,3 +54,61 @@
         "android.hidl.base@1.0",
     ],
 }
+
+genrule {
+    name: "android.hardware.sensors.vts.driver@1.0_genc++",
+    tools: ["hidl-gen", "vtsc"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lvts -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.sensors@1.0 && $(location vtsc) -mDRIVER -tSOURCE -b$(genDir) android/hardware/sensors/1.0/ $(genDir)/android/hardware/sensors/1.0/",
+    srcs: [
+        "types.hal",
+        "ISensors.hal",
+    ],
+    out: [
+        "android/hardware/sensors/1.0/types.vts.cpp",
+        "android/hardware/sensors/1.0/Sensors.vts.cpp",
+    ],
+}
+
+genrule {
+    name: "android.hardware.sensors.vts.driver@1.0_genc++_headers",
+    tools: ["hidl-gen", "vtsc"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lvts -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.sensors@1.0 && $(location vtsc) -mDRIVER -tHEADER -b$(genDir) android/hardware/sensors/1.0/ $(genDir)/android/hardware/sensors/1.0/",
+    srcs: [
+        "types.hal",
+        "ISensors.hal",
+    ],
+    out: [
+        "android/hardware/sensors/1.0/types.vts.h",
+        "android/hardware/sensors/1.0/Sensors.vts.h",
+    ],
+}
+
+cc_library_shared {
+    name: "android.hardware.sensors.vts.driver@1.0",
+    generated_sources: ["android.hardware.sensors.vts.driver@1.0_genc++"],
+    generated_headers: ["android.hardware.sensors.vts.driver@1.0_genc++_headers"],
+    export_generated_headers: ["android.hardware.sensors.vts.driver@1.0_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.sensors@1.0",
+    ],
+    export_shared_lib_headers: [
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "libutils",
+        "android.hidl.base@1.0",
+    ],
+}
diff --git a/sensors/1.0/vts/Android.mk b/sensors/1.0/vts/Android.mk
index df8d66f..93bbd96 100644
--- a/sensors/1.0/vts/Android.mk
+++ b/sensors/1.0/vts/Android.mk
@@ -16,36 +16,6 @@
 
 LOCAL_PATH := $(call my-dir)
 
-# build VTS driver for Sensors v1.0.
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := libvts_driver_hidl_sensors@1.0
-
-LOCAL_SRC_FILES := \
-  Sensors.vts \
-  types.vts \
-
-LOCAL_SHARED_LIBRARIES += \
-  android.hardware.sensors@1.0 \
-  libbase \
-  libutils \
-  libcutils \
-  liblog \
-  libhidlbase \
-  libhidltransport \
-  libhwbinder \
-  libprotobuf-cpp-full \
-  libvts_common \
-  libvts_datatype \
-  libvts_measurement \
-  libvts_multidevice_proto \
-
-LOCAL_PROTOC_OPTIMIZE_TYPE := full
-
-LOCAL_MULTILIB := both
-
-include $(BUILD_SHARED_LIBRARY)
-
 # build profiler for sensors.
 include $(CLEAR_VARS)
 
diff --git a/thermal/1.0/vts/Android.mk b/thermal/1.0/vts/Android.mk
index ef926fe..644b2ed 100644
--- a/thermal/1.0/vts/Android.mk
+++ b/thermal/1.0/vts/Android.mk
@@ -16,43 +16,6 @@
 
 LOCAL_PATH := $(call my-dir)
 
-# build VTS driver for Thermal v1.0.
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := libvts_driver_hidl_thermal@1.0
-
-LOCAL_SRC_FILES := \
-  Thermal.vts \
-  types.vts \
-
-LOCAL_C_INCLUDES := \
-  android.hardware.thermal@1.0 \
-  system/core/base/include \
-  system/core/include \
-
-LOCAL_SHARED_LIBRARIES += \
-  android.hardware.thermal@1.0 \
-  libbase \
-  libutils \
-  libcutils \
-  liblog \
-  libhidlbase \
-  libhidltransport \
-  libhwbinder \
-  libprotobuf-cpp-full \
-  libvts_common \
-  libvts_datatype \
-  libvts_measurement \
-  libvts_multidevice_proto \
-
-LOCAL_STATIC_LIBRARIES := \
-
-LOCAL_PROTOC_OPTIMIZE_TYPE := full
-
-LOCAL_MULTILIB := both
-
-include $(BUILD_SHARED_LIBRARY)
-
 # build profiler for thermal.
 include $(CLEAR_VARS)
 
diff --git a/thermal/1.0/vts/functional/Android.bp b/thermal/1.0/vts/functional/Android.bp
index fedb760..bef7bc2 100644
--- a/thermal/1.0/vts/functional/Android.bp
+++ b/thermal/1.0/vts/functional/Android.bp
@@ -31,8 +31,12 @@
     ],
     static_libs: ["libgtest"],
     cflags: [
+        "--coverage",
         "-O0",
         "-g",
     ],
+    ldflags: [
+        "--coverage"
+    ]
 }
 
diff --git a/thermal/1.0/vts/functional/vts/testcases/hal/thermal/hidl/target/AndroidTest.xml b/thermal/1.0/vts/functional/vts/testcases/hal/thermal/hidl/target/AndroidTest.xml
index 169264d..3e42b77 100644
--- a/thermal/1.0/vts/functional/vts/testcases/hal/thermal/hidl/target/AndroidTest.xml
+++ b/thermal/1.0/vts/functional/vts/testcases/hal/thermal/hidl/target/AndroidTest.xml
@@ -26,6 +26,8 @@
             "/>
         <option name="binary-test-type" value="gtest" />
         <option name="test-timeout" value="5m" />
+        <option name="test-cobfig-path"
+            value="vts/testcases/hal/thermal/hidl/target/ThermalHidlBasicTest.config" />
     </test>
 </configuration>
 
diff --git a/thermal/1.0/vts/functional/vts/testcases/hal/thermal/hidl/target/ThermalHidlBasicTest.config b/thermal/1.0/vts/functional/vts/testcases/hal/thermal/hidl/target/ThermalHidlBasicTest.config
new file mode 100644
index 0000000..1505476
--- /dev/null
+++ b/thermal/1.0/vts/functional/vts/testcases/hal/thermal/hidl/target/ThermalHidlBasicTest.config
@@ -0,0 +1,25 @@
+{
+    "use_gae_db": true,
+    "coverage": true,
+    "modules": [{
+                    "module_name": "system/lib64/hw/thermal.bullhead",
+                    "git_project": {
+                        "name": "device/lge/bullhead",
+                        "path": "device/lge/bullhead"
+                    }
+                },
+                {
+                    "module_name": "system/lib64/hw/thermal.marlin",
+                    "git_project": {
+                        "name": "device/google/marlin",
+                        "path": "device/google/marlin"
+                    }
+                },
+                {
+                    "module_name": "system/lib64/hw/android.hardware.thermal@1.0-impl",
+                    "git_project": {
+                        "name": "platform/hardware/interfaces".
+                        "path": "hardware/interfaces"
+                    }
+                }]
+}
diff --git a/tv/input/1.0/vts/Android.mk b/tv/input/1.0/vts/Android.mk
index f8610dd..5a60edc 100644
--- a/tv/input/1.0/vts/Android.mk
+++ b/tv/input/1.0/vts/Android.mk
@@ -16,39 +16,6 @@
 
 LOCAL_PATH := $(call my-dir)
 
-# build VTS driver for TvInput v1.0.
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := libvts_driver_hidl_tv_input@1.0
-
-LOCAL_SRC_FILES := \
-  TvInput.vts \
-  TvInputCallback.vts \
-  types.vts \
-  ../../../../audio/common/2.0/vts/types.vts \
-
-LOCAL_SHARED_LIBRARIES += \
-  android.hardware.tv.input@1.0 \
-  libbase \
-  libutils \
-  libcutils \
-  liblog \
-  libhidlbase \
-  libhidltransport \
-  libhwbinder \
-  libprotobuf-cpp-full \
-  libvts_common \
-  libvts_datatype \
-  libvts_measurement \
-  libvts_multidevice_proto \
-
-LOCAL_PROTOC_OPTIMIZE_TYPE := full
-
-LOCAL_MULTILIB := both
-
-include $(BUILD_SHARED_LIBRARY)
-
-
 # build VTS profiler for TvInput
 include $(CLEAR_VARS)
 
diff --git a/vehicle/2.0/Android.mk b/vehicle/2.0/Android.mk
index e1b3b39..71b587b 100644
--- a/vehicle/2.0/Android.mk
+++ b/vehicle/2.0/Android.mk
@@ -663,6 +663,25 @@
 LOCAL_GENERATED_SOURCES += $(GEN)
 
 #
+# Build types.hal (VehicleIgnitionState)
+#
+GEN := $(intermediates)/android/hardware/vehicle/V2_0/VehicleIgnitionState.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.vehicle@2.0::types.VehicleIgnitionState
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
 # Build types.hal (VehicleInstrumentClusterType)
 #
 GEN := $(intermediates)/android/hardware/vehicle/V2_0/VehicleInstrumentClusterType.java
@@ -681,10 +700,6 @@
 	$(transform-generated-source)
 LOCAL_GENERATED_SOURCES += $(GEN)
 
-$(GEN): $(LOCAL_PATH)/types.hal
-	$(transform-generated-source)
-LOCAL_GENERATED_SOURCES += $(GEN)
-
 #
 # Build types.hal (VehiclePropConfig)
 #
@@ -1601,6 +1616,25 @@
 LOCAL_GENERATED_SOURCES += $(GEN)
 
 #
+# Build types.hal (VehicleIgnitionState)
+#
+GEN := $(intermediates)/android/hardware/vehicle/V2_0/VehicleIgnitionState.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.vehicle@2.0::types.VehicleIgnitionState
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
 # Build types.hal (VehicleInstrumentClusterType)
 #
 GEN := $(intermediates)/android/hardware/vehicle/V2_0/VehicleInstrumentClusterType.java
diff --git a/vehicle/2.0/default/impl/DefaultConfig.h b/vehicle/2.0/default/impl/DefaultConfig.h
index 77c4f98..77ee9d4 100644
--- a/vehicle/2.0/default/impl/DefaultConfig.h
+++ b/vehicle/2.0/default/impl/DefaultConfig.h
@@ -153,6 +153,12 @@
                 .maxInt32Value = 10
             }
         }
+    },
+
+    {
+        .prop = VehicleProperty::IGNITION_STATE,
+        .access = VehiclePropertyAccess::READ,
+        .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
     }
 };
 
diff --git a/vehicle/2.0/default/impl/DefaultVehicleHal.cpp b/vehicle/2.0/default/impl/DefaultVehicleHal.cpp
index 4e27bdc..6cbcfe3 100644
--- a/vehicle/2.0/default/impl/DefaultVehicleHal.cpp
+++ b/vehicle/2.0/default/impl/DefaultVehicleHal.cpp
@@ -87,6 +87,9 @@
         case VehicleProperty::DRIVING_STATUS:
             v = pool.obtainInt32(toInt(VehicleDrivingStatus::UNRESTRICTED));
             break;
+        case VehicleProperty::IGNITION_STATE:
+            v = pool.obtainInt32(toInt(VehicleIgnitionState::ACC));
+            break;
         default:
             *outStatus = StatusCode::INVALID_ARG;
     }
diff --git a/vehicle/2.0/types.hal b/vehicle/2.0/types.hal
index 5ab0c24..850efa7 100644
--- a/vehicle/2.0/types.hal
+++ b/vehicle/2.0/types.hal
@@ -310,6 +310,18 @@
         | VehicleArea:GLOBAL),
 
     /*
+     * Represents ignition state
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ
+     */
+    IGNITION_STATE = (
+        0x0409
+            | VehiclePropertyGroup:SYSTEM
+            | VehiclePropertyType:INT32
+            | VehicleArea:GLOBAL),
+
+    /*
      * Fan speed setting
      *
      * @change_mode VehiclePropertyChangeMode:ON_CHANGE
@@ -1614,6 +1626,20 @@
         | VehiclePropertyGroup:SYSTEM
         | VehiclePropertyType:BOOLEAN
         | VehicleArea:GLOBAL),
+
+    /*
+     * Vehicle Maps Data Service
+     *
+     * A VMDS message.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     */
+    VEHICLE_MAPS_DATA_SERVICE = (
+        0x0C00
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:BYTES
+        | VehicleArea:GLOBAL),
 };
 
 /*
@@ -2376,6 +2402,35 @@
     RawValue value;
 };
 
+enum VehicleIgnitionState : int32_t {
+    UNDEFINED = 0,
+
+    /* Steering wheel is locked */
+    LOCK = 1,
+
+     /*
+      * Steering wheel is not locked, engine and all accessories are OFF. If
+      * car can be in LOCK and OFF state at the same time than HAL must report
+      * LOCK state.
+      */
+    OFF,
+
+    /*
+     * Typically in this state accessories become available (e.g. radio).
+     * Instrument cluster and engine are turned off
+     */
+    ACC,
+
+    /*
+     * Ignition is in state ON. Accessories and instrument cluster available,
+     * engine might be running or ready to be started.
+     */
+    ON,
+
+    /* Typically in this state engine is starting (cranking). */
+    START
+};
+
 
 /*
  * Represent the operation where the current error has happened.