Merge "graphics: replace non-const references by pointers"
diff --git a/audio/2.0/IStream.hal b/audio/2.0/IStream.hal
index dc43346..5c88a69 100644
--- a/audio/2.0/IStream.hal
+++ b/audio/2.0/IStream.hal
@@ -227,4 +227,56 @@
      * @param fd dump file descriptor.
      */
     debugDump(handle fd);
+
+    /*
+     * Called by the framework to start a stream operating in mmap mode.
+     * createMmapBuffer() must be called before calling start().
+     * Function only implemented by streams operating in mmap mode.
+     *
+     * @return retval OK in case the success.
+     *                NOT_SUPPORTED on non mmap mode streams
+     *                INVALID_STATE if called out of sequence
+     */
+    start() generates (Result retval);
+
+    /**
+     * Called by the framework to stop a stream operating in mmap mode.
+     * Function only implemented by streams operating in mmap mode.
+     *
+     * @return retval OK in case the succes.
+     *                NOT_SUPPORTED on non mmap mode streams
+     *                INVALID_STATE if called out of sequence
+     */
+    stop() generates (Result retval) ;
+
+    /*
+     * Called by the framework to retrieve information on the mmap buffer used for audio
+     * samples transfer.
+     * Function only implemented by streams operating in mmap mode.
+     *
+     * @param minSizeFrames minimum buffer size requested. The actual buffer
+     *                     size returned in struct MmapBufferInfo can be larger.
+     * @return retval OK in case the success.
+     *                NOT_SUPPORTED on non mmap mode streams
+     *                NOT_INITIALIZED in case of memory allocation error
+     *                INVALID_ARGUMENTS if the requested buffer size is too large
+     *                INVALID_STATE if called out of sequence
+     * @return info    a MmapBufferInfo struct containing information on the MMMAP buffer created.
+     */
+    createMmapBuffer(int32_t minSizeFrames)
+            generates (Result retval, MmapBufferInfo info);
+
+    /*
+     * Called by the framework to read current read/write position in the mmap buffer
+     * with associated time stamp.
+     * Function only implemented by streams operating in mmap mode.
+     *
+     * @return retval OK in case the success.
+     *                NOT_SUPPORTED on non mmap mode streams
+     *                INVALID_STATE if called out of sequence
+     * @return position a MmapPosition struct containing current HW read/write position in frames
+     *                  with associated time stamp.
+     */
+    getMmapPosition()
+            generates (Result retval, MmapPosition position);
 };
diff --git a/audio/2.0/IStreamOutCallback.hal b/audio/2.0/IStreamOutCallback.hal
index 267c46d..cdb38de 100644
--- a/audio/2.0/IStreamOutCallback.hal
+++ b/audio/2.0/IStreamOutCallback.hal
@@ -23,15 +23,15 @@
     /*
      * Non blocking write completed.
      */
-    onWriteReady();
+    oneway onWriteReady();
 
     /*
      * Drain completed.
      */
-    onDrainReady();
+    oneway onDrainReady();
 
     /*
      * Stream hit an error.
      */
-    onError();
+    oneway onError();
 };
diff --git a/audio/2.0/default/Android.mk b/audio/2.0/default/Android.mk
index 2b1aa4f..c3cfd69 100644
--- a/audio/2.0/default/Android.mk
+++ b/audio/2.0/default/Android.mk
@@ -33,6 +33,7 @@
     libhidlbase \
     libhidltransport \
     libhwbinder \
+    libcutils \
     libutils \
     libhardware \
     liblog \
diff --git a/audio/2.0/default/Stream.cpp b/audio/2.0/default/Stream.cpp
index 40f67f0..f214eed 100644
--- a/audio/2.0/default/Stream.cpp
+++ b/audio/2.0/default/Stream.cpp
@@ -43,9 +43,10 @@
     mStream = nullptr;
 }
 
+// static
 Result Stream::analyzeStatus(const char* funcName, int status, int ignoreError) {
     if (status != 0 && status != -ignoreError) {
-        ALOGW("Stream %p %s: %s", mStream, funcName, strerror(-status));
+        ALOGW("Error from HAL stream in function %s: %s", funcName, strerror(-status));
     }
     switch (status) {
         case 0: return Result::OK;
@@ -229,6 +230,29 @@
     return Void();
 }
 
+Return<Result>  Stream::start() {
+    return Result::NOT_SUPPORTED;
+}
+
+Return<Result>  Stream::stop() {
+    return Result::NOT_SUPPORTED;
+}
+
+Return<void>  Stream::createMmapBuffer(int32_t minSizeFrames __unused,
+                                       createMmapBuffer_cb _hidl_cb) {
+    Result retval(Result::NOT_SUPPORTED);
+    MmapBufferInfo info;
+    _hidl_cb(retval, info);
+    return Void();
+}
+
+Return<void>  Stream::getMmapPosition(getMmapPosition_cb _hidl_cb) {
+    Result retval(Result::NOT_SUPPORTED);
+    MmapPosition position;
+    _hidl_cb(retval, position);
+    return Void();
+}
+
 } // namespace implementation
 }  // namespace V2_0
 }  // namespace audio
diff --git a/audio/2.0/default/Stream.h b/audio/2.0/default/Stream.h
index 0ebd723..819bbf7 100644
--- a/audio/2.0/default/Stream.h
+++ b/audio/2.0/default/Stream.h
@@ -18,6 +18,7 @@
 #define ANDROID_HARDWARE_AUDIO_V2_0_STREAM_H
 
 #include <android/hardware/audio/2.0/IStream.h>
+#include <hardware/audio.h>
 #include <hidl/Status.h>
 
 #include <hidl/MQDescriptor.h>
@@ -71,9 +72,13 @@
             const hidl_vec<hidl_string>& keys, getParameters_cb _hidl_cb)  override;
     Return<Result> setParameters(const hidl_vec<ParameterValue>& parameters)  override;
     Return<void> debugDump(const hidl_handle& fd)  override;
+    Return<Result> start() override;
+    Return<Result> stop() override;
+    Return<void> createMmapBuffer(int32_t minSizeFrames, createMmapBuffer_cb _hidl_cb) override;
+    Return<void> getMmapPosition(getMmapPosition_cb _hidl_cb) override;
 
     // Utility methods for extending interfaces.
-    Result analyzeStatus(const char* funcName, int status, int ignoreError = OK);
+    static Result analyzeStatus(const char* funcName, int status, int ignoreError = OK);
 
   private:
     audio_stream_t *mStream;
@@ -85,6 +90,80 @@
     int halSetParameters(const char* keysAndValues) override;
 };
 
+
+template <typename T>
+struct StreamMmap : public RefBase {
+    explicit StreamMmap(T* stream) : mStream(stream) {}
+
+    Return<Result> start();
+    Return<Result> stop();
+    Return<void> createMmapBuffer(
+            int32_t minSizeFrames, size_t frameSize, IStream::createMmapBuffer_cb _hidl_cb);
+    Return<void> getMmapPosition(IStream::getMmapPosition_cb _hidl_cb);
+
+ private:
+   StreamMmap() {}
+
+   T *mStream;
+};
+
+template <typename T>
+Return<Result> StreamMmap<T>::start() {
+    if (mStream->start == NULL) return Result::NOT_SUPPORTED;
+    int result = mStream->start(mStream);
+    return Stream::analyzeStatus("start", result);
+}
+
+template <typename T>
+Return<Result> StreamMmap<T>::stop() {
+    if (mStream->stop == NULL) return Result::NOT_SUPPORTED;
+    int result = mStream->stop(mStream);
+    return Stream::analyzeStatus("stop", result);
+}
+
+template <typename T>
+Return<void> StreamMmap<T>::createMmapBuffer(int32_t minSizeFrames, size_t frameSize,
+                                             IStream::createMmapBuffer_cb _hidl_cb) {
+    Result retval(Result::NOT_SUPPORTED);
+    MmapBufferInfo info;
+
+    if (mStream->create_mmap_buffer != NULL) {
+        struct audio_mmap_buffer_info halInfo;
+        retval = Stream::analyzeStatus(
+                "create_mmap_buffer",
+                mStream->create_mmap_buffer(mStream, minSizeFrames, &halInfo));
+        if (retval == Result::OK) {
+            native_handle_t* hidlHandle = native_handle_create(1, 0);
+            hidlHandle->data[0] = halInfo.shared_memory_fd;
+            info.sharedMemory = hidl_memory("audio_buffer", hidlHandle,
+                                            frameSize *halInfo.buffer_size_frames);
+            info.bufferSizeFrames = halInfo.buffer_size_frames;
+            info.burstSizeFrames = halInfo.burst_size_frames;
+        }
+    }
+    _hidl_cb(retval, info);
+    return Void();
+}
+
+template <typename T>
+Return<void> StreamMmap<T>::getMmapPosition(IStream::getMmapPosition_cb _hidl_cb) {
+    Result retval(Result::NOT_SUPPORTED);
+    MmapPosition position;
+
+    if (mStream->get_mmap_position != NULL) {
+        struct audio_mmap_position halPosition;
+        retval = Stream::analyzeStatus(
+                "get_mmap_position",
+                mStream->get_mmap_position(mStream, &halPosition));
+        if (retval == Result::OK) {
+            position.timeNanoseconds = halPosition.time_nanoseconds;
+            position.positionFrames = halPosition.position_frames;
+        }
+    }
+    _hidl_cb(retval, position);
+    return Void();
+}
+
 }  // namespace implementation
 }  // namespace V2_0
 }  // namespace audio
diff --git a/audio/2.0/default/StreamIn.cpp b/audio/2.0/default/StreamIn.cpp
index 1bc9dfb..1441e74 100644
--- a/audio/2.0/default/StreamIn.cpp
+++ b/audio/2.0/default/StreamIn.cpp
@@ -28,7 +28,9 @@
 namespace implementation {
 
 StreamIn::StreamIn(audio_hw_device_t* device, audio_stream_in_t* stream)
-        : mDevice(device), mStream(stream), mStreamCommon(new Stream(&stream->common)) {
+        : mDevice(device), mStream(stream),
+          mStreamCommon(new Stream(&stream->common)),
+          mStreamMmap(new StreamMmap<audio_stream_in_t>(stream)) {
 }
 
 StreamIn::~StreamIn() {
@@ -130,6 +132,22 @@
     return mStreamCommon->debugDump(fd);
 }
 
+Return<Result> StreamIn::start() {
+    return mStreamMmap->start();
+}
+
+Return<Result> StreamIn::stop() {
+    return mStreamMmap->stop();
+}
+
+Return<void> StreamIn::createMmapBuffer(int32_t minSizeFrames, createMmapBuffer_cb _hidl_cb) {
+    return mStreamMmap->createMmapBuffer(
+            minSizeFrames, audio_stream_in_frame_size(mStream), _hidl_cb);
+}
+
+Return<void> StreamIn::getMmapPosition(getMmapPosition_cb _hidl_cb) {
+    return mStreamMmap->getMmapPosition(_hidl_cb);
+}
 
 // Methods from ::android::hardware::audio::V2_0::IStreamIn follow.
 Return<void> StreamIn::getAudioSource(getAudioSource_cb _hidl_cb)  {
@@ -144,7 +162,7 @@
 }
 
 Return<Result> StreamIn::setGain(float gain)  {
-    return mStreamCommon->analyzeStatus("set_gain", mStream->set_gain(mStream, gain));
+    return Stream::analyzeStatus("set_gain", mStream->set_gain(mStream, gain));
 }
 
 Return<void> StreamIn::read(uint64_t size, read_cb _hidl_cb)  {
@@ -157,7 +175,7 @@
         data.resize(readResult);
     } else if (readResult < 0) {
         data.resize(0);
-        retval = mStreamCommon->analyzeStatus("read", readResult);
+        retval = Stream::analyzeStatus("read", readResult);
     }
     _hidl_cb(retval, data);
     return Void();
@@ -172,7 +190,7 @@
     uint64_t frames = 0, time = 0;
     if (mStream->get_capture_position != NULL) {
         int64_t halFrames, halTime;
-        retval = mStreamCommon->analyzeStatus(
+        retval = Stream::analyzeStatus(
                 "get_capture_position",
                 mStream->get_capture_position(mStream, &halFrames, &halTime));
         if (retval == Result::OK) {
diff --git a/audio/2.0/default/StreamIn.h b/audio/2.0/default/StreamIn.h
index f7c17b7..65e94bb 100644
--- a/audio/2.0/default/StreamIn.h
+++ b/audio/2.0/default/StreamIn.h
@@ -80,11 +80,17 @@
     Return<void> read(uint64_t size, read_cb _hidl_cb)  override;
     Return<uint32_t> getInputFramesLost()  override;
     Return<void> getCapturePosition(getCapturePosition_cb _hidl_cb)  override;
+    Return<Result> start() override;
+    Return<Result> stop() override;
+    Return<void> createMmapBuffer(int32_t minSizeFrames, createMmapBuffer_cb _hidl_cb) override;
+    Return<void> getMmapPosition(getMmapPosition_cb _hidl_cb) override;
 
   private:
     audio_hw_device_t *mDevice;
     audio_stream_in_t *mStream;
     sp<Stream> mStreamCommon;
+    sp<StreamMmap<audio_stream_in_t>> mStreamMmap;
+
 
     virtual ~StreamIn();
 };
diff --git a/audio/2.0/default/StreamOut.cpp b/audio/2.0/default/StreamOut.cpp
index 913b6ae..3d20d11 100644
--- a/audio/2.0/default/StreamOut.cpp
+++ b/audio/2.0/default/StreamOut.cpp
@@ -15,6 +15,7 @@
  */
 
 #define LOG_TAG "StreamOutHAL"
+//#define LOG_NDEBUG 0
 
 #include <hardware/audio.h>
 #include <android/log.h>
@@ -28,7 +29,9 @@
 namespace implementation {
 
 StreamOut::StreamOut(audio_hw_device_t* device, audio_stream_out_t* stream)
-        : mDevice(device), mStream(stream), mStreamCommon(new Stream(&stream->common)) {
+        : mDevice(device), mStream(stream),
+          mStreamCommon(new Stream(&stream->common)),
+          mStreamMmap(new StreamMmap<audio_stream_out_t>(stream)) {
 }
 
 StreamOut::~StreamOut() {
@@ -132,7 +135,6 @@
     return mStreamCommon->debugDump(fd);
 }
 
-
 // Methods from ::android::hardware::audio::V2_0::IStreamOut follow.
 Return<uint32_t> StreamOut::getLatency()  {
     return mStream->get_latency(mStream);
@@ -141,7 +143,7 @@
 Return<Result> StreamOut::setVolume(float left, float right)  {
     Result retval(Result::NOT_SUPPORTED);
     if (mStream->set_volume != NULL) {
-        retval = mStreamCommon->analyzeStatus(
+        retval = Stream::analyzeStatus(
                 "set_volume", mStream->set_volume(mStream, left, right));
     }
     return retval;
@@ -155,7 +157,7 @@
     if (writeResult >= 0) {
         written = writeResult;
     } else {
-        retval = mStreamCommon->analyzeStatus("write", writeResult);
+        retval = Stream::analyzeStatus("write", writeResult);
         written = 0;
     }
     _hidl_cb(retval, written);
@@ -164,7 +166,7 @@
 
 Return<void> StreamOut::getRenderPosition(getRenderPosition_cb _hidl_cb)  {
     uint32_t halDspFrames;
-    Result retval = mStreamCommon->analyzeStatus(
+    Result retval = Stream::analyzeStatus(
             "get_render_position", mStream->get_render_position(mStream, &halDspFrames));
     _hidl_cb(retval, halDspFrames);
     return Void();
@@ -174,7 +176,7 @@
     Result retval(Result::NOT_SUPPORTED);
     int64_t timestampUs = 0;
     if (mStream->get_next_write_timestamp != NULL) {
-        retval = mStreamCommon->analyzeStatus(
+        retval = Stream::analyzeStatus(
                 "get_next_write_timestamp",
                 mStream->get_next_write_timestamp(mStream, &timestampUs));
     }
@@ -188,7 +190,7 @@
     if (result == 0) {
         mCallback = callback;
     }
-    return mStreamCommon->analyzeStatus("set_callback", result);
+    return Stream::analyzeStatus("set_callback", result);
 }
 
 Return<Result> StreamOut::clearCallback()  {
@@ -227,13 +229,13 @@
 
 Return<Result> StreamOut::pause()  {
     return mStream->pause != NULL ?
-            mStreamCommon->analyzeStatus("pause", mStream->pause(mStream)) :
+            Stream::analyzeStatus("pause", mStream->pause(mStream)) :
             Result::NOT_SUPPORTED;
 }
 
 Return<Result> StreamOut::resume()  {
     return mStream->resume != NULL ?
-            mStreamCommon->analyzeStatus("resume", mStream->resume(mStream)) :
+            Stream::analyzeStatus("resume", mStream->resume(mStream)) :
             Result::NOT_SUPPORTED;
 }
 
@@ -243,14 +245,14 @@
 
 Return<Result> StreamOut::drain(AudioDrain type)  {
     return mStream->drain != NULL ?
-            mStreamCommon->analyzeStatus(
+            Stream::analyzeStatus(
                     "drain", mStream->drain(mStream, static_cast<audio_drain_type_t>(type))) :
             Result::NOT_SUPPORTED;
 }
 
 Return<Result> StreamOut::flush()  {
     return mStream->flush != NULL ?
-            mStreamCommon->analyzeStatus("flush", mStream->flush(mStream)) :
+            Stream::analyzeStatus("flush", mStream->flush(mStream)) :
             Result::NOT_SUPPORTED;
 }
 
@@ -260,7 +262,7 @@
     TimeSpec timeStamp = { 0, 0 };
     if (mStream->get_presentation_position != NULL) {
         struct timespec halTimeStamp;
-        retval = mStreamCommon->analyzeStatus(
+        retval = Stream::analyzeStatus(
                 "get_presentation_position",
                 mStream->get_presentation_position(mStream, &frames, &halTimeStamp),
                 // Don't logspam on EINVAL--it's normal for get_presentation_position
@@ -275,6 +277,23 @@
     return Void();
 }
 
+Return<Result> StreamOut::start() {
+    return mStreamMmap->start();
+}
+
+Return<Result> StreamOut::stop() {
+    return mStreamMmap->stop();
+}
+
+Return<void> StreamOut::createMmapBuffer(int32_t minSizeFrames, createMmapBuffer_cb _hidl_cb) {
+    return mStreamMmap->createMmapBuffer(
+            minSizeFrames, audio_stream_out_frame_size(mStream), _hidl_cb);
+}
+
+Return<void> StreamOut::getMmapPosition(getMmapPosition_cb _hidl_cb) {
+    return mStreamMmap->getMmapPosition(_hidl_cb);
+}
+
 }  // namespace implementation
 }  // namespace V2_0
 }  // namespace audio
diff --git a/audio/2.0/default/StreamOut.h b/audio/2.0/default/StreamOut.h
index dc9a604..9b7f9f8 100644
--- a/audio/2.0/default/StreamOut.h
+++ b/audio/2.0/default/StreamOut.h
@@ -91,11 +91,16 @@
     Return<Result> drain(AudioDrain type)  override;
     Return<Result> flush()  override;
     Return<void> getPresentationPosition(getPresentationPosition_cb _hidl_cb)  override;
+    Return<Result> start() override;
+    Return<Result> stop() override;
+    Return<void> createMmapBuffer(int32_t minSizeFrames, createMmapBuffer_cb _hidl_cb) override;
+    Return<void> getMmapPosition(getMmapPosition_cb _hidl_cb) override;
 
   private:
     audio_hw_device_t *mDevice;
     audio_stream_out_t *mStream;
     sp<Stream> mStreamCommon;
+    sp<StreamMmap<audio_stream_out_t>> mStreamMmap;
     sp<IStreamOutCallback> mCallback;
 
     virtual ~StreamOut();
diff --git a/audio/2.0/types.hal b/audio/2.0/types.hal
index 7002f38..37c39e4 100644
--- a/audio/2.0/types.hal
+++ b/audio/2.0/types.hal
@@ -70,3 +70,22 @@
     string busAddress;      // used for BUS
     string rSubmixAddress;  // used for REMOTE_SUBMIX
 };
+
+/*
+ * Mmap buffer descriptor returned by IStream.createMmapBuffer().
+ * Used by streams opened in mmap mode.
+ */
+struct MmapBufferInfo {
+    memory  sharedMemory;         // mmap memory buffer
+    int32_t bufferSizeFrames;     // total buffer size in frames
+    int32_t burstSizeFrames;      // transfer size granularity in frames
+};
+
+/*
+ * Mmap buffer read/write position returned by IStream.getMmapPosition().
+ * Used by streams opened in mmap mode.
+ */
+struct MmapPosition {
+    int64_t  timeNanoseconds; // time stamp in ns, CLOCK_MONOTONIC
+    int32_t  positionFrames;  // increasing 32 bit frame count reset when IStream.stop() is called
+};
diff --git a/audio/common/2.0/default/HidlUtils.cpp b/audio/common/2.0/default/HidlUtils.cpp
index b1bff00..241ca90 100644
--- a/audio/common/2.0/default/HidlUtils.cpp
+++ b/audio/common/2.0/default/HidlUtils.cpp
@@ -97,6 +97,7 @@
         const audio_offload_info_t& halOffload, AudioOffloadInfo* offload) {
     offload->sampleRateHz = halOffload.sample_rate;
     offload->channelMask = AudioChannelMask(halOffload.channel_mask);
+    offload->format = AudioFormat(halOffload.format);
     offload->streamType = AudioStreamType(halOffload.stream_type);
     offload->bitRatePerSecond = halOffload.bit_rate;
     offload->durationMicroseconds = halOffload.duration_us;
@@ -109,6 +110,7 @@
     *halOffload = AUDIO_INFO_INITIALIZER;
     halOffload->sample_rate = offload.sampleRateHz;
     halOffload->channel_mask = static_cast<audio_channel_mask_t>(offload.channelMask);
+    halOffload->format = static_cast<audio_format_t>(offload.format);
     halOffload->stream_type = static_cast<audio_stream_type_t>(offload.streamType);
     halOffload->bit_rate = offload.bitRatePerSecond;
     halOffload->duration_us = offload.durationMicroseconds;
diff --git a/audio/effect/2.0/vts/functional/audio_effect_hidl_hal_test.cpp b/audio/effect/2.0/vts/functional/audio_effect_hidl_hal_test.cpp
index ef70215..1e0ab32 100644
--- a/audio/effect/2.0/vts/functional/audio_effect_hidl_hal_test.cpp
+++ b/audio/effect/2.0/vts/functional/audio_effect_hidl_hal_test.cpp
@@ -97,49 +97,6 @@
   EXPECT_NE(effect, nullptr);
 }
 
-// See b/32834072 -- we should have those operator== generated by hidl-gen.
-
-namespace android {
-namespace hardware {
-namespace audio {
-namespace common {
-namespace V2_0 {
-
-static bool operator==(const Uuid& lhs, const Uuid& rhs) {
-  return lhs.timeLow == rhs.timeLow && lhs.timeMid == rhs.timeMid &&
-         lhs.versionAndTimeHigh == rhs.versionAndTimeHigh &&
-         lhs.variantAndClockSeqHigh == rhs.variantAndClockSeqHigh &&
-         memcmp(lhs.node.data(), rhs.node.data(), lhs.node.size()) == 0;
-}
-
-}  // namespace V2_0
-}  // namespace common
-}  // namespace audio
-}  // namespace hardware
-}  // namespace android
-
-namespace android {
-namespace hardware {
-namespace audio {
-namespace effect {
-namespace V2_0 {
-
-static bool operator==(const EffectDescriptor& lhs,
-                       const EffectDescriptor& rhs) {
-  return lhs.type == rhs.type && lhs.uuid == rhs.uuid &&
-         lhs.flags == rhs.flags && lhs.cpuLoad == rhs.cpuLoad &&
-         lhs.memoryUsage == rhs.memoryUsage &&
-         memcmp(lhs.name.data(), rhs.name.data(), lhs.name.size()) == 0 &&
-         memcmp(lhs.implementor.data(), rhs.implementor.data(),
-                lhs.implementor.size()) == 0;
-}
-
-}  // namespace V2_0
-}  // namespace effect
-}  // namespace audio
-}  // namespace hardware
-}  // namespace android
-
 TEST_F(AudioEffectHidlTest, GetDescriptor) {
   hidl_vec<EffectDescriptor> allDescriptors;
   Return<void> ret = effectsFactory->getAllDescriptors(
diff --git a/boot/1.0/vts/functional/vts/testcases/hal/boot/hidl/target/AndroidTest.xml b/boot/1.0/vts/functional/vts/testcases/hal/boot/hidl/target/AndroidTest.xml
index 6c7809c..bc759bf 100644
--- a/boot/1.0/vts/functional/vts/testcases/hal/boot/hidl/target/AndroidTest.xml
+++ b/boot/1.0/vts/functional/vts/testcases/hal/boot/hidl/target/AndroidTest.xml
@@ -24,6 +24,7 @@
             _32bit::DATA/nativetest/boot_hidl_hal_test/boot_hidl_hal_test,
             _64bit::DATA/nativetest64/boot_hidl_hal_test/boot_hidl_hal_test,
             "/>
+        <option name="test-config-path" value="vts/testcases/hal/boot/hidl/target/HalBootHidlTargetTest.config" />
         <option name="binary-test-type" value="gtest" />
         <option name="test-timeout" value="1m" />
     </test>
diff --git a/boot/1.0/vts/functional/vts/testcases/hal/boot/hidl/target/HalBootHidlTargetTest.config b/boot/1.0/vts/functional/vts/testcases/hal/boot/hidl/target/HalBootHidlTargetTest.config
new file mode 100644
index 0000000..ebb4d1b
--- /dev/null
+++ b/boot/1.0/vts/functional/vts/testcases/hal/boot/hidl/target/HalBootHidlTargetTest.config
@@ -0,0 +1,20 @@
+{
+    "use_gae_db": true,
+    "coverage": true,
+    "modules": [
+        {
+            "module_name": "system/lib64/hw/bootctrl.msm8996",
+            "git_project": {
+                "name": "platform/hardware/qcom/bootctrl",
+                "path": "hardware/qcom/bootctrl"
+            }
+        },
+        {
+            "module_name": "system/lib64/hw/android.hardware.boot@1.0-impl",
+            "git_project": {
+                "name": "platform/hardware/interfaces",
+                "path": "hardware/interfaces"
+            }
+        }
+    ]
+}
diff --git a/camera/device/3.2/types.hal b/camera/device/3.2/types.hal
index 3ce5037..ed6ef7d 100644
--- a/camera/device/3.2/types.hal
+++ b/camera/device/3.2/types.hal
@@ -20,6 +20,9 @@
 import android.hardware.graphics.common@1.0::types;
 
 typedef vec<uint8_t> CameraMetadata;
+typedef bitfield<ProducerUsage> ProducerUsageFlags;
+typedef bitfield<ConsumerUsage> ConsumerUsageFlags;
+typedef bitfield<Dataspace> DataspaceFlags;
 
 /**
  * StreamType:
@@ -221,24 +224,12 @@
      * together and then passed to the platform gralloc HAL module for
      * allocating the gralloc buffers for each stream.
      *
-     * For streamType OUTPUT, when passed via
-     * configureStreams(), the initial value of this is the consumer's usage
-     * flags. The HAL may use these consumer flags to decide stream
-     * configuration. For streamType INPUT, when passed via
-     * configureStreams(), the initial value of this is 0. For all streams
-     * passed via configureStreams(), the HAL must set its desired producer
-     * usage flags in the final stream configuration.
+     * The HAL may use these consumer flags to decide stream configuration. For
+     * streamType INPUT, the value of this field is always 0. For all streams
+     * passed via configureStreams(), the HAL must set its own
+     * additional usage flags in its output HalStreamConfiguration.
      */
-    ConsumerUsage usage;
-
-    /**
-     * The maximum number of buffers the HAL device may need to have dequeued at
-     * the same time. The HAL device may not have more buffers in-flight from
-     * this stream than this value. For all streams passed via
-     * configureStreams(), the HAL must set its desired max buffer count in the
-     * final stream configuration.
-     */
-    uint32_t maxBuffers;
+    ConsumerUsageFlags usage;
 
     /**
      * A field that describes the contents of the buffer. The format and buffer
@@ -256,7 +247,7 @@
      * supported. The dataspace values are set using the V0 dataspace
      * definitions.
      */
-    Dataspace dataSpace;
+    DataspaceFlags dataSpace;
 
     /**
      * The required output rotation of the stream.
@@ -328,18 +319,18 @@
     int32_t id;
 
     /**
-     * The pixel format for the buffers in this stream.
-     *
-     * If HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED is used, then the platform
-     * gralloc module must select a format based on the usage flags provided by
-     * the camera device and the other endpoint of the stream.
+     * An override pixel format for the buffers in this stream.
      *
      * The HAL must respect the requested format in Stream unless it is
      * IMPLEMENTATION_DEFINED, in which case the override format here must be
-     * used instead. This allows cross-platform HALs to use a standard format
-     * since IMPLEMENTATION_DEFINED formats often require device-specific
-     * information. In all other cases, the overrideFormat must match the
-     * requested format.
+     * used by the client instead, for this stream. This allows cross-platform
+     * HALs to use a standard format since IMPLEMENTATION_DEFINED formats often
+     * require device-specific information. In all other cases, the
+     * overrideFormat must match the requested format.
+     *
+     * When HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED is used, then the platform
+     * gralloc module must select a format based on the usage flags provided by
+     * the camera device and the other endpoint of the stream.
      */
     android.hardware.graphics.common@1.0::PixelFormat overrideFormat;
 
@@ -356,8 +347,8 @@
      * consumerUsage must be set. For other types, producerUsage must be set,
      * and consumerUsage must be 0.
      */
-    ProducerUsage producerUsage;
-    ConsumerUsage consumerUsage;
+    ProducerUsageFlags producerUsage;
+    ConsumerUsageFlags consumerUsage;
 
     /**
      * The maximum number of buffers the HAL device may need to have dequeued at
@@ -635,7 +626,7 @@
          * Shutter message contents. Valid if type is MsgType::SHUTTER
          */
         ShutterMsg shutter;
-    };
+    } msg;
 
 };
 
diff --git a/contexthub/1.0/IContexthub.hal b/contexthub/1.0/IContexthub.hal
index 8d19aeb..8c792fd 100644
--- a/contexthub/1.0/IContexthub.hal
+++ b/contexthub/1.0/IContexthub.hal
@@ -60,9 +60,11 @@
      * After the init method for nanoApp returns success, this must be indicated
      * to the service by an asynchronous call to handleTxnResult.
      *
+     * Loading a nanoapp must not take more than 30 seconds.
+     *
      * @param hubId identifer of the contextHub
-     *        appBinary binary for the nanoApp
-     *        msg   message to be sent
+     *        appBinary serialized NanoApppBinary for the nanoApp
+     *        transactionId transactionId for this call
      *
      * @return result OK if transation started
      *                BAD_VALUE if parameters are not sane
@@ -71,7 +73,9 @@
      *                TRANSACTION_FAILED if load failed synchronously
      *
      */
-    loadNanoApp(uint32_t hubId, NanoAppBinary appBinary, uint32_t transactionId)
+    loadNanoApp(uint32_t hubId,
+                vec<uint8_t> appBinary,
+                uint32_t transactionId)
             generates (Result result);
 
     /**
@@ -79,6 +83,8 @@
      * After this, success must be indicated to the service through an
      * asynchronous call to handleTxnResult.
      *
+     * Unloading a nanoapp must not take more than 5 seconds.
+     *
      * @param hubId identifer of the contextHub
      *        appId appIdentifier returned by the HAL
      *        msg   message to be sent
@@ -98,6 +104,8 @@
      * After this, success must be indicated to the service through an
      * asynchronous message.
      *
+     * Enabling a nanoapp must not take more than 5 seconds.
+     *
      * @param hubId identifer of the contextHub
      *        appId appIdentifier returned by the HAL
      *        msg   message to be sent
@@ -117,6 +125,8 @@
      * After this, success must be indicated to the service through an
      * asynchronous message.
      *
+     * Disabling a nanoapp must not take more than 5 seconds.
+     *
      * @param hubId identifer of the contextHub
      *        appId appIdentifier returned by the HAL
      *        msg   message to be sent
@@ -136,7 +146,11 @@
      *
      * @param hubId identifer of the contextHub
      *
-     * @return apps all nanoApps on the hub
+     * @return apps all nanoApps on the hub.
+     *              All nanoApps that can be modified by the service must
+     *              be returned. A non-modifiable nanoapps must not be
+     *              returned. A modifiable nanoApp is one that can be
+     *              unloaded/disabled/enabled by the service.
      *
      */
     queryApps(uint32_t hubId) generates (Result result);
diff --git a/contexthub/1.0/IContexthubCallback.hal b/contexthub/1.0/IContexthubCallback.hal
index 29c41ce..9e9cf27 100644
--- a/contexthub/1.0/IContexthubCallback.hal
+++ b/contexthub/1.0/IContexthubCallback.hal
@@ -22,41 +22,44 @@
      * implementation to allow the HAL to send asynchronous messages back
      * to the service and registered clients of the ContextHub service.
      *
-     * @params hubId : identifier of the hub calling callback
-     *         msg   : message
+     * @params msg : message
      *
      */
-     handleClientMsg(uint32_t hubId, ContextHubMsg msg);
+     handleClientMsg(ContextHubMsg msg);
 
     /*
      * This callback is passed by the Contexthub service to the HAL
      * implementation to allow the HAL to send the response for a
      * transaction.
      *
-     * @params hubId : identifier of the hub calling callback
-     *         txnId : transaction id whose result is being sent
+     * @params txnId : transaction id whose result is being sent
      *                 passed in by the service at start of transacation.
      *         result: result of transaction.
      *
      */
-     handleTxnResult(uint32_t hubId, uint32_t txnId,
-             TransactionResult result);
+     handleTxnResult(uint32_t txnId, TransactionResult result);
 
     /*
      * This callback is passed by the Contexthub service to the HAL
      * implementation to allow the HAL to send an asynchronous event
      * to the ContextHub service.
      *
-     * @params hubId : identifier of the hub calling callback
-     *         msg   : message
+     * @params msg : message
      *
      */
-     handleHubEvent(uint32_t hubId, AsyncEventType evt);
+     handleHubEvent(AsyncEventType evt);
 
      /*
       * This callback is passed by the Contexthub service to the HAL
       * implementation to allow the HAL to send information about the
       * currently loaded and active nanoapps on the hub.
+      *
+      * @params appInfo : vector of HubAppinfo structure for each nanoApp
+      *                   on the hub that can be enabled, disabled and
+      *                   unloaded by the service. Any nanoApps that cannot
+      *                   be controlled by the service must not be reported.
+      *                   All nanoApps that can be controlled by the service
+      *                   must be reported.
       */
-      handleAppsInfo(uint32_t hubId, vec<HubAppInfo> appInfo);
+      handleAppsInfo(vec<HubAppInfo> appInfo);
 };
diff --git a/contexthub/1.0/default/Android.bp b/contexthub/1.0/default/Android.bp
new file mode 100644
index 0000000..7c5f79d
--- /dev/null
+++ b/contexthub/1.0/default/Android.bp
@@ -0,0 +1,33 @@
+/*
+ * 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_library_shared {
+    name: "android.hardware.contexthub@1.0-impl",
+    relative_install_path: "hw",
+    srcs: ["Contexthub.cpp"],
+    shared_libs: [
+        "liblog",
+        "libcutils",
+        "libhardware",
+        "libhwbinder",
+        "libbase",
+        "libcutils",
+        "libutils",
+        "libhidlbase",
+        "libhidltransport",
+        "android.hardware.contexthub@1.0",
+    ],
+}
diff --git a/contexthub/1.0/default/Android.mk b/contexthub/1.0/default/Android.mk
new file mode 100644
index 0000000..ad40878
--- /dev/null
+++ b/contexthub/1.0/default/Android.mk
@@ -0,0 +1,23 @@
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE_RELATIVE_PATH := hw
+LOCAL_MODULE := android.hardware.contexthub@1.0-service
+LOCAL_INIT_RC := android.hardware.contexthub@1.0-service.rc
+LOCAL_SRC_FILES := \
+        service.cpp \
+
+LOCAL_SHARED_LIBRARIES := \
+        libbase \
+        libcutils \
+        libdl \
+        libhardware \
+        libhardware_legacy \
+        libhidlbase \
+        libhidltransport \
+        libhwbinder \
+        liblog \
+        libutils \
+        android.hardware.contexthub@1.0 \
+
+include $(BUILD_EXECUTABLE)
diff --git a/contexthub/1.0/default/Contexthub.cpp b/contexthub/1.0/default/Contexthub.cpp
new file mode 100644
index 0000000..d530a87
--- /dev/null
+++ b/contexthub/1.0/default/Contexthub.cpp
@@ -0,0 +1,528 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "Contexthub.h"
+
+#include <inttypes.h>
+
+#include <android/log.h>
+#include <android/hardware/contexthub/1.0/IContexthub.h>
+#include <hardware/context_hub.h>
+
+#undef LOG_TAG
+#define LOG_TAG "ContextHubHalAdapter"
+
+namespace android {
+namespace hardware {
+namespace contexthub {
+namespace V1_0 {
+namespace implementation {
+
+static constexpr uint64_t ALL_APPS = UINT64_C(0xFFFFFFFFFFFFFFFF);
+
+Contexthub::Contexthub()
+        : mInitCheck(NO_INIT),
+          mContextHubModule(nullptr),
+          mIsTransactionPending(false) {
+    const hw_module_t *module;
+
+    mInitCheck = hw_get_module(CONTEXT_HUB_MODULE_ID, &module);
+
+    if (mInitCheck != OK) {
+        ALOGE("Could not load %s module: %s", CONTEXT_HUB_MODULE_ID, strerror(-mInitCheck));
+    } else if (module == nullptr) {
+        ALOGE("hal returned succes but a null module!");
+        // Assign an error, this should not really happen...
+        mInitCheck = UNKNOWN_ERROR;
+    } else {
+        ALOGI("Loaded Context Hub module");
+        mContextHubModule = reinterpret_cast<const context_hub_module_t *>(module);
+    }
+}
+
+bool Contexthub::setOsAppAsDestination(hub_message_t *msg, int hubId) {
+    if (!isValidHubId(hubId)) {
+        ALOGW("%s: Hub information is null for hubHandle %d",
+              __FUNCTION__,
+              hubId);
+        return false;
+    } else {
+        msg->app_name = mCachedHubInfo[hubId].osAppName;
+        return true;
+    }
+}
+
+Return<void> Contexthub::getHubs(getHubs_cb _hidl_cb) {
+    std::vector<ContextHub> hubs;
+    if (isInitialized()) {
+        const context_hub_t *hubArray = nullptr;
+        size_t numHubs;
+
+        // Explicitly discarding const. HAL method discards it.
+        numHubs = mContextHubModule->get_hubs(const_cast<context_hub_module_t *>(mContextHubModule),
+                                              &hubArray);
+        ALOGI("Context Hub Hal Adapter reports %zu hubs", numHubs);
+
+        mCachedHubInfo.clear();
+
+        for (size_t i = 0; i < numHubs; i++) {
+            CachedHubInformation info;
+            ContextHub c;
+
+            c.hubId = hubArray[i].hub_id;
+            c.name = hubArray[i].name;
+            c.vendor = hubArray[i].vendor;
+            c.toolchain = hubArray[i].toolchain;
+            c.toolchainVersion = hubArray[i].toolchain_version;
+            c.platformVersion = hubArray[i].platform_version;
+            c.maxSupportedMsgLen = hubArray[i].max_supported_msg_len;
+            c.peakMips = hubArray[i].peak_mips;
+            c.peakPowerDrawMw = hubArray[i].peak_power_draw_mw;
+            c.stoppedPowerDrawMw = hubArray[i].stopped_power_draw_mw;
+            c.sleepPowerDrawMw = hubArray[i].sleep_power_draw_mw;
+
+            info.callBack = nullptr;
+            info.osAppName = hubArray[i].os_app_name;
+            mCachedHubInfo[hubArray[i].hub_id] = info;
+
+            hubs.push_back(c);
+        }
+    } else {
+        ALOGW("Context Hub Hal Adapter not initialized");
+    }
+
+    _hidl_cb(hubs);
+    return Void();
+}
+
+bool Contexthub::isValidHubId(uint32_t hubId) {
+    if (!mCachedHubInfo.count(hubId)) {
+        ALOGW("Hub information not found for hubId %" PRIu32, hubId);
+        return false;
+    } else {
+        return true;
+    }
+}
+
+sp<IContexthubCallback> Contexthub::getCallBackForHubId(uint32_t hubId) {
+    if (!isValidHubId(hubId)) {
+        return nullptr;
+    } else {
+        return mCachedHubInfo[hubId].callBack;
+    }
+}
+
+Return<Result> Contexthub::sendMessageToHub(uint32_t hubId,
+                                            const ContextHubMsg &msg) {
+    if (!isInitialized()) {
+        return Result::NOT_INIT;
+    }
+
+    if (!isValidHubId(hubId) || msg.msg.size() > UINT32_MAX) {
+        return Result::BAD_PARAMS;
+    }
+
+    hub_message_t txMsg = {
+        .app_name.id = msg.appName,
+        .message_type = msg.msgType,
+        .message_len = static_cast<uint32_t>(msg.msg.size()), // Note the check above
+        .message = static_cast<const uint8_t *>(msg.msg.data()),
+    };
+
+    ALOGI("Sending msg of type %" PRIu32 ", size %" PRIu32 " to app 0x%" PRIx64,
+          txMsg.message_type,
+          txMsg.message_len,
+          txMsg.app_name.id);
+
+    if(mContextHubModule->send_message(hubId, &txMsg) != 0) {
+        return Result::TRANSACTION_FAILED;
+    }
+
+    return Result::OK;
+}
+
+Return<Result> Contexthub::reboot(uint32_t hubId) {
+    if (!isInitialized()) {
+      return Result::NOT_INIT;
+    }
+
+    hub_message_t msg;
+
+    if (setOsAppAsDestination(&msg, hubId) == false) {
+        return Result::BAD_PARAMS;
+    }
+
+    msg.message_type = CONTEXT_HUB_OS_REBOOT;
+    msg.message_len = 0;
+    msg.message = nullptr;
+
+    if(mContextHubModule->send_message(hubId, &msg) != 0) {
+        return Result::TRANSACTION_FAILED;
+    } else {
+        return Result::OK;
+    }
+}
+
+Return<Result> Contexthub::registerCallback(uint32_t hubId,
+                                            const sp<IContexthubCallback> &cb) {
+    Return<Result> retVal = Result::BAD_PARAMS;
+
+    if (!isInitialized()) {
+        // Not initilalized
+        ALOGW("Context hub not initialized successfully");
+        retVal = Result::NOT_INIT;
+    } else if (!isValidHubId(hubId)) {
+        // Initialized, but hubId is  not valid
+        retVal = Result::BAD_PARAMS;
+    } else if (mContextHubModule->subscribe_messages(hubId,
+                                                     contextHubCb,
+                                                     this) == 0) {
+        // Initialized && valid hub && subscription successful
+        retVal = Result::OK;
+        mCachedHubInfo[hubId].callBack = cb;
+    } else {
+        // Initalized && valid hubId - but subscription unsuccessful
+        // This is likely an internal error in the HAL implementation, but we
+        // cannot add more information.
+        ALOGW("Could not subscribe to the hub for callback");
+        retVal = Result::UNKNOWN_FAILURE;
+    }
+
+    return retVal;
+}
+
+static bool isValidOsStatus(const uint8_t *msg,
+                            size_t msgLen,
+                            status_response_t *rsp) {
+    // Workaround a bug in some HALs
+    if (msgLen == 1) {
+        rsp->result = msg[0];
+        return true;
+    }
+
+    if (msg == nullptr || msgLen != sizeof(*rsp)) {
+        ALOGI("Received invalid response (is null : %d, size %zu)",
+              msg == nullptr ? 1 : 0,
+              msgLen);
+        return false;
+    }
+
+    memcpy(rsp, msg, sizeof(*rsp));
+
+    // No sanity checks on return values
+    return true;
+}
+
+int Contexthub::handleOsMessage(sp<IContexthubCallback> cb,
+                                uint32_t msgType,
+                                const uint8_t *msg,
+                                int msgLen) {
+    int retVal = -1;
+
+
+    switch(msgType) {
+        case CONTEXT_HUB_APPS_ENABLE:
+        case CONTEXT_HUB_APPS_DISABLE:
+        case CONTEXT_HUB_LOAD_APP:
+        case CONTEXT_HUB_UNLOAD_APP:
+        {
+            struct status_response_t rsp;
+            TransactionResult result;
+            if (isValidOsStatus(msg, msgLen, &rsp) && rsp.result == 0) {
+                retVal = 0;
+                result = TransactionResult::SUCCESS;
+            } else {
+                result = TransactionResult::FAILURE;
+            }
+
+            if (cb != nullptr) {
+                cb->handleTxnResult(mTransactionId, result);
+            }
+            retVal = 0;
+            mIsTransactionPending = false;
+            break;
+        }
+
+        case CONTEXT_HUB_QUERY_APPS:
+        {
+            std::vector<HubAppInfo> apps;
+            int numApps = msgLen / sizeof(hub_app_info);
+            const hub_app_info *unalignedInfoAddr = reinterpret_cast<const hub_app_info *>(msg);
+
+            for (int i = 0; i < numApps; i++) {
+                hub_app_info query_info;
+                memcpy(&query_info, &unalignedInfoAddr[i], sizeof(query_info));
+                HubAppInfo app;
+                app.appId = query_info.app_name.id;
+                app.version = query_info.version;
+                // TODO :: Add memory ranges
+
+                apps.push_back(app);
+            }
+
+            if (cb != nullptr) {
+                cb->handleAppsInfo(apps);
+            }
+            retVal = 0;
+            break;
+        }
+
+        case CONTEXT_HUB_QUERY_MEMORY:
+        {
+            // Deferring this use
+            retVal = 0;
+            break;
+        }
+
+        case CONTEXT_HUB_OS_REBOOT:
+        {
+            mIsTransactionPending = false;
+            if (cb != nullptr) {
+                cb->handleHubEvent(AsyncEventType::RESTARTED);
+            }
+            retVal = 0;
+            break;
+        }
+
+        default:
+        {
+            retVal = -1;
+            break;
+        }
+      }
+
+      return retVal;
+}
+
+int Contexthub::contextHubCb(uint32_t hubId,
+                             const struct hub_message_t *rxMsg,
+                             void *cookie) {
+    Contexthub *obj = static_cast<Contexthub *>(cookie);
+
+    if (rxMsg == nullptr) {
+        ALOGW("Ignoring NULL message");
+        return -1;
+    }
+
+    if (!obj->isValidHubId(hubId)) {
+        ALOGW("Invalid hub Id %" PRIu32, hubId);
+        return -1;
+    }
+
+    sp<IContexthubCallback> cb = obj->getCallBackForHubId(hubId);
+
+    if (cb == nullptr) {
+        // This should not ever happen
+        ALOGW("No callback registered, returning");
+        return -1;
+    }
+
+    if (rxMsg->message_type < CONTEXT_HUB_TYPE_PRIVATE_MSG_BASE) {
+        obj->handleOsMessage(cb,
+                             rxMsg->message_type,
+                             static_cast<const uint8_t *>(rxMsg->message),
+                             rxMsg->message_len);
+    } else {
+        ContextHubMsg msg;
+
+        msg.appName = rxMsg->app_name.id;
+        msg.msgType = rxMsg->message_type;
+        msg.msg = std::vector<uint8_t>(static_cast<const uint8_t *>(rxMsg->message),
+                                       static_cast<const uint8_t *>(rxMsg->message) +
+                                       rxMsg->message_len);
+
+        cb->handleClientMsg(msg);
+    }
+
+    return 0;
+}
+
+Return<Result> Contexthub::unloadNanoApp(uint32_t hubId,
+                                         uint64_t appId,
+                                         uint32_t transactionId) {
+    if (!isInitialized()) {
+      return Result::NOT_INIT;
+    }
+
+    if (mIsTransactionPending) {
+        return Result::TRANSACTION_PENDING;
+    }
+
+    hub_message_t msg;
+
+    if (setOsAppAsDestination(&msg, hubId) == false) {
+        return Result::BAD_PARAMS;
+    }
+
+    struct apps_disable_request_t req;
+
+    msg.message_type = CONTEXT_HUB_UNLOAD_APP;
+    msg.message_len = sizeof(req);
+    msg.message = &req;
+    req.app_name.id = appId;
+
+    if(mContextHubModule->send_message(hubId, &msg) != 0) {
+        return Result::TRANSACTION_FAILED;
+    } else {
+        mTransactionId = transactionId;
+        mIsTransactionPending = true;
+        return Result::OK;
+    }
+}
+
+Return<Result> Contexthub::loadNanoApp(uint32_t hubId,
+                                       const ::android::hardware::hidl_vec<uint8_t>& appBinary,
+                                       uint32_t transactionId) {
+    if (!isInitialized()) {
+      return Result::NOT_INIT;
+    }
+
+    if (mIsTransactionPending) {
+        return Result::TRANSACTION_PENDING;
+    }
+
+    hub_message_t hubMsg;
+
+    if (setOsAppAsDestination(&hubMsg, hubId) == false) {
+        return Result::BAD_PARAMS;
+    }
+
+    hubMsg.message_type = CONTEXT_HUB_LOAD_APP;
+    hubMsg.message_len = appBinary.size();
+    hubMsg.message = appBinary.data();
+
+    if(mContextHubModule->send_message(hubId, &hubMsg) != 0) {
+        return Result::TRANSACTION_FAILED;
+    } else {
+        mTransactionId = transactionId;
+        mIsTransactionPending = true;
+        return Result::OK;
+    }
+}
+
+Return<Result> Contexthub::enableNanoApp(uint32_t hubId,
+                                         uint64_t appId,
+                                         uint32_t transactionId) {
+    if (!isInitialized()) {
+      return Result::NOT_INIT;
+    }
+
+    if (mIsTransactionPending) {
+        return Result::TRANSACTION_PENDING;
+    }
+
+    hub_message_t msg;
+
+    if (setOsAppAsDestination(&msg, hubId) == false) {
+        return Result::BAD_PARAMS;
+    }
+
+    struct apps_enable_request_t req;
+
+    msg.message_type = CONTEXT_HUB_APPS_ENABLE;
+    msg.message_len = sizeof(req);
+    req.app_name.id = appId;
+    msg.message = &req;
+
+    if(mContextHubModule->send_message(hubId, &msg) != 0) {
+        return Result::TRANSACTION_FAILED;
+    } else {
+        mTransactionId = transactionId;
+        mIsTransactionPending = true;
+        return Result::OK;
+    }
+}
+
+Return<Result> Contexthub::disableNanoApp(uint32_t hubId,
+                                          uint64_t appId,
+                                          uint32_t transactionId) {
+    if (!isInitialized()) {
+      return Result::NOT_INIT;
+    }
+
+    if (mIsTransactionPending) {
+        return Result::TRANSACTION_PENDING;
+    }
+
+    hub_message_t msg;
+
+    if (setOsAppAsDestination(&msg, hubId) == false) {
+        return Result::BAD_PARAMS;
+    }
+
+    struct apps_disable_request_t req;
+
+    msg.message_type = CONTEXT_HUB_APPS_DISABLE;
+    msg.message_len = sizeof(req);
+    req.app_name.id = appId;
+    msg.message = &req;
+
+    if(mContextHubModule->send_message(hubId, &msg) != 0) {
+        return Result::TRANSACTION_FAILED;
+    } else {
+        mTransactionId = transactionId;
+        mIsTransactionPending = true;
+        return Result::OK;
+    }
+}
+
+Return<Result> Contexthub::queryApps(uint32_t hubId) {
+    if (!isInitialized()) {
+      return Result::NOT_INIT;
+    }
+
+    hub_message_t msg;
+
+    if (setOsAppAsDestination(&msg, hubId) == false) {
+        ALOGW("Could not find hubId %" PRIu32, hubId);
+        return Result::BAD_PARAMS;
+    }
+
+    query_apps_request_t payload;
+    payload.app_name.id = ALL_APPS; // TODO : Pass this in as a parameter
+    msg.message = &payload;
+    msg.message_len = sizeof(payload);
+    msg.message_type = CONTEXT_HUB_QUERY_APPS;
+
+    if(mContextHubModule->send_message(hubId, &msg) != 0) {
+        ALOGW("Query Apps sendMessage failed");
+        return Result::TRANSACTION_FAILED;
+    }
+
+    return Result::OK;
+}
+
+bool Contexthub::isInitialized() {
+    return (mInitCheck == OK && mContextHubModule != nullptr);
+}
+
+IContexthub *HIDL_FETCH_IContexthub(const char * halName) {
+    ALOGI("%s Called for %s", __FUNCTION__, halName);
+    Contexthub *contexthub = new Contexthub;
+
+    if (!contexthub->isInitialized()) {
+        delete contexthub;
+        contexthub = nullptr;
+    }
+
+    return contexthub;
+}
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace contexthub
+}  // namespace hardware
+}  // namespace android
diff --git a/contexthub/1.0/default/Contexthub.h b/contexthub/1.0/default/Contexthub.h
new file mode 100644
index 0000000..0883ce8
--- /dev/null
+++ b/contexthub/1.0/default/Contexthub.h
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_CONTEXTHUB_V1_0_CONTEXTHUB_H_
+#define ANDROID_HARDWARE_CONTEXTHUB_V1_0_CONTEXTHUB_H_
+
+#include <unordered_map>
+
+#include <android/hardware/contexthub/1.0/IContexthub.h>
+#include <hardware/context_hub.h>
+
+namespace android {
+namespace hardware {
+namespace contexthub {
+namespace V1_0 {
+namespace implementation {
+
+struct Contexthub : public ::android::hardware::contexthub::V1_0::IContexthub {
+    Contexthub();
+
+    Return<void> getHubs(getHubs_cb _hidl_cb) override;
+
+    Return<Result> registerCallback(uint32_t hubId,
+                                    const sp<IContexthubCallback> &cb) override;
+
+    Return<Result> sendMessageToHub(uint32_t hubId,
+                                    const ContextHubMsg &msg) override;
+
+    Return<Result> loadNanoApp(uint32_t hubId,
+                               const ::android::hardware::hidl_vec<uint8_t>& appBinary,
+                               uint32_t transactionId) override;
+
+    Return<Result> unloadNanoApp(uint32_t hubId,
+                                 uint64_t appId,
+                                 uint32_t transactionId) override;
+
+    Return<Result> enableNanoApp(uint32_t hubId,
+                                 uint64_t appId,
+                                 uint32_t transactionId) override;
+
+    Return<Result> disableNanoApp(uint32_t hubId,
+                                  uint64_t appId,
+                                  uint32_t transactionId) override;
+
+    Return<Result> queryApps(uint32_t hubId) override;
+
+    Return<Result> reboot(uint32_t hubId);
+
+    bool isInitialized();
+
+private:
+
+    struct CachedHubInformation{
+        struct hub_app_name_t osAppName;
+        sp<IContexthubCallback> callBack;
+    };
+
+    status_t mInitCheck;
+    const struct context_hub_module_t *mContextHubModule;
+    std::unordered_map<uint32_t, CachedHubInformation> mCachedHubInfo;
+
+    sp<IContexthubCallback> mCb;
+    bool mIsTransactionPending;
+    uint32_t mTransactionId;
+
+    bool isValidHubId(uint32_t hubId);
+
+    sp<IContexthubCallback> getCallBackForHubId(uint32_t hubId);
+
+    int handleOsMessage(sp<IContexthubCallback> cb,
+                        uint32_t msgType,
+                        const uint8_t *msg,
+                        int msgLen);
+
+    static int contextHubCb(uint32_t hubId,
+                            const struct hub_message_t *rxMsg,
+                            void *cookie);
+
+    bool setOsAppAsDestination(hub_message_t *msg, int hubId);
+
+    DISALLOW_COPY_AND_ASSIGN(Contexthub);
+};
+
+extern "C" IContexthub *HIDL_FETCH_IContexthub(const char *name);
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace contexthub
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_CONTEXTHUB_V1_0_CONTEXTHUB_H_
diff --git a/contexthub/1.0/default/android.hardware.contexthub@1.0-service.rc b/contexthub/1.0/default/android.hardware.contexthub@1.0-service.rc
new file mode 100644
index 0000000..8dba85f
--- /dev/null
+++ b/contexthub/1.0/default/android.hardware.contexthub@1.0-service.rc
@@ -0,0 +1,4 @@
+service contexthub-hal-1-0 /system/bin/hw/android.hardware.contexthub@1.0-service
+    class hal
+    user system
+    group system
diff --git a/contexthub/1.0/default/service.cpp b/contexthub/1.0/default/service.cpp
new file mode 100644
index 0000000..db9a4e7
--- /dev/null
+++ b/contexthub/1.0/default/service.cpp
@@ -0,0 +1,27 @@
+/*
+ * 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 "android.hardware.contexthub@1.0-service"
+
+#include <android/hardware/contexthub/1.0/IContexthub.h>
+#include <hidl/LegacySupport.h>
+
+using android::hardware::contexthub::V1_0::IContexthub;
+using android::hardware::defaultPassthroughServiceImplementation;
+
+int main() {
+    return defaultPassthroughServiceImplementation<IContexthub>("context_hub");
+}
diff --git a/contexthub/1.0/types.hal b/contexthub/1.0/types.hal
index b9f014b..043bb39 100644
--- a/contexthub/1.0/types.hal
+++ b/contexthub/1.0/types.hal
@@ -18,6 +18,7 @@
 
 enum Result : uint32_t {
     OK,                  // Success
+    UNKNOWN_FAILURE,     // Failure, unknown reason
     BAD_PARAMS,          // Parameters not sane
     NOT_INIT,            // not initialized
     TRANSACTION_FAILED,  // transaction failed
diff --git a/contexthub/Android.bp b/contexthub/Android.bp
index bbb3e4b..ba90f2c 100644
--- a/contexthub/Android.bp
+++ b/contexthub/Android.bp
@@ -1,4 +1,5 @@
 // This is an autogenerated file, do not edit.
 subdirs = [
     "1.0",
+    "1.0/default",
 ]
diff --git a/drm/crypto/1.0/ICryptoFactory.hal b/drm/crypto/1.0/ICryptoFactory.hal
index 58f86df..0ac7828 100644
--- a/drm/crypto/1.0/ICryptoFactory.hal
+++ b/drm/crypto/1.0/ICryptoFactory.hal
@@ -25,7 +25,7 @@
  * which are used by a codec to decrypt protected video content.
  */
 interface ICryptoFactory {
-    /*
+    /**
      * Determine if a crypto scheme is supported by this HAL
      *
      * @param uuid identifies the crypto scheme in question
@@ -33,23 +33,17 @@
      */
     isCryptoSchemeSupported(uint8_t[16] uuid) generates(bool isSupported);
 
-    /*
+    /**
      * Create a crypto plugin for the specified uuid and scheme-specific
      * initialization data.
      *
      * @param uuid uniquely identifies the drm scheme. See
      * http://dashif.org/identifiers/protection for uuid assignments
      * @param initData scheme-specific init data.
-     * @return the status of the call
-     * @return the created ICryptoPlugin
-    */
+     * @return status the status of the call. If the plugin can't
+     * be created, the HAL implementation must return ERROR_DRM_CANNOT_HANDLE.
+     * @return cryptoPlugin the created ICryptoPlugin
+     */
     createPlugin(uint8_t[16] uuid, vec<uint8_t> initData)
         generates (Status status, ICryptoPlugin cryptoPlugin);
-
-    /*
-     * Destroy a previously created crypto plugin
-     *
-     * @return status the status of the call
-     */
-    destroyPlugin() generates(Status status);
 };
diff --git a/drm/crypto/1.0/ICryptoPlugin.hal b/drm/crypto/1.0/ICryptoPlugin.hal
index 1255fdb..e86c9f2 100644
--- a/drm/crypto/1.0/ICryptoPlugin.hal
+++ b/drm/crypto/1.0/ICryptoPlugin.hal
@@ -25,7 +25,7 @@
  * load crypto keys for a codec to decrypt protected video content.
  */
 interface ICryptoPlugin {
-    /*
+    /**
      * Check if the specified mime-type requires a secure decoder
      * component.
      *
@@ -36,7 +36,7 @@
     requiresSecureDecoderComponent(string mime)
         generates(bool secureRequired);
 
-    /*
+    /**
      * Notify a plugin of the currently configured resolution
      *
      * @param width - the display resolutions's width
@@ -44,16 +44,19 @@
      */
     notifyResolution(uint32_t width, uint32_t height);
 
-    /*
+    /**
      * Associate a mediadrm session with this crypto session
      *
      * @param sessionId the MediaDrm session ID to associate with this crypto
      * session
-     * @return the status of the call
+     * @return status the status of the call, status must be
+     * ERROR_DRM_SESSION_NOT_OPENED if the session is not opened, or
+     * ERROR_DRM_CANNOT_HANDLE if the operation is not supported by the drm
+     * scheme.
      */
     setMediaDrmSession(vec<uint8_t> sessionId) generates(Status status);
 
-    /*
+    /**
      * Decrypt an array of subsamples from the source memory buffer to the
      * destination memory buffer.
      *
@@ -71,7 +74,14 @@
      * call to operate on a range of subsamples in a single call
      * @param source the input buffer for the decryption
      * @param destination the output buffer for the decryption
-     * @return status the status of the call
+     * @return status the status of the call. The status must be one of
+     * the following: ERROR_DRM_NO_LICENSE if no license keys have been
+     * loaded, ERROR_DRM_LICENSE_EXPIRED if the license keys have expired,
+     * ERROR_DRM_RESOURCE_BUSY if the resources required to perform the
+     * decryption are not available, ERROR_DRM_INSUFFICIENT_OUTPUT_PROTECTION
+     * if required output protections are not active,
+     * ERROR_DRM_SESSION_NOT_OPENED if the decrypt session is not opened, or
+     * ERROR_DRM_CANNOT_HANDLE in other failure cases.
      * @return bytesWritten the number of bytes output from the decryption
      * @return detailedError if the error is a vendor-specific error, the
      * vendor's crypto HAL may provide a detailed error string to help
diff --git a/drm/crypto/1.0/default/Android.mk b/drm/crypto/1.0/default/Android.mk
new file mode 100644
index 0000000..83794ac
--- /dev/null
+++ b/drm/crypto/1.0/default/Android.mk
@@ -0,0 +1,41 @@
+# 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 $(CLEAR_VARS)
+LOCAL_MODULE := android.hardware.drm.crypto@1.0-impl
+LOCAL_MODULE_RELATIVE_PATH := hw
+LOCAL_SRC_FILES := \
+    CryptoFactory.cpp \
+    CryptoPlugin.cpp \
+    TypeConvert.cpp \
+
+LOCAL_SHARED_LIBRARIES := \
+    libhidlbase \
+    libhidltransport \
+    libhwbinder \
+    libhidlmemory \
+    libutils \
+    liblog \
+    libmediadrm \
+    libstagefright_foundation \
+    android.hardware.drm.crypto@1.0 \
+    android.hidl.memory@1.0
+
+LOCAL_C_INCLUDES := \
+    frameworks/native/include \
+    frameworks/av/include
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/drm/crypto/1.0/default/CryptoFactory.cpp b/drm/crypto/1.0/default/CryptoFactory.cpp
new file mode 100644
index 0000000..e67a990
--- /dev/null
+++ b/drm/crypto/1.0/default/CryptoFactory.cpp
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "CryptoFactory.h"
+#include "CryptoPlugin.h"
+#include "TypeConvert.h"
+#include <utils/Log.h>
+
+namespace android {
+namespace hardware {
+namespace drm {
+namespace crypto {
+namespace V1_0 {
+namespace implementation {
+
+    CryptoFactory::CryptoFactory() :
+        loader("/vendor/lib/mediadrm", "createCryptoFactory", "crypto") {}
+
+    // Methods from ::android::hardware::drm::crypto::V1_0::ICryptoFactory follow.
+    Return<bool> CryptoFactory::isCryptoSchemeSupported(
+            const hidl_array<uint8_t, 16>& uuid) {
+        for (size_t i = 0; i < loader.factoryCount(); i++) {
+            if (loader.getFactory(i)->isCryptoSchemeSupported(uuid.data())) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    Return<void> CryptoFactory::createPlugin(const hidl_array<uint8_t, 16>& uuid,
+            const hidl_vec<uint8_t>& initData, createPlugin_cb _hidl_cb) {
+
+        for (size_t i = 0; i < loader.factoryCount(); i++) {
+            if (loader.getFactory(i)->isCryptoSchemeSupported(uuid.data())) {
+                android::CryptoPlugin *legacyPlugin = NULL;
+                status_t status = loader.getFactory(i)->createPlugin(uuid.data(),
+                        initData.data(), initData.size(), &legacyPlugin);
+                CryptoPlugin *newPlugin = NULL;
+                if (legacyPlugin == NULL) {
+                    ALOGE("Crypto legacy HAL: failed to create crypto plugin");
+                } else {
+                    newPlugin = new CryptoPlugin(legacyPlugin);
+                }
+                _hidl_cb(toStatus(status), newPlugin);
+                return Void();
+            }
+        }
+        _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, NULL);
+        return Void();
+    }
+
+    ICryptoFactory* HIDL_FETCH_ICryptoFactory(const char /* *name */) {
+        return new CryptoFactory();
+    }
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace crypto
+}  // namespace drm
+}  // namespace hardware
+}  // namespace android
diff --git a/drm/crypto/1.0/default/CryptoFactory.h b/drm/crypto/1.0/default/CryptoFactory.h
new file mode 100644
index 0000000..0855996
--- /dev/null
+++ b/drm/crypto/1.0/default/CryptoFactory.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef ANDROID_HARDWARE_DRM_CRYPTO_V1_0__CRYPTOFACTORY_H
+#define ANDROID_HARDWARE_DRM_CRYPTO_V1_0__CRYPTOFACTORY_H
+
+#include <android/hardware/drm/crypto/1.0/ICryptoFactory.h>
+#include <hidl/Status.h>
+#include <media/hardware/CryptoAPI.h>
+#include <media/PluginLoader.h>
+#include <media/SharedLibrary.h>
+
+namespace android {
+namespace hardware {
+namespace drm {
+namespace crypto {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::drm::crypto::V1_0::ICryptoFactory;
+using ::android::hardware::drm::crypto::V1_0::ICryptoPlugin;
+using ::android::hardware::hidl_array;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::sp;
+
+struct CryptoFactory : public ICryptoFactory {
+    CryptoFactory();
+    virtual ~CryptoFactory() {}
+
+    // Methods from ::android::hardware::drm::crypto::V1_0::ICryptoFactory follow.
+
+    Return<bool> isCryptoSchemeSupported(const hidl_array<uint8_t, 16>& uuid)
+            override;
+
+    Return<void> createPlugin(const hidl_array<uint8_t, 16>& uuid,
+            const hidl_vec<uint8_t>& initData, createPlugin_cb _hidl_cb)
+            override;
+
+private:
+    android::PluginLoader<android::CryptoFactory> loader;
+
+    CryptoFactory(const CryptoFactory &) = delete;
+    void operator=(const CryptoFactory &) = delete;
+};
+
+extern "C" ICryptoFactory* HIDL_FETCH_ICryptoFactory(const char* name);
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace crypto
+}  // namespace drm
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_DRM_CRYPTO_V1_0__CRYPTOFACTORY_H
diff --git a/drm/crypto/1.0/default/CryptoPlugin.cpp b/drm/crypto/1.0/default/CryptoPlugin.cpp
new file mode 100644
index 0000000..9173d5b
--- /dev/null
+++ b/drm/crypto/1.0/default/CryptoPlugin.cpp
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "CryptoPlugin.h"
+#include "TypeConvert.h"
+
+#include <media/stagefright/foundation/AString.h>
+
+#include <hidlmemory/mapping.h>
+#include <android/hidl/memory/1.0/IMemory.h>
+
+using android::hidl::memory::V1_0::IMemory;
+
+
+namespace android {
+namespace hardware {
+namespace drm {
+namespace crypto {
+namespace V1_0 {
+namespace implementation {
+
+    // Methods from ::android::hardware::drm::crypto::V1_0::ICryptoPlugin follow
+    Return<bool> CryptoPlugin::requiresSecureDecoderComponent(
+            const hidl_string& mime) {
+        return mLegacyPlugin->requiresSecureDecoderComponent(mime);
+    }
+
+    Return<void> CryptoPlugin::notifyResolution(uint32_t width,
+            uint32_t height) {
+        mLegacyPlugin->notifyResolution(width, height);
+        return Void();
+    }
+
+    Return<Status> CryptoPlugin::setMediaDrmSession(
+            const hidl_vec<uint8_t>& sessionId) {
+        return toStatus(mLegacyPlugin->setMediaDrmSession(toVector(sessionId)));
+    }
+
+    Return<void> CryptoPlugin::decrypt(bool secure,
+            const hidl_array<uint8_t, 16>& keyId,
+            const hidl_array<uint8_t, 16>& iv, Mode mode,
+            const Pattern& pattern, const hidl_vec<SubSample>& subSamples,
+            const hidl_memory &source, const DestinationBuffer& destination,
+            decrypt_cb _hidl_cb) {
+
+        android::CryptoPlugin::Mode legacyMode;
+        switch(mode) {
+        case Mode::UNENCRYPTED:
+            legacyMode = android::CryptoPlugin::kMode_Unencrypted;
+            break;
+        case Mode::AES_CTR:
+            legacyMode = android::CryptoPlugin::kMode_AES_CTR;
+            break;
+        case Mode::AES_CBC_CTS:
+            legacyMode = android::CryptoPlugin::kMode_AES_WV;
+            break;
+        case Mode::AES_CBC:
+            legacyMode = android::CryptoPlugin::kMode_AES_CBC;
+            break;
+        }
+        android::CryptoPlugin::Pattern legacyPattern;
+        legacyPattern.mEncryptBlocks = pattern.encryptBlocks;
+        legacyPattern.mSkipBlocks = pattern.skipBlocks;
+
+        android::CryptoPlugin::SubSample *legacySubSamples =
+            new android::CryptoPlugin::SubSample[subSamples.size()];
+
+        for (size_t i = 0; i < subSamples.size(); i++) {
+            legacySubSamples[i].mNumBytesOfClearData
+                = subSamples[i].numBytesOfClearData;
+            legacySubSamples[i].mNumBytesOfEncryptedData
+                = subSamples[i].numBytesOfEncryptedData;
+        }
+
+        AString detailMessage;
+
+        void *destPtr = NULL;
+        sp<IMemory> sharedMemory;
+
+        if (destination.type == BufferType::SHARED_MEMORY) {
+            sharedMemory = mapMemory(source);
+            destPtr = sharedMemory->getPointer();
+            sharedMemory->update();
+        } else if (destination.type == BufferType::NATIVE_HANDLE) {
+            native_handle_t *handle = const_cast<native_handle_t *>(
+                    destination.secureMemory.getNativeHandle());
+            destPtr = static_cast<void *>(handle);
+        }
+        ssize_t result = mLegacyPlugin->decrypt(secure, keyId.data(), iv.data(),
+                legacyMode, legacyPattern, sharedMemory->getPointer(),
+                legacySubSamples, subSamples.size(), destPtr, &detailMessage);
+
+        if (destination.type == BufferType::SHARED_MEMORY) {
+            sharedMemory->commit();
+        }
+        delete[] legacySubSamples;
+
+        uint32_t status;
+        uint32_t bytesWritten;
+
+        if (result >= 0) {
+            status = android::OK;
+            bytesWritten = result;
+        } else {
+            status = -result;
+            bytesWritten = 0;
+        }
+
+        _hidl_cb(toStatus(status), bytesWritten, detailMessage.c_str());
+        return Void();
+    }
+
+} // namespace implementation
+}  // namespace V1_0
+}  // namespace crypto
+}  // namespace drm
+}  // namespace hardware
+}  // namespace android
diff --git a/drm/crypto/1.0/default/CryptoPlugin.h b/drm/crypto/1.0/default/CryptoPlugin.h
new file mode 100644
index 0000000..b17dade
--- /dev/null
+++ b/drm/crypto/1.0/default/CryptoPlugin.h
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_DRM_CRYPTO_V1_0__CRYPTOPLUGIN_H
+#define ANDROID_HARDWARE_DRM_CRYPTO_V1_0__CRYPTOPLUGIN_H
+
+#include <media/hardware/CryptoAPI.h>
+#include <android/hardware/drm/crypto/1.0/ICryptoPlugin.h>
+#include <hidl/Status.h>
+
+namespace android {
+namespace hardware {
+namespace drm {
+namespace crypto {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::drm::crypto::V1_0::DestinationBuffer;
+using ::android::hardware::drm::crypto::V1_0::ICryptoPlugin;
+using ::android::hardware::drm::crypto::V1_0::Mode;
+using ::android::hardware::drm::crypto::V1_0::Pattern;
+using ::android::hardware::drm::crypto::V1_0::SubSample;
+using ::android::hardware::hidl_array;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::sp;
+
+struct CryptoPlugin : public ICryptoPlugin {
+    CryptoPlugin(android::CryptoPlugin *plugin) : mLegacyPlugin(plugin) {}
+    ~CryptoPlugin() {delete mLegacyPlugin;}
+
+    // Methods from ::android::hardware::drm::crypto::V1_0::ICryptoPlugin
+    // follow.
+
+    Return<bool> requiresSecureDecoderComponent(const hidl_string& mime)
+            override;
+
+    Return<void> notifyResolution(uint32_t width, uint32_t height) override;
+
+    Return<Status> setMediaDrmSession(const hidl_vec<uint8_t>& sessionId)
+            override;
+
+    Return<void> decrypt(bool secure, const hidl_array<uint8_t, 16>& keyId,
+            const hidl_array<uint8_t, 16>& iv, Mode mode, const Pattern& pattern,
+            const hidl_vec<SubSample>& subSamples, const hidl_memory& source,
+            const DestinationBuffer& destination, decrypt_cb _hidl_cb) override;
+
+private:
+    android::CryptoPlugin *mLegacyPlugin;
+
+    CryptoPlugin() = delete;
+    CryptoPlugin(const CryptoPlugin &) = delete;
+    void operator=(const CryptoPlugin &) = delete;
+};
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace crypto
+}  // namespace drm
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_DRM_CRYPTO_V1_0__CRYPTOPLUGIN_H
diff --git a/drm/crypto/1.0/default/TypeConvert.cpp b/drm/crypto/1.0/default/TypeConvert.cpp
new file mode 100644
index 0000000..d9cca6b
--- /dev/null
+++ b/drm/crypto/1.0/default/TypeConvert.cpp
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "TypeConvert.h"
+
+namespace android {
+namespace hardware {
+namespace drm {
+namespace crypto {
+namespace V1_0 {
+namespace implementation {
+
+Status toStatus(status_t legacyStatus) {
+    Status status;
+    switch(legacyStatus) {
+    case android::ERROR_DRM_NO_LICENSE:
+        status = Status::ERROR_DRM_NO_LICENSE;
+        break;
+    case android::ERROR_DRM_LICENSE_EXPIRED:
+        status = Status::ERROR_DRM_LICENSE_EXPIRED;
+        break;
+    case android::ERROR_DRM_RESOURCE_BUSY:
+        status = Status::ERROR_DRM_RESOURCE_BUSY;
+        break;
+    case android::ERROR_DRM_INSUFFICIENT_OUTPUT_PROTECTION:
+        status = Status::ERROR_DRM_INSUFFICIENT_OUTPUT_PROTECTION;
+        break;
+    case android::ERROR_DRM_SESSION_NOT_OPENED:
+        status = Status::ERROR_DRM_SESSION_NOT_OPENED;
+        break;
+    case android::ERROR_DRM_CANNOT_HANDLE:
+    case android::BAD_VALUE:
+        status = Status::ERROR_DRM_CANNOT_HANDLE;
+        break;
+    default:
+        ALOGW("Unable to convert legacy status: %d, defaulting to UNKNOWN",
+                legacyStatus);
+        status = Status::ERROR_UNKNOWN_CRYPTO_EXCEPTION;
+        break;
+    }
+    return status;
+}
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace crypto
+}  // namespace drm
+}  // namespace hardware
+}  // namespace android
diff --git a/drm/crypto/1.0/default/TypeConvert.h b/drm/crypto/1.0/default/TypeConvert.h
new file mode 100644
index 0000000..1655bab
--- /dev/null
+++ b/drm/crypto/1.0/default/TypeConvert.h
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_DRM_CRYPTO_V1_0_TYPECONVERT
+#define ANDROID_HARDWARE_DRM_CRYPTO_V1_0_TYPECONVERT
+
+#include <utils/Vector.h>
+#include <media/stagefright/MediaErrors.h>
+#include <media/hardware/CryptoAPI.h>
+
+#include <hidl/MQDescriptor.h>
+#include <android/hardware/drm/crypto/1.0/types.h>
+
+namespace android {
+namespace hardware {
+namespace drm {
+namespace crypto {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::hidl_vec;
+
+template<typename T> const hidl_vec<T> toHidlVec(const Vector<T> &Vector) {
+    hidl_vec<T> vec;
+    vec.setToExternal(const_cast<T *>(Vector.array()), Vector.size());
+    return vec;
+}
+
+template<typename T> hidl_vec<T> toHidlVec(Vector<T> &Vector) {
+    hidl_vec<T> vec;
+    vec.setToExternal(Vector.editArray(), Vector.size());
+    return vec;
+}
+
+template<typename T> const Vector<T> toVector(const hidl_vec<T> &vec) {
+    Vector<T> vector;
+    vector.appendArray(vec.data(), vec.size());
+    return *const_cast<const Vector<T> *>(&vector);
+}
+
+template<typename T> Vector<T> toVector(hidl_vec<T> &vec) {
+    Vector<T> vector;
+    vector.appendArray(vec.data(), vec.size());
+    return vector;
+}
+
+template<typename T, size_t SIZE> const Vector<T> toVector(
+        const hidl_array<T, SIZE> &array) {
+    Vector<T> vector;
+    vector.appendArray(array.data(), array.size());
+    return vector;
+}
+
+template<typename T, size_t SIZE> Vector<T> toVector(
+        hidl_array<T, SIZE> &array) {
+    Vector<T> vector;
+    vector.appendArray(array.data(), array.size());
+    return vector;
+}
+
+Status toStatus(status_t legacyStatus);
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace crypto
+}  // namespace drm
+}  // namespace hardware
+}  // namespace android
+
+#endif // ANDROID_HARDWARE_DRM_CRYPTO_V1_0_TYPECONVERT
diff --git a/drm/drm/1.0/IDrmFactory.hal b/drm/drm/1.0/IDrmFactory.hal
index a4ee0f1..a58bcaa 100644
--- a/drm/drm/1.0/IDrmFactory.hal
+++ b/drm/drm/1.0/IDrmFactory.hal
@@ -27,7 +27,7 @@
  */
 
 interface IDrmFactory {
-    /*
+    /**
      * Determine if a crypto scheme is supported by this HAL
      *
      * @param uuid identifies the crypto scheme in question
@@ -35,22 +35,16 @@
      */
     isCryptoSchemeSupported(uint8_t[16] uuid) generates(bool isSupported);
 
-    /*
+    /**
      * Create a drm plugin instance for the specified uuid and scheme-specific
      * initialization data.
      *
      * @param uuid uniquely identifies the drm scheme. See
      * http://dashif.org/identifiers/protection for uuid assignments
-     * @param initData scheme-specific init data.
-     * @return the status of the call
-     * @return the created IDrmPlugin
+     * @return status the status of the call. If the plugin can't be created,
+     * the HAL implementation must return ERROR_DRM_CANNOT_HANDLE.
+     * @return drmPlugin the created IDrmPlugin
      */
-    createPlugin(uint8_t[16] uuid, vec<uint8_t> initData)
-        generates (Status status, IDrmPlugin drmPlugin);
-
-    /*
-     * Destroy a previously created drm plugin
-     * @return status the status of the call
-     */
-    destroyPlugin() generates(Status status);
+    createPlugin(uint8_t[16] uuid) generates (Status status,
+            IDrmPlugin drmPlugin);
 };
diff --git a/drm/drm/1.0/IDrmPlugin.hal b/drm/drm/1.0/IDrmPlugin.hal
index 7f396d9..e847805 100644
--- a/drm/drm/1.0/IDrmPlugin.hal
+++ b/drm/drm/1.0/IDrmPlugin.hal
@@ -30,15 +30,25 @@
     /**
      * Open a new session with the DrmPlugin object. A session ID is returned
      * in the sessionId parameter.
-     * @return status the status of the call
+     * @return status the status of the call. The status must be one of
+     * ERROR_DRM_NOT_PROVISIONED if the device requires provisioning before
+     * it can open a session, ERROR_DRM_RESOURCE_BUSY if there are insufficent
+     * resources available to open a session, ERROR_DRM_CANNOT_HANDLE,
+     * if openSession is not supported at the time of the call or
+     * ERROR_DRM_INVALID_STATE if the HAL is in a state where a session cannot
+     * be opened.
+     * @return sessionId the session ID for the newly opened session
      */
-    openSession() generates (SessionId sessionId, Status status);
+    openSession() generates (Status status, SessionId sessionId);
 
     /**
      * Close a session on the DrmPlugin object
      *
      * @param sessionId the session id the call applies to
-     * @return status the status of the call
+     * @return status the status of the call.  The status must be one of
+     * ERROR_DRM_SESSION_NOT_OPENED if the session is not opened,
+     * BAD_VALUE if the sessionId is invalid or ERROR_DRM_INVALID_STATE
+     * if the HAL is in a state where the session cannot be closed.
      */
     closeSession(SessionId sessionId) generates (Status status);
 
@@ -65,6 +75,13 @@
      * allow a client application to provide additional message parameters to
      * the server.
      *
+     * @return status the status of the call.  The status must be one of
+     * ERROR_DRM_SESSION_NOT_OPENED if the session is not opened,
+     * ERROR_DRM_NOT_PROVISIONED if the device requires provisioning before
+     * it can generate a key request, ERROR_DRM_CANNOT_HANDLE if keyKeyRequest
+     * is not supported at the time of the call, BAD_VALUE if any parameters
+     * are invalid or ERROR_DRM_INVALID_STATE if the HAL is in a state where
+     * a key request cannot be generated.
      * @return request if successful, the opaque key request blob is returned
      * @return requestType indicates type information about the returned
      * request. The type may be one of INITIAL, RENEWAL or RELEASE. An
@@ -72,15 +89,14 @@
      * subsequent key request used to refresh the keys in a license. RELEASE
      * corresponds to a keyType of RELEASE, which indicates keys are being
      * released.
-     * @return status the status of the call
      * @return defaultUrl the URL that the request may be sent to, if
      * provided by the drm HAL. The app may choose to override this
      * URL.
      */
     getKeyRequest(vec<uint8_t> scope, vec<uint8_t> initData,
-        string mimeType, KeyType keyType, KeyedVector optionalParameters)
-        generates (vec<uint8_t> request, KeyRequestType requestType,
-            Status status, string defaultUrl);
+            string mimeType, KeyType keyType, KeyedVector optionalParameters)
+        generates (Status status, vec<uint8_t> request,
+                KeyRequestType requestType, string defaultUrl);
 
     /**
      * After a key response is received by the app, it is provided to the
@@ -93,22 +109,31 @@
      * @param response the response from the key server that is being
      * provided to the drm HAL.
      *
+     * @return status the status of the call.  The status must be one of
+     * ERROR_DRM_SESSION_NOT_OPENED if the session is not opened,
+     * ERROR_DRM_NOT_PROVISIONED if the device requires provisioning before
+     * it can handle the key response, ERROR_DRM_DEVICE_REVOKED if the device
+     * has been disabled by the license policy, ERROR_DRM_CANNOT_HANDLE if
+     * provideKeyResponse is not supported at the time of the call, BAD_VALUE
+     * if any parameters are invalid or ERROR_DRM_INVALID_STATE if the HAL is
+     * in a state where a key response cannot be handled.
      * @return keySetId when the response is for an offline key request, a
      * keySetId is returned in the keySetId vector parameter that can be used
      * to later restore the keys to a new session with the method restoreKeys.
      * When the response is for a streaming or release request, no keySetId is
      * returned.
-     *
-     * @return status the status of the call
      */
-    provideKeyResponse(vec<uint8_t> scope,
-        vec<uint8_t> response) generates (vec<uint8_t> keySetId, Status status);
+    provideKeyResponse(vec<uint8_t> scope, vec<uint8_t> response)
+        generates (Status status, vec<uint8_t> keySetId);
 
     /**
      * Remove the current keys from a session
      *
      * @param sessionId the session id the call applies to
-     * @return status the status of the call
+     * @return status the status of the call.  The status must be one of
+     * ERROR_DRM_SESSION_NOT_OPENED if the session is not opened,
+     * BAD_VALUE if the sessionId is invalid or ERROR_DRM_INVALID_STATE
+     * if the HAL is in a state where the keys cannot be removed.
      */
     removeKeys(SessionId sessionId) generates (Status status);
 
@@ -118,12 +143,15 @@
      * @param sessionId the session id the call applies to
      * @param keySetId identifies the keys to load, obtained from a prior
      * call to provideKeyResponse().
-     * @return status the status of the call
+     * @return status the status of the call. The status must be one of
+     * ERROR_DRM_SESSION_NOT_OPENED if the session is not opened,
+     * BAD_VALUE if any parameters are invalid or ERROR_DRM_INVALID_STATE
+     * if the HAL is in a state where keys cannot be restored.
      */
     restoreKeys(SessionId sessionId,
-        vec<uint8_t> keySetId) generates (Status status);
+            vec<uint8_t> keySetId) generates (Status status);
 
-    /*
+    /**
      * Request an informative description of the license for the session. The
      * status is in the form of {name, value} pairs. Since DRM license policies
      * vary by vendor, the specific status field names are determined by each
@@ -131,45 +159,61 @@
      * the field names for a particular drm scheme.
      *
      * @param sessionId the session id the call applies to
+     * @return status the status of the call. The status must be one of
+     * ERROR_DRM_SESSION_NOT_OPENED if the session is not opened,
+     * BAD_VALUE if the sessionId is invalid or ERROR_DRM_INVALID_STATE
+     * if the HAL is in a state where key status cannot be queried.
      * @return infoList a list of name value pairs describing the license
-     * @return status the status of the call
      */
     queryKeyStatus(SessionId sessionId)
-        generates (KeyedVector infoList, Status status);
+        generates (Status status, KeyedVector infoList);
 
     /**
      * A provision request/response exchange occurs between the app and a
      * provisioning server to retrieve a device certificate. getProvisionRequest
-     * is used to obtain an opaque key request blob that is delivered to the
-     * provisioning server.
+     * is used to obtain an opaque provisioning request blob that is delivered
+     * to the provisioning server.
      *
      * @param certificateType the type of certificate requested, e.g. "X.509"
      * @param certificateAuthority identifies the certificate authority. A
      * certificate authority (CA) is an entity which issues digital certificates
-     * for use by other parties. It is an example of a trusted third party
-     * @return if successful the opaque certirequest blob is returned
-     * @return status the status of the call
+     * for use by other parties. It is an example of a trusted third party.
+     * @return status the status of the call. The status must be one of
+     * BAD_VALUE if the sessionId is invalid or ERROR_DRM_INVALID_STATE
+     * if the HAL is in a state where the provision request cannot be
+     * generated.
+     * @return request if successful the opaque certificate request blob
+     * is returned
+     * @return defaultUrl URL that the provisioning request should be
+     * sent to, if known by the HAL implementation.  If the HAL implementation
+     * does not provide a defaultUrl, the returned string must be empty.
      */
     getProvisionRequest(string certificateType, string certificateAuthority)
-        generates (vec<uint8_t> request, string defaultUrl, Status status);
+        generates (Status status, vec<uint8_t> request, string defaultUrl);
 
     /**
      * After a provision response is received by the app from a provisioning
-     * server, it can be provided to the Drm HAL using provideProvisionResponse.
+     * server, it is provided to the Drm HAL using provideProvisionResponse.
+     * The HAL implementation must receive the provision request and
+     * store the provisioned credentials.
      *
      * @param response the opaque provisioning response received by the
-     * app from a provisioning server
+     * app from a provisioning server.
+
+     * @return status the status of the call. The status must be one of
+     * ERROR_DRM_DEVICE_REVOKED if the device has been disabled by the license
+     * policy, BAD_VALUE if any parameters are invalid or ERROR_DRM_INVALID_STATE
+     * if the HAL is in a state where the provision response cannot be
+     * handled.
      * @return certificate the public certificate resulting from the provisioning
      * operation, if any. An empty vector indicates that no certificate was
      * returned.
      * @return wrappedKey an opaque object containing encrypted private key
      * material to be used by signRSA when computing an RSA signature on a
      * message, see the signRSA method.
-     * @return status the status of the call
      */
-    provideProvisionResponse(vec<uint8_t> response)
-        generates (vec<uint8_t> certificate, vec<uint8_t> wrappedKey,
-            Status status);
+    provideProvisionResponse(vec<uint8_t> response) generates (Status status,
+            vec<uint8_t> certificate, vec<uint8_t> wrappedKey);
 
     /**
      * SecureStop is a way of enforcing the concurrent stream limit per
@@ -193,41 +237,50 @@
     /**
      * Get all secure stops on the device
      *
+     * @return status the status of the call. The status must be
+     * ERROR_DRM_INVALID_STATE if the HAL is in a state where the secure stops
+     * cannot be returned.
      * @return secureStops a list of the secure stop opaque objects
-     * @return status the status of the call
      */
     getSecureStops() generates
-        (vec<SecureStop> secureStops, Status status);
+        (Status status, vec<SecureStop> secureStops);
 
     /**
-    * Get all secure stops by secure stop ID
-    *
-    * @param secureStopId the ID of the secure stop to return. The
-    * secure stop ID is delivered by the key server as part of the key
-    * response and must also be known by the app.
-    *
-    * @return the secure stop opaque object
-    * @return status the status of the call
-    */
+     * Get all secure stops by secure stop ID
+     *
+     * @param secureStopId the ID of the secure stop to return. The
+     * secure stop ID is delivered by the key server as part of the key
+     * response and must also be known by the app.
+     *
+     * @return status the status of the call. The status must be one of
+     * BAD_VALUE if the secureStopId is invalid or ERROR_DRM_INVALID_STATE
+     * if the HAL is in a state where the secure stop cannot be returned.
+     * @return secureStop the secure stop opaque object
+     */
+
     getSecureStop(SecureStopId secureStopId)
-        generates (SecureStop secureStop, Status status);
+        generates (Status status, SecureStop secureStop);
 
     /**
      * Release all secure stops on the device
      *
-     * @return status the status of the call
+     * @return status the status of the call. The status must be one of
+     * ERROR_DRM_INVALID_STATE if the HAL is in a state where the secure
+     * stops cannot be released.
      */
     releaseAllSecureStops() generates (Status status);
 
     /**
-    * Release a secure stop by secure stop ID
-    *
-    * @param secureStopId the ID of the secure stop to release. The
-    * secure stop ID is delivered by the key server as part of the key
-    * response and must also be known by the app.
-    *
-    * @return status the status of the call
-    */
+     * Release a secure stop by secure stop ID
+     *
+     * @param secureStopId the ID of the secure stop to release. The
+     * secure stop ID is delivered by the key server as part of the key
+     * response and must also be known by the app.
+     *
+     * @return status the status of the call. The status must be one of
+     * BAD_VALUE if the secureStopId is invalid or ERROR_DRM_INVALID_STATE
+     * if the HAL is in a state where the secure stop cannot be released.
+     */
     releaseSecureStop(vec<uint8_t> secureStopId) generates (Status status);
 
     /**
@@ -252,30 +305,39 @@
      * Read a string property value given the property name.
      *
      * @param propertyName the name of the property
-     * @return the property value string
-     * @return status the status of the call
+     * @return status the status of the call. The status must be one of
+     * BAD_VALUE if the property name is invalid, ERROR_DRM_CANNOT_HANDLE
+     * if the property is not supported, or ERROR_DRM_INVALID_STATE if the
+     * HAL is in a state where the property cannot be obtained.
+     * @return value the property value string
      */
     getPropertyString(string propertyName)
-        generates (string value, Status status);
+        generates (Status status, string value);
 
     /**
      * Read a byte array property value given the property name.
      *
      * @param propertyName the name of the property
-     * @return the property value byte array
-     * @return status the status of the call
+     * @return status the status of the call. The status must be one of
+     * BAD_VALUE if the property name is invalid, ERROR_DRM_CANNOT_HANDLE
+     * if the property is not supported, or ERROR_DRM_INVALID_STATE if the
+     * HAL is in a state where the property cannot be obtained.
+     * @return value the property value byte array
      */
     getPropertyByteArray(string propertyName)
-        generates (vec<uint8_t> value, Status status);
+        generates (Status status, vec<uint8_t> value);
 
     /**
      * Write a property string value given the property name
      *
      * @param propertyName the name of the property
      * @param value the value to write
-     * @return status the status of the call
+     * @return status the status of the call. The status must be one of
+     * BAD_VALUE if the property name is invalid, ERROR_DRM_CANNOT_HANDLE
+     * if the property is not supported, or ERROR_DRM_INVALID_STATE if the
+     * HAL is in a state where the property cannot be set.
      */
-    setPropertyString(string propertyName, string value )
+    setPropertyString(string propertyName, string value)
         generates (Status status);
 
     /**
@@ -283,7 +345,10 @@
      *
      * @param propertyName the name of the property
      * @param value the value to write
-     * @return status the status of the call
+     * @return status the status of the call. The status must be one of
+     * BAD_VALUE if the property name is invalid, ERROR_DRM_CANNOT_HANDLE
+     * if the property is not supported, or ERROR_DRM_INVALID_STATE if the
+     * HAL is in a state where the property cannot be set.
      */
     setPropertyByteArray(string propertyName, vec<uint8_t> value )
         generates (Status status);
@@ -301,7 +366,10 @@
      * @param algorithm the algorithm to use. The string conforms to JCA
      * Standard Names for Cipher Transforms and is case insensitive. An
      * example algorithm is "AES/CBC/PKCS5Padding".
-     * @return status the status of the call
+     * @return status the status of the call. The status must be one of
+     * ERROR_DRM_SESSION_NOT_OPENED if the session is not opened,
+     * BAD_VALUE if any parameters are invalid or ERROR_DRM_INVALID_STATE
+     * if the HAL is in a state where the algorithm cannot be set.
      */
     setCipherAlgorithm(SessionId sessionId, string algorithm)
         generates (Status status);
@@ -313,7 +381,10 @@
      * @param algorithm the algorithm to use. The string conforms to JCA
      * Standard Names for Mac Algorithms and is case insensitive. An example MAC
      * algorithm string is "HmacSHA256".
-     * @return status the status of the call
+     * @return status the status of the call. The status must be one of
+     * ERROR_DRM_SESSION_NOT_OPENED if the session is not opened,
+     * BAD_VALUE if any parameters are invalid or ERROR_DRM_INVALID_STATE
+     * if the HAL is in a state where the algorithm cannot be set.
      */
     setMacAlgorithm(SessionId sessionId, string algorithm)
         generates (Status status);
@@ -327,12 +398,15 @@
      * @param keyId the ID of the key to use for encryption
      * @param input the input data to encrypt
      * @param iv the initialization vector to use for encryption
+     * @return status the status of the call. The status must be one of
+     * ERROR_DRM_SESSION_NOT_OPENED if the session is not opened,
+     * BAD_VALUE if any parameters are invalid or ERROR_DRM_INVALID_STATE
+     * if the HAL is in a state where the encrypt operation cannot be
+     * performed.
      * @return output the decrypted data
-     * @return status the status of the call
      */
     encrypt(SessionId sessionId, vec<uint8_t> keyId, vec<uint8_t> input,
-        vec<uint8_t> iv)
-        generates (vec<uint8_t> output, Status status);
+            vec<uint8_t> iv) generates (Status status, vec<uint8_t> output);
 
     /**
      * Decrypt the provided input buffer with the cipher algorithm
@@ -343,11 +417,15 @@
      * @param keyId the ID of the key to use for decryption
      * @param input the input data to decrypt
      * @param iv the initialization vector to use for decryption
+     * @return status the status of the call. The status must be one of
+     * ERROR_DRM_SESSION_NOT_OPENED if the session is not opened,
+     * BAD_VALUE if any parameters are invalid or ERROR_DRM_INVALID_STATE
+     * if the HAL is in a state where the decrypt operation cannot be
+     * performed.
      * @return output the decrypted data
-     * @return status the status of the call
      */
     decrypt(SessionId sessionId, vec<uint8_t> keyId, vec<uint8_t> input,
-        vec<uint8_t> iv) generates (vec<uint8_t> output, Status status);
+            vec<uint8_t> iv) generates (Status status, vec<uint8_t> output);
 
     /**
      * Compute a signature over the provided message using the mac algorithm
@@ -357,11 +435,15 @@
      * @param sessionId the session id the call applies to
      * @param keyId the ID of the key to use for decryption
      * @param message the message to compute a signature over
-     * @return the computed signature
-     * @return status the status of the call
+     * @return status the status of the call. The status must be one of
+     * ERROR_DRM_SESSION_NOT_OPENED if the session is not opened,
+     * BAD_VALUE if any parameters are invalid or ERROR_DRM_INVALID_STATE
+     * if the HAL is in a state where the sign operation cannot be
+     * performed.
+     * @return signature the computed signature
      */
     sign(SessionId sessionId, vec<uint8_t> keyId, vec<uint8_t> message)
-        generates (vec<uint8_t> signature, Status status);
+        generates (Status status, vec<uint8_t> signature);
 
     /**
      * Compute a hash of the provided message using the mac algorithm specified
@@ -371,26 +453,43 @@
      * @param sessionId the session id the call applies to
      * @param keyId the ID of the key to use for decryption
      * @param message the message to compute a hash of
-     * @return status the status of the call
+     * @param signature the signature to verify
+     * @return status the status of the call. The status must be one of
+     * ERROR_DRM_SESSION_NOT_OPENED if the session is not opened,
+     * BAD_VALUE if any parameters are invalid or ERROR_DRM_INVALID_STATE
+     * if the HAL is in a state where the verify operation cannot be
+     * performed.
+     * @return match true if the signature is verified positively,
+     * false otherwise.
      */
     verify(SessionId sessionId, vec<uint8_t> keyId, vec<uint8_t> message,
-        vec<uint8_t> signature) generates (bool match, Status status);
+            vec<uint8_t> signature) generates (Status status, bool match);
 
     /**
      * Compute an RSA signature on the provided message using the specified
      * algorithm.
      *
+     * @param sessionId the session id the call applies to
      * @param algorithm the signing algorithm, such as "RSASSA-PSS-SHA1"
      * or "PKCS1-BlockType1"
-     * @param sessionId the session id the call applies to
-     * @param wrappedKey the private key returned during provisioning
-     * as returned by provideProvisionResponse.
+     * @param message the message to compute the signature on
+     * @param wrappedKey the private key returned during provisioning as
+     * returned by provideProvisionResponse.
+     * @return status the status of the call. The status must be one of
+     * ERROR_DRM_SESSION_NOT_OPENED if the session is not opened,
+     * BAD_VALUE if any parameters are invalid or ERROR_DRM_INVALID_STATE
+     * if the HAL is in a state where the signRSA operation cannot be
+     * performed.
      * @return signature the RSA signature computed over the message
-     * @return status the status of the call
      */
     signRSA(SessionId sessionId, string algorithm, vec<uint8_t> message,
         vec<uint8_t> wrappedkey)
-        generates (vec<uint8_t> signature, Status status);
+        generates (Status status, vec<uint8_t> signature);
+
+    /**
+     * Plugins call the following methods to deliver events to the
+     * java app.
+     */
 
     /**
      * Set a listener for a drm session. This allows the drm HAL to
@@ -401,11 +500,6 @@
     setListener(IDrmPluginListener listener);
 
     /**
-     * HAL implementations call the following methods to deliver events to the
-     * listener
-     */
-
-    /**
      * Legacy event sending method, it sends events of various types using a
      * single overloaded set of parameters. This form is deprecated.
      *
@@ -413,24 +507,23 @@
      * @param sessionId identifies the session the event originated from
      * @param data event-specific data blob
      */
-    oneway sendEvent(EventType eventType, SessionId sessionId,
-            vec<uint8_t> data);
+    sendEvent(EventType eventType, SessionId sessionId, vec<uint8_t> data);
 
     /**
      * Send a license expiration update to the listener. The expiration
-     * update indicates how long the current keys are valid before they
-     * need to be renewed.
+     * update indicates how long the current license is valid before it
+     * needs to be renewed.
      *
      * @param sessionId identifies the session the event originated from
      * @param expiryTimeInMS the time when the keys need to be renewed.
      * The time is in milliseconds, relative to the Unix epoch. A time of 0
      * indicates that the keys never expire.
      */
-    oneway sendExpirationUpdate(SessionId sessionId, int64_t expiryTimeInMS);
+     sendExpirationUpdate(SessionId sessionId, int64_t expiryTimeInMS);
 
     /**
      * Send a keys change event to the listener. The keys change event
-     * indicates the status of each key in the session. `Keys can be
+     * indicates the status of each key in the session. Keys can be
      * indicated as being usable, expired, outputnotallowed or statuspending.
      *
      * @param sessionId identifies the session the event originated from
@@ -439,6 +532,6 @@
      * @param hasNewUsableKey indicates if the event includes at least one
      * key that has become usable.
      */
-    oneway sendKeysChange(SessionId sessionId, vec<KeyStatus> keyStatusList,
-        bool hasNewUsableKey);
+    sendKeysChange(SessionId sessionId, vec<KeyStatus> keyStatusList,
+            bool hasNewUsableKey);
 };
diff --git a/drm/drm/1.0/IDrmPluginListener.hal b/drm/drm/1.0/IDrmPluginListener.hal
index fe2d998..92010a1 100644
--- a/drm/drm/1.0/IDrmPluginListener.hal
+++ b/drm/drm/1.0/IDrmPluginListener.hal
@@ -36,7 +36,8 @@
      * @param sessionId identifies the session the event originated from
      * @param data event-specific data blob
      */
-    sendEvent(EventType eventType, SessionId sessionId, vec<uint8_t> data);
+    oneway sendEvent(EventType eventType, SessionId sessionId,
+            vec<uint8_t> data);
 
     /**
      * Send a license expiration update to the listener. The expiration
@@ -48,7 +49,7 @@
      * The time is in milliseconds, relative to the Unix epoch. A time
      * of 0 indicates that the keys never expire.
      */
-    sendExpirationUpdate(SessionId sessionId, int64_t expiryTimeInMS);
+    oneway sendExpirationUpdate(SessionId sessionId, int64_t expiryTimeInMS);
 
     /**
      * Send a keys change event to the listener. The keys change event
@@ -61,6 +62,6 @@
      * @param hasNewUsableKey indicates if the event includes at least one
      * key that has become usable.
      */
-    sendKeysChange(SessionId sessionId, vec<KeyStatus> keyStatusList,
+    oneway sendKeysChange(SessionId sessionId, vec<KeyStatus> keyStatusList,
             bool hasNewUsableKey);
 };
diff --git a/drm/drm/1.0/default/Android.mk b/drm/drm/1.0/default/Android.mk
new file mode 100644
index 0000000..952957c
--- /dev/null
+++ b/drm/drm/1.0/default/Android.mk
@@ -0,0 +1,39 @@
+# 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 $(CLEAR_VARS)
+LOCAL_MODULE := android.hardware.drm.drm@1.0-impl
+LOCAL_MODULE_RELATIVE_PATH := hw
+LOCAL_SRC_FILES := \
+    DrmFactory.cpp \
+    DrmPlugin.cpp \
+    TypeConvert.cpp \
+
+LOCAL_SHARED_LIBRARIES := \
+    libhidlbase \
+    libhidltransport \
+    libhwbinder \
+    libutils \
+    liblog \
+    libmediadrm \
+    libstagefright_foundation \
+    android.hardware.drm.drm@1.0 \
+
+LOCAL_C_INCLUDES := \
+    frameworks/native/include \
+    frameworks/av/include
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/drm/drm/1.0/default/DrmFactory.cpp b/drm/drm/1.0/default/DrmFactory.cpp
new file mode 100644
index 0000000..494ca53
--- /dev/null
+++ b/drm/drm/1.0/default/DrmFactory.cpp
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "DrmFactory.h"
+#include "DrmPlugin.h"
+#include "TypeConvert.h"
+#include <utils/Log.h>
+
+namespace android {
+namespace hardware {
+namespace drm {
+namespace drm {
+namespace V1_0 {
+namespace implementation {
+
+    DrmFactory::DrmFactory() :
+        loader("/vendor/lib/mediadrm", "createDrmFactory", "drm") {}
+
+    // Methods from ::android::hardware::drm::drm::V1_0::IDrmFactory follow.
+    Return<bool> DrmFactory::isCryptoSchemeSupported (
+            const hidl_array<uint8_t, 16>& uuid) {
+        for (size_t i = 0; i < loader.factoryCount(); i++) {
+            if (loader.getFactory(i)->isCryptoSchemeSupported(uuid.data())) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    Return<void> DrmFactory::createPlugin(const hidl_array<uint8_t, 16>& uuid,
+            createPlugin_cb _hidl_cb) {
+
+        for (size_t i = 0; i < loader.factoryCount(); i++) {
+            if (loader.getFactory(i)->isCryptoSchemeSupported(uuid.data())) {
+                android::DrmPlugin *legacyPlugin = NULL;
+                status_t status = loader.getFactory(i)->createDrmPlugin(
+                        uuid.data(), &legacyPlugin);
+                DrmPlugin *newPlugin = NULL;
+                if (legacyPlugin == NULL) {
+                    ALOGE("Drm legacy HAL: failed to create drm plugin");
+                } else {
+                    newPlugin = new DrmPlugin(legacyPlugin);
+                }
+                _hidl_cb(toStatus(status), newPlugin);
+                return Void();
+            }
+        }
+        _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, NULL);
+        return Void();
+    }
+
+    IDrmFactory* HIDL_FETCH_IDrmFactory(const char* /* name */) {
+        return new DrmFactory();
+    }
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace drm
+}  // namespace drm
+}  // namespace hardware
+}  // namespace android
diff --git a/drm/drm/1.0/default/DrmFactory.h b/drm/drm/1.0/default/DrmFactory.h
new file mode 100644
index 0000000..4dd9ac0
--- /dev/null
+++ b/drm/drm/1.0/default/DrmFactory.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef ANDROID_HARDWARE_DRM_DRM_V1_0__DRMFACTORY_H
+#define ANDROID_HARDWARE_DRM_DRM_V1_0__DRMFACTORY_H
+
+#include <android/hardware/drm/drm/1.0/IDrmFactory.h>
+#include <hidl/Status.h>
+#include <media/drm/DrmAPI.h>
+#include <media/PluginLoader.h>
+#include <media/SharedLibrary.h>
+
+namespace android {
+namespace hardware {
+namespace drm {
+namespace drm {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::drm::drm::V1_0::IDrmFactory;
+using ::android::hardware::drm::drm::V1_0::IDrmPlugin;
+using ::android::hardware::hidl_array;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::sp;
+
+struct DrmFactory : public IDrmFactory {
+    DrmFactory();
+    virtual ~DrmFactory() {}
+
+    // Methods from ::android::hardware::drm::drm::V1_0::IDrmFactory follow.
+
+    Return<bool> isCryptoSchemeSupported(const hidl_array<uint8_t, 16>& uuid)
+            override;
+
+    Return<void> createPlugin(const hidl_array<uint8_t, 16>& uuid,
+            createPlugin_cb _hidl_cb) override;
+
+private:
+    android::PluginLoader<android::DrmFactory> loader;
+
+    DrmFactory(const DrmFactory &) = delete;
+    void operator=(const DrmFactory &) = delete;
+};
+
+extern "C" IDrmFactory* HIDL_FETCH_IDrmFactory(const char* name);
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace drm
+}  // namespace drm
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_DRM_DRM_V1_0__DRMFACTORY_H
diff --git a/drm/drm/1.0/default/DrmPlugin.cpp b/drm/drm/1.0/default/DrmPlugin.cpp
new file mode 100644
index 0000000..5c8f426
--- /dev/null
+++ b/drm/drm/1.0/default/DrmPlugin.cpp
@@ -0,0 +1,428 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <utils/KeyedVector.h>
+#include <utils/String8.h>
+
+#include "DrmPlugin.h"
+#include "TypeConvert.h"
+
+namespace android {
+namespace hardware {
+namespace drm {
+namespace drm {
+namespace V1_0 {
+namespace implementation {
+
+    // Methods from ::android::hardware::drm::drm::V1_0::IDrmPlugin follow.
+
+    Return<void> DrmPlugin::openSession(openSession_cb _hidl_cb) {
+
+        Vector<uint8_t> legacySessionId;
+        status_t status = mLegacyPlugin->openSession(legacySessionId);
+        _hidl_cb(toStatus(status), toHidlVec(legacySessionId));
+        return Void();
+    }
+
+    Return<Status> DrmPlugin::closeSession(const hidl_vec<uint8_t>& sessionId) {
+        return toStatus(mLegacyPlugin->closeSession(toVector(sessionId)));
+    }
+
+    Return<void> DrmPlugin::getKeyRequest(const hidl_vec<uint8_t>& scope,
+            const hidl_vec<uint8_t>& initData, const hidl_string& mimeType,
+            KeyType keyType, const hidl_vec<KeyValue>& optionalParameters,
+            getKeyRequest_cb _hidl_cb) {
+
+        status_t status = android::OK;
+
+        android::DrmPlugin::KeyType legacyKeyType;
+        switch(keyType) {
+        case KeyType::OFFLINE:
+            legacyKeyType = android::DrmPlugin::kKeyType_Offline;
+            break;
+        case KeyType::STREAMING:
+            legacyKeyType = android::DrmPlugin::kKeyType_Streaming;
+            break;
+        case KeyType::RELEASE:
+            legacyKeyType = android::DrmPlugin::kKeyType_Release;
+            break;
+        default:
+            status = android::BAD_VALUE;
+            break;
+        }
+
+        Vector<uint8_t> legacyRequest;
+        KeyRequestType requestType = KeyRequestType::UNKNOWN;
+        String8 defaultUrl;
+
+        if (status == android::OK) {
+            android::KeyedVector<String8, String8> legacyOptionalParameters;
+            for (size_t i = 0; i < optionalParameters.size(); i++) {
+                legacyOptionalParameters.add(String8(optionalParameters[i].key),
+                        String8(optionalParameters[i].value));
+            }
+
+            android::DrmPlugin::KeyRequestType legacyRequestType =
+                    android::DrmPlugin::kKeyRequestType_Unknown;
+
+            status_t status = mLegacyPlugin->getKeyRequest(toVector(scope),
+                    toVector(initData), String8(mimeType), legacyKeyType,
+                    legacyOptionalParameters, legacyRequest, defaultUrl,
+                    &legacyRequestType);
+
+            switch(legacyRequestType) {
+            case android::DrmPlugin::kKeyRequestType_Initial:
+                requestType = KeyRequestType::INITIAL;
+                break;
+            case android::DrmPlugin::kKeyRequestType_Renewal:
+                requestType = KeyRequestType::RENEWAL;
+                break;
+            case android::DrmPlugin::kKeyRequestType_Release:
+                requestType = KeyRequestType::RELEASE;
+                break;
+            case android::DrmPlugin::kKeyRequestType_Unknown:
+                status = android::BAD_VALUE;
+                break;
+            }
+        }
+        _hidl_cb(toStatus(status), toHidlVec(legacyRequest), requestType,
+                 defaultUrl.string());
+        return Void();
+    }
+
+    Return<void> DrmPlugin::provideKeyResponse(const hidl_vec<uint8_t>& scope,
+            const hidl_vec<uint8_t>& response, provideKeyResponse_cb _hidl_cb) {
+
+        Vector<uint8_t> keySetId;
+        status_t status = mLegacyPlugin->provideKeyResponse(toVector(scope),
+                toVector(response), keySetId);
+        _hidl_cb(toStatus(status), toHidlVec(keySetId));
+        return Void();
+    }
+
+    Return<Status> DrmPlugin::removeKeys(const hidl_vec<uint8_t>& sessionId) {
+        return toStatus(mLegacyPlugin->removeKeys(toVector(sessionId)));
+    }
+
+    Return<Status> DrmPlugin::restoreKeys(const hidl_vec<uint8_t>& sessionId,
+            const hidl_vec<uint8_t>& keySetId) {
+        status_t legacyStatus = mLegacyPlugin->restoreKeys(toVector(sessionId),
+                toVector(keySetId));
+        return toStatus(legacyStatus);
+    }
+
+    Return<void> DrmPlugin::queryKeyStatus(const hidl_vec<uint8_t>& sessionId,
+            queryKeyStatus_cb _hidl_cb) {
+
+        android::KeyedVector<String8, String8> legacyInfoMap;
+        status_t status = mLegacyPlugin->queryKeyStatus(toVector(sessionId),
+                legacyInfoMap);
+
+        Vector<KeyValue> infoMapVec;
+        for (size_t i = 0; i < legacyInfoMap.size(); i++) {
+            KeyValue keyValuePair;
+            keyValuePair.key = String8(legacyInfoMap.keyAt(i));
+            keyValuePair.value = String8(legacyInfoMap.valueAt(i));
+            infoMapVec.push_back(keyValuePair);
+        }
+        _hidl_cb(toStatus(status), toHidlVec(infoMapVec));
+        return Void();
+    }
+
+    Return<void> DrmPlugin::getProvisionRequest(
+            const hidl_string& certificateType,
+            const hidl_string& certificateAuthority,
+            getProvisionRequest_cb _hidl_cb) {
+
+        Vector<uint8_t> legacyRequest;
+        String8 legacyDefaultUrl;
+        status_t status = mLegacyPlugin->getProvisionRequest(
+                String8(certificateType), String8(certificateAuthority),
+                legacyRequest, legacyDefaultUrl);
+
+        _hidl_cb(toStatus(status), toHidlVec(legacyRequest),
+                hidl_string(legacyDefaultUrl));
+        return Void();
+    }
+
+    Return<void> DrmPlugin::provideProvisionResponse(
+            const hidl_vec<uint8_t>& response,
+            provideProvisionResponse_cb _hidl_cb) {
+
+        Vector<uint8_t> certificate;
+        Vector<uint8_t> wrappedKey;
+
+        status_t legacyStatus = mLegacyPlugin->provideProvisionResponse(
+                toVector(response), certificate, wrappedKey);
+
+        _hidl_cb(toStatus(legacyStatus), toHidlVec(certificate),
+                toHidlVec(wrappedKey));
+        return Void();
+    }
+
+    Return<void> DrmPlugin::getSecureStops(getSecureStops_cb _hidl_cb) {
+        List<Vector<uint8_t> > legacySecureStops;
+        status_t status = mLegacyPlugin->getSecureStops(legacySecureStops);
+
+        Vector<SecureStop> secureStopsVec;
+        List<Vector<uint8_t> >::iterator iter = legacySecureStops.begin();
+
+        while (iter != legacySecureStops.end()) {
+            SecureStop secureStop;
+            secureStop.opaqueData = toHidlVec(*iter++);
+            secureStopsVec.push_back(secureStop);
+        }
+
+        _hidl_cb(toStatus(status), toHidlVec(secureStopsVec));
+        return Void();
+    }
+
+    Return<void> DrmPlugin::getSecureStop(const hidl_vec<uint8_t>& secureStopId,
+            getSecureStop_cb _hidl_cb) {
+
+        Vector<uint8_t> legacySecureStop;
+        status_t status = mLegacyPlugin->getSecureStop(toVector(secureStopId),
+                legacySecureStop);
+
+        SecureStop secureStop;
+        secureStop.opaqueData = toHidlVec(legacySecureStop);
+        _hidl_cb(toStatus(status), secureStop);
+        return Void();
+    }
+
+    Return<Status> DrmPlugin::releaseAllSecureStops() {
+        return toStatus(mLegacyPlugin->releaseAllSecureStops());
+    }
+
+    Return<Status> DrmPlugin::releaseSecureStop(
+            const hidl_vec<uint8_t>& secureStopId) {
+        status_t legacyStatus =
+            mLegacyPlugin->releaseSecureStops(toVector(secureStopId));
+        return toStatus(legacyStatus);
+    }
+
+    Return<void> DrmPlugin::getPropertyString(const hidl_string& propertyName,
+            getPropertyString_cb _hidl_cb) {
+        String8 legacyValue;
+        status_t status = mLegacyPlugin->getPropertyString(
+                String8(propertyName), legacyValue);
+        _hidl_cb(toStatus(status), legacyValue.string());
+        return Void();
+    }
+
+    Return<void> DrmPlugin::getPropertyByteArray(const hidl_string& propertyName,
+            getPropertyByteArray_cb _hidl_cb) {
+        Vector<uint8_t> legacyValue;
+        status_t status = mLegacyPlugin->getPropertyByteArray(
+                String8(propertyName), legacyValue);
+        _hidl_cb(toStatus(status), toHidlVec(legacyValue));
+        return Void();
+    }
+
+    Return<Status> DrmPlugin::setPropertyString(const hidl_string& propertyName,
+            const hidl_string& value) {
+        status_t legacyStatus =
+            mLegacyPlugin->setPropertyString(String8(propertyName),
+                    String8(value));
+        return toStatus(legacyStatus);
+    }
+
+    Return<Status> DrmPlugin::setPropertyByteArray(
+            const hidl_string& propertyName, const hidl_vec<uint8_t>& value) {
+        status_t legacyStatus =
+            mLegacyPlugin->setPropertyByteArray(String8(propertyName),
+                    toVector(value));
+        return toStatus(legacyStatus);
+    }
+
+    Return<Status> DrmPlugin::setCipherAlgorithm(
+            const hidl_vec<uint8_t>& sessionId, const hidl_string& algorithm) {
+        status_t legacyStatus =
+            mLegacyPlugin->setCipherAlgorithm(toVector(sessionId),
+                String8(algorithm));
+        return toStatus(legacyStatus);
+    }
+
+    Return<Status> DrmPlugin::setMacAlgorithm(
+            const hidl_vec<uint8_t>& sessionId, const hidl_string& algorithm) {
+        status_t legacyStatus =
+            mLegacyPlugin->setMacAlgorithm(toVector(sessionId),
+                String8(algorithm));
+        return toStatus(legacyStatus);
+    }
+
+    Return<void> DrmPlugin::encrypt(const hidl_vec<uint8_t>& sessionId,
+            const hidl_vec<uint8_t>& keyId, const hidl_vec<uint8_t>& input,
+            const hidl_vec<uint8_t>& iv, encrypt_cb _hidl_cb) {
+
+        Vector<uint8_t> legacyOutput;
+        status_t status = mLegacyPlugin->encrypt(toVector(sessionId),
+                toVector(keyId), toVector(input), toVector(iv), legacyOutput);
+        _hidl_cb(toStatus(status), toHidlVec(legacyOutput));
+        return Void();
+    }
+
+    Return<void> DrmPlugin::decrypt(const hidl_vec<uint8_t>& sessionId,
+            const hidl_vec<uint8_t>& keyId, const hidl_vec<uint8_t>& input,
+            const hidl_vec<uint8_t>& iv, decrypt_cb _hidl_cb) {
+
+        Vector<uint8_t> legacyOutput;
+        status_t status = mLegacyPlugin->decrypt(toVector(sessionId),
+                toVector(keyId), toVector(input), toVector(iv), legacyOutput);
+        _hidl_cb(toStatus(status), toHidlVec(legacyOutput));
+        return Void();
+    }
+
+    Return<void> DrmPlugin::sign(const hidl_vec<uint8_t>& sessionId,
+            const hidl_vec<uint8_t>& keyId, const hidl_vec<uint8_t>& message,
+            sign_cb _hidl_cb) {
+        Vector<uint8_t> legacySignature;
+        status_t status = mLegacyPlugin->sign(toVector(sessionId),
+                toVector(keyId), toVector(message), legacySignature);
+        _hidl_cb(toStatus(status), toHidlVec(legacySignature));
+        return Void();
+    }
+
+    Return<void> DrmPlugin::verify(const hidl_vec<uint8_t>& sessionId,
+            const hidl_vec<uint8_t>& keyId, const hidl_vec<uint8_t>& message,
+            const hidl_vec<uint8_t>& signature, verify_cb _hidl_cb) {
+
+        bool match;
+        status_t status = mLegacyPlugin->verify(toVector(sessionId),
+                toVector(keyId), toVector(message), toVector(signature),
+                match);
+        _hidl_cb(toStatus(status), match);
+        return Void();
+    }
+
+    Return<void> DrmPlugin::signRSA(const hidl_vec<uint8_t>& sessionId,
+            const hidl_string& algorithm, const hidl_vec<uint8_t>& message,
+            const hidl_vec<uint8_t>& wrappedKey, signRSA_cb _hidl_cb) {
+
+        Vector<uint8_t> legacySignature;
+        status_t status = mLegacyPlugin->signRSA(toVector(sessionId),
+                String8(algorithm), toVector(message), toVector(wrappedKey),
+                legacySignature);
+        _hidl_cb(toStatus(status), toHidlVec(legacySignature));
+        return Void();
+    }
+
+    Return<void> DrmPlugin::setListener(const sp<IDrmPluginListener>& listener) {
+        mListener = listener;
+        return Void();
+    }
+
+    Return<void> DrmPlugin::sendEvent(EventType eventType,
+            const hidl_vec<uint8_t>& sessionId, const hidl_vec<uint8_t>& data) {
+        mListener->sendEvent(eventType, sessionId, data);
+        return Void();
+    }
+
+    Return<void> DrmPlugin::sendExpirationUpdate(
+            const hidl_vec<uint8_t>& sessionId, int64_t expiryTimeInMS) {
+        mListener->sendExpirationUpdate(sessionId, expiryTimeInMS);
+        return Void();
+    }
+
+    Return<void> DrmPlugin::sendKeysChange(const hidl_vec<uint8_t>& sessionId,
+            const hidl_vec<KeyStatus>& keyStatusList, bool hasNewUsableKey) {
+        mListener->sendKeysChange(sessionId, keyStatusList, hasNewUsableKey);
+        return Void();
+    }
+
+
+    // Methods from android::DrmPluginListener
+
+    void DrmPlugin::sendEvent(android::DrmPlugin::EventType legacyEventType,
+            int /*unused*/, Vector<uint8_t> const *sessionId,
+            Vector<uint8_t> const *data) {
+
+        EventType eventType;
+        bool sendEvent = true;
+        switch(legacyEventType) {
+        case android::DrmPlugin::kDrmPluginEventProvisionRequired:
+            eventType = EventType::PROVISION_REQUIRED;
+            break;
+        case android::DrmPlugin::kDrmPluginEventKeyNeeded:
+            eventType = EventType::KEY_NEEDED;
+            break;
+        case android::DrmPlugin::kDrmPluginEventKeyExpired:
+            eventType = EventType::KEY_EXPIRED;
+            break;
+        case android::DrmPlugin::kDrmPluginEventVendorDefined:
+            eventType = EventType::VENDOR_DEFINED;
+            break;
+        case android::DrmPlugin::kDrmPluginEventSessionReclaimed:
+            eventType = EventType::SESSION_RECLAIMED;
+            break;
+        default:
+            sendEvent = false;
+            break;
+        }
+        if (sendEvent) {
+            mListener->sendEvent(eventType, toHidlVec(*sessionId),
+                    toHidlVec(*data));
+        }
+    }
+
+    void DrmPlugin::sendExpirationUpdate(Vector<uint8_t> const *sessionId,
+            int64_t expiryTimeInMS) {
+        mListener->sendExpirationUpdate(toHidlVec(*sessionId), expiryTimeInMS);
+    }
+
+    void DrmPlugin::sendKeysChange(Vector<uint8_t> const *sessionId,
+            Vector<android::DrmPlugin::KeyStatus> const *legacyKeyStatusList,
+            bool hasNewUsableKey) {
+
+        Vector<KeyStatus> keyStatusVec;
+        for (size_t i = 0; i < legacyKeyStatusList->size(); i++) {
+            const android::DrmPlugin::KeyStatus &legacyKeyStatus =
+                legacyKeyStatusList->itemAt(i);
+
+            KeyStatus keyStatus;
+
+            switch(legacyKeyStatus.mType) {
+            case android::DrmPlugin::kKeyStatusType_Usable:
+                keyStatus.type = KeyStatusType::USABLE;
+                break;
+            case android::DrmPlugin::kKeyStatusType_Expired:
+                keyStatus.type = KeyStatusType::EXPIRED;
+                break;
+            case android::DrmPlugin::kKeyStatusType_OutputNotAllowed:
+                keyStatus.type = KeyStatusType::OUTPUTNOTALLOWED;
+                break;
+            case android::DrmPlugin::kKeyStatusType_StatusPending:
+                keyStatus.type = KeyStatusType::STATUSPENDING;
+                break;
+            case android::DrmPlugin::kKeyStatusType_InternalError:
+            default:
+                keyStatus.type = KeyStatusType::INTERNALERROR;
+                break;
+            }
+
+            keyStatus.keyId = toHidlVec(legacyKeyStatus.mKeyId);
+            keyStatusVec.push_back(keyStatus);
+        }
+        mListener->sendKeysChange(toHidlVec(*sessionId),
+                toHidlVec(keyStatusVec), hasNewUsableKey);
+    }
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace drm
+}  // namespace drm
+}  // namespace hardware
+}  // namespace android
diff --git a/drm/drm/1.0/default/DrmPlugin.h b/drm/drm/1.0/default/DrmPlugin.h
new file mode 100644
index 0000000..2bf3b5e
--- /dev/null
+++ b/drm/drm/1.0/default/DrmPlugin.h
@@ -0,0 +1,172 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_DRM_DRM_V1_0__DRMPLUGIN_H
+#define ANDROID_HARDWARE_DRM_DRM_V1_0__DRMPLUGIN_H
+
+#include <media/drm/DrmAPI.h>
+#include <android/hardware/drm/drm/1.0/IDrmPlugin.h>
+#include <android/hardware/drm/drm/1.0/IDrmPluginListener.h>
+#include <hidl/MQDescriptor.h>
+#include <hidl/Status.h>
+
+namespace android {
+namespace hardware {
+namespace drm {
+namespace drm {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::drm::drm::V1_0::EventType;
+using ::android::hardware::drm::drm::V1_0::IDrmPlugin;
+using ::android::hardware::drm::drm::V1_0::IDrmPluginListener;
+using ::android::hardware::drm::drm::V1_0::KeyRequestType;
+using ::android::hardware::drm::drm::V1_0::KeyStatus;
+using ::android::hardware::drm::drm::V1_0::KeyType;
+using ::android::hardware::drm::drm::V1_0::KeyValue;
+using ::android::hardware::drm::drm::V1_0::SecureStop;
+using ::android::hardware::hidl_array;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::sp;
+
+struct DrmPlugin : public IDrmPlugin, android::DrmPluginListener {
+
+    DrmPlugin(android::DrmPlugin *plugin) : mLegacyPlugin(plugin) {}
+    ~DrmPlugin() {delete mLegacyPlugin;}
+
+    // Methods from ::android::hardware::drm::drm::V1_0::IDrmPlugin follow.
+
+    Return<void> openSession(openSession_cb _hidl_cb) override;
+
+    Return<Status> closeSession(const hidl_vec<uint8_t>& sessionId) override;
+
+    Return<void> getKeyRequest(const hidl_vec<uint8_t>& scope,
+            const hidl_vec<uint8_t>& initData, const hidl_string& mimeType,
+            KeyType keyType, const hidl_vec<KeyValue>& optionalParameters,
+            getKeyRequest_cb _hidl_cb) override;
+
+    Return<void> provideKeyResponse(const hidl_vec<uint8_t>& scope,
+            const hidl_vec<uint8_t>& response, provideKeyResponse_cb _hidl_cb)
+            override;
+
+    Return<Status> removeKeys(const hidl_vec<uint8_t>& sessionId) override;
+
+    Return<Status> restoreKeys(const hidl_vec<uint8_t>& sessionId,
+            const hidl_vec<uint8_t>& keySetId) override;
+
+    Return<void> queryKeyStatus(const hidl_vec<uint8_t>& sessionId,
+            queryKeyStatus_cb _hidl_cb) override;
+
+    Return<void> getProvisionRequest(const hidl_string& certificateType,
+            const hidl_string& certificateAuthority,
+            getProvisionRequest_cb _hidl_cb) override;
+
+    Return<void> provideProvisionResponse(const hidl_vec<uint8_t>& response,
+            provideProvisionResponse_cb _hidl_cb) override;
+
+    Return<void> getSecureStops(getSecureStops_cb _hidl_cb) override;
+
+    Return<void> getSecureStop(const hidl_vec<uint8_t>& secureStopId,
+            getSecureStop_cb _hidl_cb) override;
+
+    Return<Status> releaseAllSecureStops() override;
+
+    Return<Status> releaseSecureStop(const hidl_vec<uint8_t>& secureStopId)
+            override;
+
+    Return<void> getPropertyString(const hidl_string& propertyName,
+            getPropertyString_cb _hidl_cb) override;
+
+    Return<void> getPropertyByteArray(const hidl_string& propertyName,
+            getPropertyByteArray_cb _hidl_cb) override;
+
+    Return<Status> setPropertyString(const hidl_string& propertyName,
+            const hidl_string& value) override;
+
+    Return<Status> setPropertyByteArray(const hidl_string& propertyName,
+            const hidl_vec<uint8_t>& value) override;
+
+    Return<Status> setCipherAlgorithm(const hidl_vec<uint8_t>& sessionId,
+            const hidl_string& algorithm) override;
+
+    Return<Status> setMacAlgorithm(const hidl_vec<uint8_t>& sessionId,
+            const hidl_string& algorithm) override;
+
+    Return<void> encrypt(const hidl_vec<uint8_t>& sessionId,
+            const hidl_vec<uint8_t>& keyId, const hidl_vec<uint8_t>& input,
+            const hidl_vec<uint8_t>& iv, encrypt_cb _hidl_cb) override;
+
+    Return<void> decrypt(const hidl_vec<uint8_t>& sessionId,
+            const hidl_vec<uint8_t>& keyId, const hidl_vec<uint8_t>& input,
+            const hidl_vec<uint8_t>& iv, decrypt_cb _hidl_cb) override;
+
+    Return<void> sign(const hidl_vec<uint8_t>& sessionId,
+            const hidl_vec<uint8_t>& keyId, const hidl_vec<uint8_t>& message,
+            sign_cb _hidl_cb) override;
+
+    Return<void> verify(const hidl_vec<uint8_t>& sessionId,
+            const hidl_vec<uint8_t>& keyId, const hidl_vec<uint8_t>& message,
+            const hidl_vec<uint8_t>& signature, verify_cb _hidl_cb) override;
+
+    Return<void> signRSA(const hidl_vec<uint8_t>& sessionId,
+            const hidl_string& algorithm, const hidl_vec<uint8_t>& message,
+            const hidl_vec<uint8_t>& wrappedkey, signRSA_cb _hidl_cb) override;
+
+    Return<void> setListener(const sp<IDrmPluginListener>& listener) override;
+
+    Return<void> sendEvent(EventType eventType,
+            const hidl_vec<uint8_t>& sessionId, const hidl_vec<uint8_t>& data)
+            override;
+
+    Return<void> sendExpirationUpdate(const hidl_vec<uint8_t>& sessionId,
+            int64_t expiryTimeInMS) override;
+
+    Return<void> sendKeysChange(const hidl_vec<uint8_t>& sessionId,
+            const hidl_vec<KeyStatus>& keyStatusList, bool hasNewUsableKey)
+            override;
+
+    // Methods from android::DrmPluginListener follow
+
+    virtual void sendEvent(android::DrmPlugin::EventType eventType, int extra,
+            Vector<uint8_t> const *sessionId, Vector<uint8_t> const *data);
+
+    virtual void sendExpirationUpdate(Vector<uint8_t> const *sessionId,
+            int64_t expiryTimeInMS);
+
+    virtual void sendKeysChange(Vector<uint8_t> const *sessionId,
+            Vector<android::DrmPlugin::KeyStatus> const *keyStatusList,
+            bool hasNewUsableKey);
+
+private:
+    android::DrmPlugin *mLegacyPlugin;
+    sp<IDrmPluginListener> mListener;
+
+    DrmPlugin() = delete;
+    DrmPlugin(const DrmPlugin &) = delete;
+    void operator=(const DrmPlugin &) = delete;
+};
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace drm
+}  // namespace drm
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_DRM_DRM_V1_0__DRMPLUGIN_H
diff --git a/drm/drm/1.0/default/TypeConvert.cpp b/drm/drm/1.0/default/TypeConvert.cpp
new file mode 100644
index 0000000..2b4e2a2
--- /dev/null
+++ b/drm/drm/1.0/default/TypeConvert.cpp
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "TypeConvert.h"
+
+namespace android {
+namespace hardware {
+namespace drm {
+namespace drm {
+namespace V1_0 {
+namespace implementation {
+
+Status toStatus(status_t legacyStatus) {
+    Status status;
+    switch(legacyStatus) {
+    case android::ERROR_DRM_NO_LICENSE:
+        status = Status::ERROR_DRM_NO_LICENSE;
+        break;
+    case android::ERROR_DRM_LICENSE_EXPIRED:
+        status = Status::ERROR_DRM_LICENSE_EXPIRED;
+        break;
+    case android::ERROR_DRM_SESSION_NOT_OPENED:
+        status = Status::ERROR_DRM_SESSION_NOT_OPENED;
+        break;
+    case android::ERROR_DRM_CANNOT_HANDLE:
+        status = Status::ERROR_DRM_CANNOT_HANDLE;
+        break;
+    case android::ERROR_DRM_TAMPER_DETECTED:
+        status = Status::ERROR_DRM_INVALID_STATE;
+        break;
+    case android::BAD_VALUE:
+        status = Status::BAD_VALUE;
+        break;
+    case android::ERROR_DRM_NOT_PROVISIONED:
+        status = Status::ERROR_DRM_NOT_PROVISIONED;
+        break;
+    case android::ERROR_DRM_RESOURCE_BUSY:
+        status = Status::ERROR_DRM_RESOURCE_BUSY;
+        break;
+    case android::ERROR_DRM_DEVICE_REVOKED:
+        status = Status::ERROR_DRM_DEVICE_REVOKED;
+        break;
+    default:
+        ALOGW("Unable to convert legacy status: %d, defaulting to UNKNOWN",
+            legacyStatus);
+        status = Status::ERROR_DRM_UNKNOWN;
+        break;
+    }
+    return status;
+}
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace drm
+}  // namespace drm
+}  // namespace hardware
+}  // namespace android
diff --git a/drm/drm/1.0/default/TypeConvert.h b/drm/drm/1.0/default/TypeConvert.h
new file mode 100644
index 0000000..2f7875e
--- /dev/null
+++ b/drm/drm/1.0/default/TypeConvert.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_DRM_DRM_V1_0_TYPECONVERT
+#define ANDROID_HARDWARE_DRM_DRM_V1_0_TYPECONVERT
+
+#include <utils/Vector.h>
+#include <media/stagefright/MediaErrors.h>
+#include <media/drm/DrmAPI.h>
+
+#include <hidl/MQDescriptor.h>
+#include <android/hardware/drm/drm/1.0/types.h>
+
+namespace android {
+namespace hardware {
+namespace drm {
+namespace drm {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::hidl_vec;
+
+template<typename T> const hidl_vec<T> toHidlVec(const Vector<T> &Vector) {
+    hidl_vec<T> vec;
+    vec.setToExternal(const_cast<T *>(Vector.array()), Vector.size());
+    return vec;
+}
+
+template<typename T> hidl_vec<T> toHidlVec(Vector<T> &Vector) {
+    hidl_vec<T> vec;
+    vec.setToExternal(Vector.editArray(), Vector.size());
+    return vec;
+}
+
+template<typename T> const Vector<T> toVector(const hidl_vec<T> & vec) {
+    Vector<T> vector;
+    vector.appendArray(vec.data(), vec.size());
+    return *const_cast<const Vector<T> *>(&vector);
+}
+
+template<typename T> Vector<T> toVector(hidl_vec<T> &vec) {
+    Vector<T> vector;
+    vector.appendArray(vec.data(), vec.size());
+    return vector;
+}
+
+Status toStatus(status_t legacyStatus);
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace drm
+}  // namespace drm
+}  // namespace hardware
+}  // namespace android
+
+#endif // ANDROID_HARDWARE_DRM_DRM_V1_0_TYPECONVERT
diff --git a/drm/drm/1.0/types.hal b/drm/drm/1.0/types.hal
index 05101c9..3d77911 100644
--- a/drm/drm/1.0/types.hal
+++ b/drm/drm/1.0/types.hal
@@ -161,6 +161,11 @@
      * to become available for streaming.
      */
     RELEASE,
+
+    /**
+     * Key request type is unknown due to some error condition.
+     */
+    UNKNOWN,
 };
 
 /**
diff --git a/graphics/composer/2.1/default/HwcClient.cpp b/graphics/composer/2.1/default/HwcClient.cpp
index 89945da..ce6c480 100644
--- a/graphics/composer/2.1/default/HwcClient.cpp
+++ b/graphics/composer/2.1/default/HwcClient.cpp
@@ -936,7 +936,7 @@
         return false;
     }
 
-    auto err = mHal.setLayerPlaneAlpha(mDisplay, mLayer, read());
+    auto err = mHal.setLayerPlaneAlpha(mDisplay, mLayer, readFloat());
     if (err != Error::NONE) {
         mWriter.setError(getCommandLoc(), err);
     }
diff --git a/graphics/composer/2.1/default/IComposerCommandBuffer.h b/graphics/composer/2.1/default/IComposerCommandBuffer.h
index 36654d0..8f133fe 100644
--- a/graphics/composer/2.1/default/IComposerCommandBuffer.h
+++ b/graphics/composer/2.1/default/IComposerCommandBuffer.h
@@ -35,7 +35,7 @@
 #include <android/hardware/graphics/composer/2.1/IComposer.h>
 #include <log/log.h>
 #include <sync/sync.h>
-#include <MessageQueue.h>
+#include <fmq/MessageQueue.h>
 
 namespace android {
 namespace hardware {
diff --git a/ir/1.0/IConsumerIr.hal b/ir/1.0/IConsumerIr.hal
index f928c0e..f9e6316 100644
--- a/ir/1.0/IConsumerIr.hal
+++ b/ir/1.0/IConsumerIr.hal
@@ -28,7 +28,7 @@
      *
      * returns: true on success, false on error.
      */
-    transmit(int32_t carrierFreq, vec<int32_t> pattern, int32_t patternLen) generates (bool success);
+    transmit(int32_t carrierFreq, vec<int32_t> pattern) generates (bool success);
 
     /*
      * getCarrierFreqs() enumerates which frequencies the IR transmitter supports.
diff --git a/ir/1.0/default/ConsumerIr.cpp b/ir/1.0/default/ConsumerIr.cpp
index 763e09a..8cfb2e8 100644
--- a/ir/1.0/default/ConsumerIr.cpp
+++ b/ir/1.0/default/ConsumerIr.cpp
@@ -32,8 +32,8 @@
 }
 
 // Methods from ::android::hardware::consumerir::V1_0::IConsumerIr follow.
-Return<bool> ConsumerIr::transmit(int32_t carrierFreq, const hidl_vec<int32_t>& pattern, int32_t patternLen) {
-    return mDevice->transmit(mDevice, carrierFreq, pattern.data(), patternLen) == 0;
+Return<bool> ConsumerIr::transmit(int32_t carrierFreq, const hidl_vec<int32_t>& pattern) {
+    return mDevice->transmit(mDevice, carrierFreq, pattern.data(), pattern.size()) == 0;
 }
 
 Return<void> ConsumerIr::getCarrierFreqs(getCarrierFreqs_cb _hidl_cb) {
diff --git a/ir/1.0/default/ConsumerIr.h b/ir/1.0/default/ConsumerIr.h
index 527c577..1532183 100644
--- a/ir/1.0/default/ConsumerIr.h
+++ b/ir/1.0/default/ConsumerIr.h
@@ -40,7 +40,7 @@
 struct ConsumerIr : public IConsumerIr {
     ConsumerIr(consumerir_device_t *device);
     // Methods from ::android::hardware::ir::V1_0::IConsumerIr follow.
-    Return<bool> transmit(int32_t carrierFreq, const hidl_vec<int32_t>& pattern, int32_t patternLen) override;
+    Return<bool> transmit(int32_t carrierFreq, const hidl_vec<int32_t>& pattern) override;
     Return<void> getCarrierFreqs(getCarrierFreqs_cb _hidl_cb) override;
 private:
     consumerir_device_t *mDevice;
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/media/1.0/types.hal b/media/1.0/types.hal
index 98dfe14..89b7fa2 100644
--- a/media/1.0/types.hal
+++ b/media/1.0/types.hal
@@ -27,28 +27,28 @@
 
 /**
  * Ref: frameworks/native/include/ui/GraphicBuffer.h
- * Ref: system/core/include/system/window.h
+ * Ref: system/core/include/system/window.h: ANativeWindowBuffer
  */
 
 /**
  * This struct contains attributes for a gralloc buffer that can be put into a
  * union.
  */
-struct GraphicBufferAttributes {
+struct AnwBufferAttributes {
     uint32_t width;
     uint32_t height;
     uint32_t stride;
     PixelFormat format;
     uint32_t usage; // TODO: convert to an enum
-    uint32_t generationNumber;
+    uint64_t layerCount;
 };
 
 /**
- * A GraphicBuffer is simply GraphicBufferAttributes plus a native handle.
+ * An AnwBuffer is simply AnwBufferAttributes plus a native handle.
  */
-struct GraphicBuffer {
+struct AnwBuffer {
     handle nativeHandle;
-    GraphicBufferAttributes attr;
+    AnwBufferAttributes attr;
 };
 
 /**
diff --git a/media/omx/1.0/IGraphicBufferSource.hal b/media/omx/1.0/IGraphicBufferSource.hal
index a5b5813..9b3ab0c 100644
--- a/media/omx/1.0/IGraphicBufferSource.hal
+++ b/media/omx/1.0/IGraphicBufferSource.hal
@@ -29,32 +29,23 @@
  */
 interface IGraphicBufferSource {
 
-    configure(IOmxNode omxNode, Dataspace dataspace)
-        generates (Status status);
+    configure(IOmxNode omxNode, Dataspace dataspace);
 
-    setSuspend(bool suspend)
-        generates (Status status);
+    setSuspend(bool suspend);
 
-    setRepeatPreviousFrameDelayUs(int64_t repeatAfterUs)
-        generates (Status status);
+    setRepeatPreviousFrameDelayUs(int64_t repeatAfterUs);
 
-    setMaxFps(float maxFps)
-        generates (Status status);
+    setMaxFps(float maxFps);
 
-    setTimeLapseConfig(int64_t timePerFrameUs, int64_t timePerCaptureUs)
-        generates (Status status);
+    setTimeLapseConfig(int64_t timePerFrameUs, int64_t timePerCaptureUs);
 
-    setStartTimeUs(int64_t startTimeUs)
-        generates (Status status);
+    setStartTimeUs(int64_t startTimeUs);
 
-    setColorAspects(ColorAspects aspects)
-        generates (Status status);
+    setColorAspects(ColorAspects aspects);
 
-    setTimeOffsetUs(int64_t timeOffsetUs)
-        generates (Status status);
+    setTimeOffsetUs(int64_t timeOffsetUs);
 
-    signalEndOfInputStream()
-        generates (Status status);
+    signalEndOfInputStream();
 
 };
 
diff --git a/media/omx/1.0/IOmxNode.hal b/media/omx/1.0/IOmxNode.hal
index 9483be4..5945b44 100644
--- a/media/omx/1.0/IOmxNode.hal
+++ b/media/omx/1.0/IOmxNode.hal
@@ -46,14 +46,14 @@
      * Invoke a command on the node.
      *
      * @param[in] cmd indicates the type of the command.
-     * @param[in] info holds information about the command.
+     * @param[in] param is a parameter for the command.
      * @param[out] status will be the status of the call.
      *
      * @see OMX_SendCommand() in the OpenMax IL standard.
      */
     sendCommand(
             uint32_t cmd,
-            Bytes info // TODO: describe structure better or point at standard
+            int32_t param
         ) generates (
             Status status
         );
diff --git a/media/omx/1.0/types.hal b/media/omx/1.0/types.hal
index 79c3a44..ccb2ddf 100644
--- a/media/omx/1.0/types.hal
+++ b/media/omx/1.0/types.hal
@@ -34,6 +34,7 @@
 
     NAME_NOT_FOUND          = -2,
     NO_MEMORY               = -12,
+    BAD_VALUE               = -22,
     ERROR_UNSUPPORTED       = -1010,
     UNKNOWN_ERROR           = -2147483648,
 };
@@ -149,7 +150,7 @@
         SharedMemoryAttributes sharedMem;
 
         // if bufferType == ANW_BUFFER
-        GraphicBufferAttributes anwBuffer;
+        AnwBufferAttributes anwBuffer;
 
         // if bufferType == NATIVE_HANDLE
         // No additional attributes.
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/nfc/1.0/Android.bp b/nfc/1.0/Android.bp
index 930fb14..af571f3 100644
--- a/nfc/1.0/Android.bp
+++ b/nfc/1.0/Android.bp
@@ -124,3 +124,93 @@
         "android.hidl.base@1.0",
     ],
 }
+
+genrule {
+    name: "android.hardware.nfc@1.0-INfc-vts.profiler_genc++",
+    tools: ["hidl-gen", "vtsc"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lvts -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.nfc@1.0 && $(location vtsc) -mPROFILER -tSOURCE -b$(genDir) android/hardware/nfc/1.0/ $(genDir)/android/hardware/nfc/1.0/",
+    srcs: [
+        "INfc.hal",
+        "types.hal",
+    ],
+    out: [
+        "android/hardware/nfc/1.0/Nfc.vts.cpp",
+        "android/hardware/nfc/1.0/types.vts.cpp",
+    ],
+}
+
+genrule {
+    name: "android.hardware.nfc@1.0-INfc-vts.profiler_genc++_headers",
+    tools: ["hidl-gen", "vtsc"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lvts -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.nfc@1.0 && $(location vtsc) -mPROFILER -tHEADER -b$(genDir) android/hardware/nfc/1.0/ $(genDir)/android/hardware/nfc/1.0/",
+    srcs: [
+        "INfc.hal",
+        "types.hal",
+    ],
+    out: [
+        "android/hardware/nfc/1.0/Nfc.vts.h",
+        "android/hardware/nfc/1.0/types.vts.h",
+    ],
+}
+
+cc_library_shared {
+    name: "android.hardware.nfc@1.0-INfc-vts.profiler",
+    generated_sources: ["android.hardware.nfc@1.0-INfc-vts.profiler_genc++"],
+    generated_headers: ["android.hardware.nfc@1.0-INfc-vts.profiler_genc++_headers"],
+    export_generated_headers: ["android.hardware.nfc@1.0-INfc-vts.profiler_genc++_headers"],
+    shared_libs: [
+        "libbase",
+        "libhidlbase",
+        "libhidltransport",
+        "libvts_profiling",
+        "libvts_multidevice_proto",
+        "libprotobuf-cpp-full",
+        "android.hidl.base@1.0",
+        "android.hardware.nfc@1.0",
+    ],
+}
+
+genrule {
+    name: "android.hardware.nfc@1.0-INfcClientCallback-vts.profiler_genc++",
+    tools: ["hidl-gen", "vtsc"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lvts -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.nfc@1.0 && $(location vtsc) -mPROFILER -tSOURCE -b$(genDir) android/hardware/nfc/1.0/ $(genDir)/android/hardware/nfc/1.0/",
+    srcs: [
+        "INfcClientCallback.hal",
+        "types.hal",
+    ],
+    out: [
+        "android/hardware/nfc/1.0/NfcClientCallback.vts.cpp",
+        "android/hardware/nfc/1.0/types.vts.cpp",
+    ],
+}
+
+genrule {
+    name: "android.hardware.nfc@1.0-INfcClientCallback-vts.profiler_genc++_headers",
+    tools: ["hidl-gen", "vtsc"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lvts -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.nfc@1.0 && $(location vtsc) -mPROFILER -tHEADER -b$(genDir) android/hardware/nfc/1.0/ $(genDir)/android/hardware/nfc/1.0/",
+    srcs: [
+        "INfcClientCallback.hal",
+        "types.hal",
+    ],
+    out: [
+        "android/hardware/nfc/1.0/NfcClientCallback.vts.h",
+        "android/hardware/nfc/1.0/types.vts.h",
+    ],
+}
+
+cc_library_shared {
+    name: "android.hardware.nfc@1.0-INfcClientCallback-vts.profiler",
+    generated_sources: ["android.hardware.nfc@1.0-INfcClientCallback-vts.profiler_genc++"],
+    generated_headers: ["android.hardware.nfc@1.0-INfcClientCallback-vts.profiler_genc++_headers"],
+    export_generated_headers: ["android.hardware.nfc@1.0-INfcClientCallback-vts.profiler_genc++_headers"],
+    shared_libs: [
+        "libbase",
+        "libhidlbase",
+        "libhidltransport",
+        "libvts_profiling",
+        "libvts_multidevice_proto",
+        "libprotobuf-cpp-full",
+        "android.hidl.base@1.0",
+        "android.hardware.nfc@1.0",
+    ],
+}
diff --git a/nfc/1.0/vts/Android.mk b/nfc/1.0/vts/Android.mk
index e7dec14..f9e3276 100644
--- a/nfc/1.0/vts/Android.mk
+++ b/nfc/1.0/vts/Android.mk
@@ -16,68 +16,4 @@
 
 LOCAL_PATH := $(call my-dir)
 
-# build profiler for Nfc.
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := libvts_profiler_hidl_nfc@1.0
-
-LOCAL_SRC_FILES := \
-   Nfc.vts \
-   types.vts \
-
-LOCAL_C_INCLUDES += \
-  test/vts/drivers/libprofiling \
-
-LOCAL_VTS_MODE := PROFILER
-
-LOCAL_SHARED_LIBRARIES := \
-   android.hardware.nfc@1.0 \
-   libbase \
-   libcutils \
-   liblog \
-   libhidlbase \
-   libhidltransport \
-   libhwbinder \
-   libprotobuf-cpp-full \
-   libvts_common \
-   libvts_multidevice_proto \
-   libvts_profiling \
-   libutils \
-
-LOCAL_PROTOC_OPTIMIZE_TYPE := full
-
-include $(BUILD_SHARED_LIBRARY)
-
-# build profiler for NfcClientCallback.
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := libvts_profiler_hidl_nfc_client_callback_@1.0
-
-LOCAL_SRC_FILES := \
-   NfcClientCallback.vts \
-   types.vts \
-
-LOCAL_C_INCLUDES += \
-  test/vts/drivers/libprofiling \
-
-LOCAL_VTS_MODE := PROFILER
-
-LOCAL_SHARED_LIBRARIES := \
-   android.hardware.nfc@1.0 \
-   libbase \
-   libcutils \
-   liblog \
-   libhidlbase \
-   libhidltransport \
-   libhwbinder \
-   libprotobuf-cpp-full \
-   libvts_common \
-   libvts_multidevice_proto \
-   libvts_profiling \
-   libutils \
-
-LOCAL_PROTOC_OPTIMIZE_TYPE := full
-
-include $(BUILD_SHARED_LIBRARY)
-
-include $(call all-makefiles-under,$(LOCAL_PATH))
+include $(call all-subdir-makefiles)
diff --git a/nfc/1.0/vts/functional/vts/testcases/hal/nfc/hidl/host/NfcHidlBasicTest.py b/nfc/1.0/vts/functional/vts/testcases/hal/nfc/hidl/host/NfcHidlBasicTest.py
index ede7897..136704a 100644
--- a/nfc/1.0/vts/functional/vts/testcases/hal/nfc/hidl/host/NfcHidlBasicTest.py
+++ b/nfc/1.0/vts/functional/vts/testcases/hal/nfc/hidl/host/NfcHidlBasicTest.py
@@ -52,6 +52,7 @@
                                  target_version=1.0,
                                  target_package="android.hardware.nfc",
                                  target_component_name="INfc",
+                                 hw_binder_service_name="nfc_nci",
                                  bits=64)
 
     def tearDownClass(self):
diff --git a/power/1.0/vts/functional/power_hidl_hal_test.cpp b/power/1.0/vts/functional/power_hidl_hal_test.cpp
index 8833c04..045a34b 100644
--- a/power/1.0/vts/functional/power_hidl_hal_test.cpp
+++ b/power/1.0/vts/functional/power_hidl_hal_test.cpp
@@ -35,18 +35,8 @@
 class PowerHidlTest : public ::testing::Test {
  public:
   virtual void SetUp() override {
-    // TODO(b/33385836) Delete copied code
-    bool getStub = false;
-    char getSubProperty[PROPERTY_VALUE_MAX];
-    if (property_get("vts.hidl.get_stub", getSubProperty, "") > 0) {
-        if (!strcmp(getSubProperty, "true") || !strcmp(getSubProperty, "True") ||
-            !strcmp(getSubProperty, "1")) {
-            getStub = true;
-        }
-    }
-    power = IPower::getService("power", getStub);
+    power = IPower::getService("power");
     ASSERT_NE(power, nullptr);
-    ASSERT_EQ(!getStub, power->isRemote());
   }
 
   virtual void TearDown() override {}
diff --git a/power/1.0/vts/functional/vts/testcases/hal/power/hidl/target/AndroidTest.xml b/power/1.0/vts/functional/vts/testcases/hal/power/hidl/target/AndroidTest.xml
index bb80de2..0eb2142 100644
--- a/power/1.0/vts/functional/vts/testcases/hal/power/hidl/target/AndroidTest.xml
+++ b/power/1.0/vts/functional/vts/testcases/hal/power/hidl/target/AndroidTest.xml
@@ -24,6 +24,7 @@
             _32bit::DATA/nativetest/power_hidl_hal_test/power_hidl_hal_test,
             _64bit::DATA/nativetest64/power_hidl_hal_test/power_hidl_hal_test,
             "/>
+        <option name="test-config-path" value="vts/testcases/hal/power/hidl/target/HalPowerHidlTargetTest.config" />
         <option name="binary-test-type" value="gtest" />
         <option name="test-timeout" value="1m" />
     </test>
diff --git a/power/1.0/vts/functional/vts/testcases/hal/power/hidl/target/HalPowerHidlTargetTest.config b/power/1.0/vts/functional/vts/testcases/hal/power/hidl/target/HalPowerHidlTargetTest.config
new file mode 100644
index 0000000..54c0175
--- /dev/null
+++ b/power/1.0/vts/functional/vts/testcases/hal/power/hidl/target/HalPowerHidlTargetTest.config
@@ -0,0 +1,34 @@
+{
+    "use_gae_db": true,
+    "coverage": true,
+    "modules": [
+        {
+            "module_name": "system/lib64/hw/power.bullhead",
+            "git_project": {
+                "name": "device/lge/bullhead",
+                "path": "device/lge/bullhead"
+            }
+        },
+        {
+            "module_name": "system/lib64/hw/power.marlin",
+            "git_project": {
+                "name": "device/google/marlin",
+                "path": "device/google/marlin"
+            }
+        },
+        {
+            "module_name": "system/lib64/hw/power.sailfish",
+            "git_project": {
+                "name": "device/google/marlin",
+                "path": "device/google/marlin"
+            }
+        },
+        {
+            "module_name": "system/lib64/hw/android.hardware.power@1.0-impl",
+            "git_project": {
+                "name": "platform/hardware/interfaces",
+                "path": "hardware/interfaces"
+            }
+        }
+    ]
+}
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/tests/bar/1.0/Android.bp b/tests/bar/1.0/Android.bp
index 6ef8ac2..e4c79fa 100644
--- a/tests/bar/1.0/Android.bp
+++ b/tests/bar/1.0/Android.bp
@@ -6,10 +6,12 @@
     cmd: "$(location hidl-gen) -o $(genDir) -Lc++ -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.tests.bar@1.0",
     srcs: [
         "IBar.hal",
+        "IComplicated.hal",
         "IImportTypes.hal",
     ],
     out: [
         "android/hardware/tests/bar/1.0/BarAll.cpp",
+        "android/hardware/tests/bar/1.0/ComplicatedAll.cpp",
         "android/hardware/tests/bar/1.0/ImportTypesAll.cpp",
     ],
 }
@@ -20,6 +22,7 @@
     cmd: "$(location hidl-gen) -o $(genDir) -Lc++ -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.tests.bar@1.0",
     srcs: [
         "IBar.hal",
+        "IComplicated.hal",
         "IImportTypes.hal",
     ],
     out: [
@@ -28,6 +31,11 @@
         "android/hardware/tests/bar/1.0/BnBar.h",
         "android/hardware/tests/bar/1.0/BpBar.h",
         "android/hardware/tests/bar/1.0/BsBar.h",
+        "android/hardware/tests/bar/1.0/IComplicated.h",
+        "android/hardware/tests/bar/1.0/IHwComplicated.h",
+        "android/hardware/tests/bar/1.0/BnComplicated.h",
+        "android/hardware/tests/bar/1.0/BpComplicated.h",
+        "android/hardware/tests/bar/1.0/BsComplicated.h",
         "android/hardware/tests/bar/1.0/IImportTypes.h",
         "android/hardware/tests/bar/1.0/IHwImportTypes.h",
         "android/hardware/tests/bar/1.0/BnImportTypes.h",
diff --git a/tests/bar/1.0/IBar.hal b/tests/bar/1.0/IBar.hal
index 21c3473..5f94d07 100644
--- a/tests/bar/1.0/IBar.hal
+++ b/tests/bar/1.0/IBar.hal
@@ -17,9 +17,12 @@
 package android.hardware.tests.bar@1.0;
 
 import android.hardware.tests.foo@1.0::IFoo;
+import android.hardware.tests.foo@1.0::ISimple;
 import android.hardware.tests.foo@1.0::Abc;
 import android.hardware.tests.foo@1.0::Unrelated;
 
+import IComplicated;
+
 interface IBar extends android.hardware.tests.foo@1.0::IFoo {
 
     typedef android.hardware.tests.foo@1.0::IFoo FunkyAlias;
@@ -33,4 +36,6 @@
     expectNullHandle(handle h, Abc xyz) generates (bool hIsNull, bool xyzHasNull);
     takeAMask(BitField bf, bitfield<BitField> first, MyMask second, Mask third)
             generates (BitField bf, uint8_t first, uint8_t second, uint8_t third);
+
+    haveAInterface(ISimple i) generates (ISimple i);
 };
diff --git a/tests/bar/1.0/IComplicated.hal b/tests/bar/1.0/IComplicated.hal
new file mode 100644
index 0000000..deaef8d
--- /dev/null
+++ b/tests/bar/1.0/IComplicated.hal
@@ -0,0 +1,22 @@
+/*
+ * 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.tests.bar@1.0;
+
+import android.hardware.tests.foo@1.0::ISimple;
+
+interface IComplicated extends ISimple {
+};
diff --git a/tests/bar/1.0/default/Bar.cpp b/tests/bar/1.0/default/Bar.cpp
index a750fe4..4152bb9 100644
--- a/tests/bar/1.0/default/Bar.cpp
+++ b/tests/bar/1.0/default/Bar.cpp
@@ -165,6 +165,13 @@
     return Void();
 }
 
+Return<void> Bar::haveAInterface(const sp<ISimple> &in,
+            haveAInterface_cb _hidl_cb) {
+    _hidl_cb(in);
+    return Void();
+}
+
+
 IBar* HIDL_FETCH_IBar(const char* /* name */) {
     return new Bar();
 }
diff --git a/tests/bar/1.0/default/Bar.h b/tests/bar/1.0/default/Bar.h
index 71737fe..70bffe7 100644
--- a/tests/bar/1.0/default/Bar.h
+++ b/tests/bar/1.0/default/Bar.h
@@ -71,6 +71,8 @@
 
     Return<void> takeAMask(BitField bf, uint8_t first, const MyMask& second, uint8_t third,
             takeAMask_cb _hidl_cb) override;
+    Return<void> haveAInterface(const sp<ISimple> &in,
+            haveAInterface_cb _hidl_cb) override;
 
 private:
     sp<IFoo> mFoo;
diff --git a/tests/baz/1.0/IBaz.hal b/tests/baz/1.0/IBaz.hal
index 3e1e2b9..7c5d63a 100644
--- a/tests/baz/1.0/IBaz.hal
+++ b/tests/baz/1.0/IBaz.hal
@@ -49,6 +49,10 @@
     doStuffAndReturnAString() generates (string something);
     mapThisVector(vec<int32_t> param) generates (vec<int32_t> something);
     callMe(IBazCallback cb);
+
+    callMeLater(IBazCallback cb);
+    iAmFreeNow();
+
     useAnEnum(SomeEnum zzz) generates (SomeEnum kkk);
 
     haveSomeStrings(string[3] array) generates (string[2] result);
diff --git a/tests/baz/1.0/IBazCallback.hal b/tests/baz/1.0/IBazCallback.hal
index b59a107..503b970 100644
--- a/tests/baz/1.0/IBazCallback.hal
+++ b/tests/baz/1.0/IBazCallback.hal
@@ -18,4 +18,5 @@
 
 interface IBazCallback {
     heyItsMe(IBazCallback cb);
+    hey();
 };
diff --git a/tests/foo/1.0/ISimple.hal b/tests/foo/1.0/ISimple.hal
index 92e9d95..0d45835 100644
--- a/tests/foo/1.0/ISimple.hal
+++ b/tests/foo/1.0/ISimple.hal
@@ -18,4 +18,8 @@
 
 interface ISimple {
     getCookie() generates (int32_t cookie);
+    customVecInt() generates (vec<int32_t> chain);
+    customVecStr() generates (vec<string> chain);
+    mystr() generates (string str);
+    myhandle() generates (handle str);
 };
diff --git a/tests/msgq/1.0/ITestMsgQ.hal b/tests/msgq/1.0/ITestMsgQ.hal
index dcdc74a..b23f48f 100644
--- a/tests/msgq/1.0/ITestMsgQ.hal
+++ b/tests/msgq/1.0/ITestMsgQ.hal
@@ -17,6 +17,11 @@
 package android.hardware.tests.msgq@1.0;
 
 interface ITestMsgQ {
+    enum EventFlagBits : uint32_t {
+        FMQ_NOT_EMPTY = 1 << 0,
+        FMQ_NOT_FULL  = 1 << 1,
+    };
+
     /*
      * This method requests the service to set up a synchronous read/write
      * wait-free FMQ with the client as reader.
@@ -79,4 +84,11 @@
      */
     requestReadFmqUnsync(int32_t count) generates(bool ret);
 
+    /*
+     * This method requests the service to trigger a blocking read.
+     *
+     * @param count Number of messages to read.
+     *
+     */
+    oneway requestBlockingRead(int32_t count);
 };
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..3594745 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-config-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..0d19619
--- /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/cec/1.0/vts/functional/vts/testcases/hal/tv_cec/hidl/host/TvCecHidlTest.py b/tv/cec/1.0/vts/functional/vts/testcases/hal/tv_cec/hidl/host/TvCecHidlTest.py
index ba062d9..cd2374a 100644
--- a/tv/cec/1.0/vts/functional/vts/testcases/hal/tv_cec/hidl/host/TvCecHidlTest.py
+++ b/tv/cec/1.0/vts/functional/vts/testcases/hal/tv_cec/hidl/host/TvCecHidlTest.py
@@ -34,11 +34,15 @@
         self.dut.shell.InvokeTerminal("one")
         self.dut.shell.one.Execute("setenforce 0")  # SELinux permissive mode
 
+        self.dut.shell.one.Execute(
+            "setprop vts.hal.vts.hidl.get_stub true")
+
         self.dut.hal.InitHidlHal(target_type="tv_cec",
                                  target_basepaths=["/system/lib64"],
                                  target_version=1.0,
                                  target_package="android.hardware.tv.cec",
                                  target_component_name="IHdmiCec",
+                                 hw_binder_service_name="tv.cec",
                                  bits=64)
 
     def testGetCecVersion1(self):
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 dc4d25c..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
@@ -682,25 +701,6 @@
 LOCAL_GENERATED_SOURCES += $(GEN)
 
 #
-# Build types.hal (VehiclePermissionModel)
-#
-GEN := $(intermediates)/android/hardware/vehicle/V2_0/VehiclePermissionModel.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.VehiclePermissionModel
-
-$(GEN): $(LOCAL_PATH)/types.hal
-	$(transform-generated-source)
-LOCAL_GENERATED_SOURCES += $(GEN)
-
-#
 # Build types.hal (VehiclePropConfig)
 #
 GEN := $(intermediates)/android/hardware/vehicle/V2_0/VehiclePropConfig.java
@@ -1616,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
@@ -1635,25 +1654,6 @@
 LOCAL_GENERATED_SOURCES += $(GEN)
 
 #
-# Build types.hal (VehiclePermissionModel)
-#
-GEN := $(intermediates)/android/hardware/vehicle/V2_0/VehiclePermissionModel.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.VehiclePermissionModel
-
-$(GEN): $(LOCAL_PATH)/types.hal
-	$(transform-generated-source)
-LOCAL_GENERATED_SOURCES += $(GEN)
-
-#
 # Build types.hal (VehiclePropConfig)
 #
 GEN := $(intermediates)/android/hardware/vehicle/V2_0/VehiclePropConfig.java
diff --git a/vehicle/2.0/default/impl/DefaultConfig.h b/vehicle/2.0/default/impl/DefaultConfig.h
index e4ca5ca..77ee9d4 100644
--- a/vehicle/2.0/default/impl/DefaultConfig.h
+++ b/vehicle/2.0/default/impl/DefaultConfig.h
@@ -32,14 +32,12 @@
         .prop = VehicleProperty::INFO_MAKE,
         .access = VehiclePropertyAccess::READ,
         .changeMode = VehiclePropertyChangeMode::STATIC,
-        .permissionModel = VehiclePermissionModel::OEM_ONLY,
     },
 
     {
         .prop = VehicleProperty::HVAC_POWER_ON,
         .access = VehiclePropertyAccess::READ_WRITE,
         .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
-        .permissionModel = VehiclePermissionModel::NO_RESTRICTION,
         .supportedAreas = toInt(VehicleAreaZone::ROW_1)
     },
 
@@ -47,7 +45,6 @@
         .prop = VehicleProperty::HVAC_DEFROSTER,
         .access = VehiclePropertyAccess::READ_WRITE,
         .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
-        .permissionModel = VehiclePermissionModel::NO_RESTRICTION,
         .supportedAreas =
                 VehicleAreaWindow::FRONT_WINDSHIELD
                 | VehicleAreaWindow::REAR_WINDSHIELD
@@ -57,7 +54,6 @@
         .prop = VehicleProperty::HVAC_RECIRC_ON,
         .access = VehiclePropertyAccess::READ_WRITE,
         .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
-        .permissionModel = VehiclePermissionModel::NO_RESTRICTION,
         .supportedAreas = toInt(VehicleAreaZone::ROW_1)
     },
 
@@ -65,7 +61,6 @@
         .prop = VehicleProperty::HVAC_AC_ON,
         .access = VehiclePropertyAccess::READ_WRITE,
         .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
-        .permissionModel = VehiclePermissionModel::NO_RESTRICTION,
         .supportedAreas = toInt(VehicleAreaZone::ROW_1)
     },
 
@@ -73,7 +68,6 @@
         .prop = VehicleProperty::HVAC_AUTO_ON,
         .access = VehiclePropertyAccess::READ_WRITE,
         .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
-        .permissionModel = VehiclePermissionModel::NO_RESTRICTION,
         .supportedAreas = toInt(VehicleAreaZone::ROW_1)
     },
 
@@ -81,7 +75,6 @@
         .prop = VehicleProperty::HVAC_FAN_SPEED,
         .access = VehiclePropertyAccess::READ_WRITE,
         .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
-        .permissionModel = VehiclePermissionModel::NO_RESTRICTION,
         .supportedAreas = toInt(VehicleAreaZone::ROW_1),
         .areaConfigs = {
             VehicleAreaConfig {
@@ -96,7 +89,6 @@
         .prop = VehicleProperty::HVAC_FAN_DIRECTION,
         .access = VehiclePropertyAccess::READ_WRITE,
         .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
-        .permissionModel = VehiclePermissionModel::NO_RESTRICTION,
         .supportedAreas = toInt(VehicleAreaZone::ROW_1),
     },
 
@@ -104,7 +96,6 @@
         .prop = VehicleProperty::HVAC_TEMPERATURE_SET,
         .access = VehiclePropertyAccess::READ_WRITE,
         .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
-        .permissionModel = VehiclePermissionModel::NO_RESTRICTION,
         .supportedAreas =
                 VehicleAreaZone::ROW_1_LEFT
                 | VehicleAreaZone::ROW_1_RIGHT,
@@ -126,28 +117,24 @@
         .prop = VehicleProperty::NIGHT_MODE,
         .access = VehiclePropertyAccess::READ,
         .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
-        .permissionModel = VehiclePermissionModel::NO_RESTRICTION,
     },
 
     {
         .prop = VehicleProperty::DRIVING_STATUS,
         .access = VehiclePropertyAccess::READ,
         .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
-        .permissionModel = VehiclePermissionModel::NO_RESTRICTION,
     },
 
     {
         .prop = VehicleProperty::GEAR_SELECTION,
         .access = VehiclePropertyAccess::READ,
         .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
-        .permissionModel = VehiclePermissionModel::NO_RESTRICTION,
     },
 
     {
         .prop = VehicleProperty::INFO_FUEL_CAPACITY,
         .access = VehiclePropertyAccess::READ,
         .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
-        .permissionModel = VehiclePermissionModel::OEM_ONLY,
         .areaConfigs = {
             VehicleAreaConfig {
                 .minFloatValue = 0,
@@ -160,13 +147,18 @@
         .prop = VehicleProperty::DISPLAY_BRIGHTNESS,
         .access = VehiclePropertyAccess::READ_WRITE,
         .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
-        .permissionModel = VehiclePermissionModel::OEM_ONLY,
         .areaConfigs = {
             VehicleAreaConfig {
                 .minInt32Value = 0,
                 .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/default/tests/VehicleHalManager_test.cpp b/vehicle/2.0/default/tests/VehicleHalManager_test.cpp
index 964c7c8..dffcfbb 100644
--- a/vehicle/2.0/default/tests/VehicleHalManager_test.cpp
+++ b/vehicle/2.0/default/tests/VehicleHalManager_test.cpp
@@ -67,6 +67,14 @@
                     pValue = getValuePool()->obtainFloat(42.42);
                 }
                 break;
+            case VehicleProperty::VEHICLE_MAPS_DATA_SERVICE:
+                pValue = getValuePool()->obtainComplex();
+                pValue->value.int32Values = hidl_vec<int32_t> { 10, 20 };
+                pValue->value.int64Values = hidl_vec<int64_t> { 30, 40 };
+                pValue->value.floatValues = hidl_vec<float_t> { 1.1, 2.2 };
+                pValue->value.bytes = hidl_vec<uint8_t> { 1, 2, 3 };
+                pValue->value.stringValue = kCarMake;
+                break;
             default:
                 auto key = makeKey(property, areaId);
                 if (mValues.count(key) == 0) {
@@ -308,6 +316,32 @@
     ASSERT_EQ(StatusCode::OK, res);
 }
 
+TEST_F(VehicleHalManagerTest, get_Complex) {
+    invokeGet(VehicleProperty::VEHICLE_MAPS_DATA_SERVICE, 0);
+
+    ASSERT_EQ(StatusCode::OK, actualStatusCode);
+    ASSERT_EQ(VehicleProperty::VEHICLE_MAPS_DATA_SERVICE, actualValue.prop);
+
+    ASSERT_EQ(3, actualValue.value.bytes.size());
+    ASSERT_EQ(1, actualValue.value.bytes[0]);
+    ASSERT_EQ(2, actualValue.value.bytes[1]);
+    ASSERT_EQ(3, actualValue.value.bytes[2]);
+
+    ASSERT_EQ(2, actualValue.value.int32Values.size());
+    ASSERT_EQ(10, actualValue.value.int32Values[0]);
+    ASSERT_EQ(20, actualValue.value.int32Values[1]);
+
+    ASSERT_EQ(2, actualValue.value.floatValues.size());
+    ASSERT_FLOAT_EQ(1.1, actualValue.value.floatValues[0]);
+    ASSERT_FLOAT_EQ(2.2, actualValue.value.floatValues[1]);
+
+    ASSERT_EQ(2, actualValue.value.int64Values.size());
+    ASSERT_FLOAT_EQ(30, actualValue.value.int64Values[0]);
+    ASSERT_FLOAT_EQ(40, actualValue.value.int64Values[1]);
+
+    ASSERT_STREQ(kCarMake, actualValue.value.stringValue.c_str());
+}
+
 TEST_F(VehicleHalManagerTest, get_StaticString) {
     invokeGet(VehicleProperty::INFO_MAKE, 0);
 
diff --git a/vehicle/2.0/default/tests/VehicleHalTestUtils.h b/vehicle/2.0/default/tests/VehicleHalTestUtils.h
index 586b5ab..e1e355e 100644
--- a/vehicle/2.0/default/tests/VehicleHalTestUtils.h
+++ b/vehicle/2.0/default/tests/VehicleHalTestUtils.h
@@ -32,7 +32,6 @@
         .prop = VehicleProperty::INFO_MAKE,
         .access = VehiclePropertyAccess::READ,
         .changeMode = VehiclePropertyChangeMode::STATIC,
-        .permissionModel = VehiclePermissionModel::OEM_ONLY,
         .configString = "Some=config,options=if,you=have_any",
     },
 
@@ -40,7 +39,6 @@
         .prop = VehicleProperty::HVAC_FAN_SPEED,
         .access = VehiclePropertyAccess::READ_WRITE,
         .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
-        .permissionModel = VehiclePermissionModel::NO_RESTRICTION,
         .supportedAreas = static_cast<int32_t>(
             VehicleAreaZone::ROW_1_LEFT | VehicleAreaZone::ROW_1_RIGHT),
         .areaConfigs = {
@@ -61,7 +59,6 @@
         .prop = VehicleProperty::HVAC_SEAT_TEMPERATURE,
         .access = VehiclePropertyAccess::WRITE,
         .changeMode = VehiclePropertyChangeMode::ON_SET,
-        .permissionModel = VehiclePermissionModel::NO_RESTRICTION,
         .supportedAreas = static_cast<int32_t>(
             VehicleAreaZone::ROW_1_LEFT | VehicleAreaZone::ROW_1_RIGHT),
         .areaConfigs = {
@@ -81,7 +78,6 @@
         .prop = VehicleProperty::INFO_FUEL_CAPACITY,
         .access = VehiclePropertyAccess::READ,
         .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
-        .permissionModel = VehiclePermissionModel::OEM_ONLY,
         .areaConfigs = {
             VehicleAreaConfig {
                 .minFloatValue = 0,
@@ -94,7 +90,6 @@
         .prop = VehicleProperty::DISPLAY_BRIGHTNESS,
         .access = VehiclePropertyAccess::READ_WRITE,
         .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
-        .permissionModel = VehiclePermissionModel::OEM_ONLY,
         .areaConfigs = {
             VehicleAreaConfig {
                 .minInt32Value = 0,
@@ -107,8 +102,14 @@
         .prop = VehicleProperty::MIRROR_FOLD,
         .access = VehiclePropertyAccess::READ_WRITE,
         .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
-        .permissionModel = VehiclePermissionModel::OEM_ONLY,
 
+    },
+
+    // Complex data type.
+    {
+        .prop = VehicleProperty::VEHICLE_MAPS_DATA_SERVICE,
+        .access = VehiclePropertyAccess::READ_WRITE,
+        .changeMode = VehiclePropertyChangeMode::ON_CHANGE
     }
 };
 
@@ -238,7 +239,6 @@
        << "  prop: " << enumToHexString(config.prop) << ",\n"
        << "  supportedAreas: " << hexString(config.supportedAreas) << ",\n"
        << "  access: " << enumToHexString(config.access) << ",\n"
-       << "  permissionModel: " << enumToHexString(config.permissionModel) << ",\n"
        << "  changeMode: " << enumToHexString(config.changeMode) << ",\n"
        << "  configFlags: " << hexString(config.configFlags) << ",\n"
        << "  minSampleRate: " << config.minSampleRate << ",\n"
diff --git a/vehicle/2.0/default/vehicle_hal_manager/VehicleObjectPool.cpp b/vehicle/2.0/default/vehicle_hal_manager/VehicleObjectPool.cpp
index 70b93e7..463b333 100644
--- a/vehicle/2.0/default/vehicle_hal_manager/VehicleObjectPool.cpp
+++ b/vehicle/2.0/default/vehicle_hal_manager/VehicleObjectPool.cpp
@@ -80,6 +80,10 @@
     return val;
 }
 
+VehiclePropValuePool::RecyclableType VehiclePropValuePool::obtainComplex() {
+    return obtain(VehiclePropertyType::COMPLEX);
+}
+
 VehiclePropValuePool::RecyclableType VehiclePropValuePool::obtainRecylable(
         VehiclePropertyType type, size_t vecSize) {
     // VehiclePropertyType is not overlapping with vectorSize.
diff --git a/vehicle/2.0/default/vehicle_hal_manager/VehicleObjectPool.h b/vehicle/2.0/default/vehicle_hal_manager/VehicleObjectPool.h
index 1ca9211..d9231c3 100644
--- a/vehicle/2.0/default/vehicle_hal_manager/VehicleObjectPool.h
+++ b/vehicle/2.0/default/vehicle_hal_manager/VehicleObjectPool.h
@@ -184,13 +184,15 @@
     RecyclableType obtainInt64(int64_t value);
     RecyclableType obtainFloat(float value);
     RecyclableType obtainString(const char* cstr);
+    RecyclableType obtainComplex();
 
     VehiclePropValuePool(VehiclePropValuePool& ) = delete;
     VehiclePropValuePool& operator=(VehiclePropValuePool&) = delete;
 private:
     bool isDisposable(VehiclePropertyType type, size_t vecSize) const {
         return vecSize > mMaxRecyclableVectorSize ||
-               VehiclePropertyType::STRING == type;
+               VehiclePropertyType::STRING == type ||
+               VehiclePropertyType::COMPLEX == type;
     }
 
     RecyclableType obtainDisposable(VehiclePropertyType valueType,
diff --git a/vehicle/2.0/default/vehicle_hal_manager/VehicleUtils.cpp b/vehicle/2.0/default/vehicle_hal_manager/VehicleUtils.cpp
index c461833..ab1d908 100644
--- a/vehicle/2.0/default/vehicle_hal_manager/VehicleUtils.cpp
+++ b/vehicle/2.0/default/vehicle_hal_manager/VehicleUtils.cpp
@@ -47,6 +47,7 @@
             val->value.bytes.resize(vecSize);
             break;
         case VehiclePropertyType::STRING:
+        case VehiclePropertyType::COMPLEX:
             break; // Valid, but nothing to do.
         default:
             ALOGE("createVehiclePropValue: unknown type: %d", type);
diff --git a/vehicle/2.0/types.hal b/vehicle/2.0/types.hal
index 72fa554..28ccb78 100644
--- a/vehicle/2.0/types.hal
+++ b/vehicle/2.0/types.hal
@@ -31,6 +31,12 @@
     FLOAT_VEC      = 0x00610000,
     BYTES          = 0x00700000,
 
+    /*
+     * Any combination of scalar or vector types. The exact format must be
+     * provided in the description of the property.
+     */
+    COMPLEX        = 0x00e00000,
+
     MASK           = 0x00ff0000
 };
 
@@ -310,6 +316,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 +1632,18 @@
         | VehiclePropertyGroup:SYSTEM
         | VehiclePropertyType:BOOLEAN
         | VehicleArea:GLOBAL),
+
+    /*
+     * Vehicle Maps Data Service (VMDS) message
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     */
+    VEHICLE_MAPS_DATA_SERVICE = (
+        0x0C00
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:COMPLEX
+        | VehicleArea:GLOBAL),
 };
 
 /*
@@ -2144,30 +2174,6 @@
 };
 
 /*
- * These permissions define how the OEMs want to distribute their information
- * and security they want to apply. On top of these restrictions, android will
- * have additional 'app-level' permissions that the apps will need to ask the
- * user before the apps have the information.
- * This information must be kept in VehiclePropConfig#permissionModel.
- */
-enum VehiclePermissionModel : int32_t {
-  /*
-   * No special restriction, but each property can still require specific
-   * android app-level permission.
-   */
-  NO_RESTRICTION = 0,
-
-  /* Signature only. Only APKs signed with OEM keys are allowed. */
-  OEM_ONLY = 0x1,
-
-  /* System only. APKs built-in to system  can access the property. */
-  SYSTEM_APP_ONLY = 0x2,
-
-  /* Equivalent to “system|signature” */
-  OEM_OR_SYSTEM_APP = 0x3,
-};
-
-/*
  * Car states.
  *
  * The driving states determine what features of the UI will be accessible.
@@ -2311,11 +2317,6 @@
     VehiclePropertyChangeMode changeMode;
 
     /*
-     * Defines permission model to access the data.
-     */
-    VehiclePermissionModel permissionModel;
-
-    /*
      * Some of the properties may have associated areas (for example, some hvac
      * properties are associated with VehicleAreaZone), in these
      * cases the config may contain an ORed value for the associated areas.
@@ -2405,6 +2406,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.
diff --git a/vehicle/2.0/vts/functional/vts/testcases/hal/vehicle/hidl/host/VehicleHidlTest.py b/vehicle/2.0/vts/functional/vts/testcases/hal/vehicle/hidl/host/VehicleHidlTest.py
index bc37e59..8da36d1 100644
--- a/vehicle/2.0/vts/functional/vts/testcases/hal/vehicle/hidl/host/VehicleHidlTest.py
+++ b/vehicle/2.0/vts/functional/vts/testcases/hal/vehicle/hidl/host/VehicleHidlTest.py
@@ -33,6 +33,7 @@
         self.dut = self.registerController(android_device)[0]
 
         self.dut.shell.InvokeTerminal("one")
+        self.dut.shell.one.Execute("setenforce 0")  # SELinux permissive mode
 
         if self.enable_profiling:
             profiling_utils.EnableVTSProfiling(self.dut.shell.one)
@@ -55,25 +56,13 @@
             self.ProcessAndUploadTraceData(self.dut, profiling_trace_path)
             profiling_utils.DisableVTSProfiling(self.dut.shell.one)
 
-    def testEcho1(self):
-        """A simple testcase which sends a command."""
-        self.dut.shell.InvokeTerminal("my_shell1")  # creates a remote shell instance.
-        results = self.dut.shell.my_shell1.Execute("echo hello_world")  # runs a shell command.
-        logging.info(str(results[const.STDOUT]))  # prints the stdout
-        asserts.assertEqual(results[const.STDOUT][0].strip(), "hello_world")  # checks the stdout
-        asserts.assertEqual(results[const.EXIT_CODE][0], 0)  # checks the exit code
+    def testListProperties(self):
+        logging.info("vehicle_types")
+        vehicle_types = self.dut.hal.vehicle.GetHidlTypeInterface("types")
+        logging.info("vehicle_types: %s", vehicle_types)
 
-    def testEcho2(self):
-        """A simple testcase which sends two commands."""
-        self.dut.shell.InvokeTerminal("my_shell2")
-        my_shell = getattr(self.dut.shell, "my_shell2")
-        results = my_shell.Execute(["echo hello", "echo world"])
-        logging.info(str(results[const.STDOUT]))
-        asserts.assertEqual(len(results[const.STDOUT]), 2)  # check the number of processed commands
-        asserts.assertEqual(results[const.STDOUT][0].strip(), "hello")
-        asserts.assertEqual(results[const.STDOUT][1].strip(), "world")
-        asserts.assertEqual(results[const.EXIT_CODE][0], 0)
-        asserts.assertEqual(results[const.EXIT_CODE][1], 0)
+        allConfigs = self.dut.hal.vehicle.getAllPropConfigs()
+        logging.info("all supported properties: %s", allConfigs)
 
 if __name__ == "__main__":
     test_runner.main()
diff --git a/vehicle/2.0/vts/types.vts b/vehicle/2.0/vts/types.vts
index fc63add..99fa6e7 100644
--- a/vehicle/2.0/vts/types.vts
+++ b/vehicle/2.0/vts/types.vts
@@ -1149,6 +1149,10 @@
     enum_value: {
         scalar_type: "int32_t"
 
+        enumerator: "NONE"
+        scalar_value: {
+            int32_t: 0
+        }
         enumerator: "READ"
         scalar_value: {
             int32_t: 1
@@ -1165,31 +1169,6 @@
 }
 
 attribute: {
-    name: "::android::hardware::vehicle::V2_0::VehiclePermissionModel"
-    type: TYPE_ENUM
-    enum_value: {
-        scalar_type: "int32_t"
-
-        enumerator: "NO_RESTRICTION"
-        scalar_value: {
-            int32_t: 0
-        }
-        enumerator: "OEM_ONLY"
-        scalar_value: {
-            int32_t: 1
-        }
-        enumerator: "SYSTEM_APP_ONLY"
-        scalar_value: {
-            int32_t: 2
-        }
-        enumerator: "OEM_OR_SYSTEM_APP"
-        scalar_value: {
-            int32_t: 3
-        }
-    }
-}
-
-attribute: {
     name: "::android::hardware::vehicle::V2_0::VehicleDrivingStatus"
     type: TYPE_ENUM
     enum_value: {
@@ -1600,11 +1579,6 @@
         predefined_type: "::android::hardware::vehicle::V2_0::VehiclePropertyChangeMode"
     }
     struct_value: {
-        name: "permissionModel"
-        type: TYPE_ENUM
-        predefined_type: "::android::hardware::vehicle::V2_0::VehiclePermissionModel"
-    }
-    struct_value: {
         name: "supportedAreas"
         type: TYPE_SCALAR
         scalar_type: "int32_t"
diff --git a/vibrator/1.0/vts/functional/vts/testcases/hal/vibrator/hidl/host/VibratorHidlTest.py b/vibrator/1.0/vts/functional/vts/testcases/hal/vibrator/hidl/host/VibratorHidlTest.py
index e8fae30..b36f47a 100644
--- a/vibrator/1.0/vts/functional/vts/testcases/hal/vibrator/hidl/host/VibratorHidlTest.py
+++ b/vibrator/1.0/vts/functional/vts/testcases/hal/vibrator/hidl/host/VibratorHidlTest.py
@@ -48,6 +48,7 @@
             target_version=1.0,
             target_package="android.hardware.vibrator",
             target_component_name="IVibrator",
+            hw_binder_service_name="vibrator",
             bits=64)
 
     def tearDownClass(self):
diff --git a/wifi/1.0/vts/functional/Android.bp b/wifi/1.0/vts/functional/Android.bp
new file mode 100644
index 0000000..422eec5
--- /dev/null
+++ b/wifi/1.0/vts/functional/Android.bp
@@ -0,0 +1,50 @@
+//
+// Copyright (C) 2016 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+cc_test {
+    name: "wifi_hidl_test",
+    gtest: true,
+    srcs: [
+        "main.cpp",
+        "wifi_ap_iface_hidl_test.cpp",
+        "wifi_chip_hidl_test.cpp",
+        "wifi_hidl_test.cpp",
+        "wifi_hidl_test_utils.cpp",
+        "wifi_nan_iface_hidl_test.cpp",
+        "wifi_p2p_iface_hidl_test.cpp",
+        "wifi_rtt_controller_hidl_test.cpp",
+        "wifi_sta_iface_hidl_test.cpp"],
+    shared_libs: [
+        "libbase",
+        "liblog",
+        "libcutils",
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "libnativehelper",
+        "libutils",
+        "android.hardware.wifi@1.0",
+    ],
+    static_libs: ["libgtest"],
+    cflags: [
+        "--coverage",
+        "-O0",
+        "-g",
+    ],
+    ldflags: [
+        "--coverage"
+    ]
+}
diff --git a/wifi/1.0/vts/functional/Android.mk b/wifi/1.0/vts/functional/Android.mk
new file mode 100644
index 0000000..f9e3276
--- /dev/null
+++ b/wifi/1.0/vts/functional/Android.mk
@@ -0,0 +1,19 @@
+#
+# 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)
diff --git a/wifi/1.0/vts/functional/main.cpp b/wifi/1.0/vts/functional/main.cpp
new file mode 100644
index 0000000..b33b5eb
--- /dev/null
+++ b/wifi/1.0/vts/functional/main.cpp
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <android-base/logging.h>
+
+#include <gtest/gtest.h>
+
+#include "wifi_hidl_test_utils.h"
+
+class WifiHidlEnvironment : public ::testing::Environment {
+   public:
+    virtual void SetUp() override { stopFramework(); }
+    virtual void TearDown() override { startFramework(); }
+
+   private:
+};
+
+int main(int argc, char** argv) {
+    ::testing::AddGlobalTestEnvironment(new WifiHidlEnvironment);
+    ::testing::InitGoogleTest(&argc, argv);
+    int status = RUN_ALL_TESTS();
+    LOG(INFO) << "Test result = " << status;
+    return status;
+}
diff --git a/wifi/1.0/vts/functional/wifi_ap_iface_hidl_test.cpp b/wifi/1.0/vts/functional/wifi_ap_iface_hidl_test.cpp
new file mode 100644
index 0000000..dc7b0b9
--- /dev/null
+++ b/wifi/1.0/vts/functional/wifi_ap_iface_hidl_test.cpp
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <android-base/logging.h>
+
+#include <android/hardware/wifi/1.0/IWifiApIface.h>
+
+#include <gtest/gtest.h>
+
+#include "wifi_hidl_test_utils.h"
+
+using ::android::hardware::wifi::V1_0::IWifiApIface;
+using ::android::sp;
+
+/**
+ * Fixture to use for all AP Iface HIDL interface tests.
+ */
+class WifiApIfaceHidlTest : public ::testing::Test {
+   public:
+    virtual void SetUp() override {}
+
+    virtual void TearDown() override { stopWifi(); }
+
+   protected:
+};
+
+/*
+ * Create:
+ * Ensures that an instance of the IWifiApIface proxy object is
+ * successfully created.
+ */
+TEST(WifiApIfaceHidlTestNoFixture, Create) {
+    EXPECT_NE(nullptr, getWifiApIface().get());
+    stopWifi();
+}
diff --git a/wifi/1.0/vts/functional/wifi_chip_hidl_test.cpp b/wifi/1.0/vts/functional/wifi_chip_hidl_test.cpp
new file mode 100644
index 0000000..b6ecd8b
--- /dev/null
+++ b/wifi/1.0/vts/functional/wifi_chip_hidl_test.cpp
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <android-base/logging.h>
+
+#include <android/hardware/wifi/1.0/IWifiChip.h>
+
+#include <gtest/gtest.h>
+
+#include "wifi_hidl_test_utils.h"
+
+using ::android::hardware::wifi::V1_0::IWifiChip;
+using ::android::sp;
+
+/**
+ * Fixture to use for all Wifi chip HIDL interface tests.
+ */
+class WifiChipHidlTest : public ::testing::Test {
+   public:
+    virtual void SetUp() override {}
+
+    virtual void TearDown() override { stopWifi(); }
+
+   protected:
+};
+
+/*
+ * Create:
+ * Ensures that an instance of the IWifiChip proxy object is
+ * successfully created.
+ */
+TEST(WifiChipHidlTestNoFixture, Create) {
+    EXPECT_NE(nullptr, getWifiChip().get());
+    stopWifi();
+}
diff --git a/wifi/1.0/vts/functional/wifi_hidl_test.cpp b/wifi/1.0/vts/functional/wifi_hidl_test.cpp
new file mode 100644
index 0000000..3e350e5
--- /dev/null
+++ b/wifi/1.0/vts/functional/wifi_hidl_test.cpp
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <android-base/logging.h>
+
+#include <android/hardware/wifi/1.0/IWifi.h>
+
+#include <gtest/gtest.h>
+
+#include "wifi_hidl_test_utils.h"
+
+using ::android::hardware::wifi::V1_0::IWifi;
+using ::android::sp;
+
+/**
+ * Fixture to use for all root Wifi HIDL interface tests.
+ */
+class WifiHidlTest : public ::testing::Test {
+   public:
+    virtual void SetUp() override {}
+
+    virtual void TearDown() override { stopWifi(); }
+
+   protected:
+};
+
+/*
+ * Create:
+ * Ensures that an instance of the IWifi proxy object is
+ * successfully created.
+ */
+TEST(WifiHidlTestNoFixture, Create) {
+    EXPECT_NE(nullptr, getWifi().get());
+    stopWifi();
+}
diff --git a/wifi/1.0/vts/functional/wifi_hidl_test_utils.cpp b/wifi/1.0/vts/functional/wifi_hidl_test_utils.cpp
new file mode 100644
index 0000000..f88b866
--- /dev/null
+++ b/wifi/1.0/vts/functional/wifi_hidl_test_utils.cpp
@@ -0,0 +1,278 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gtest/gtest.h>
+
+#include "wifi_hidl_test_utils.h"
+
+using ::android::hardware::wifi::V1_0::IWifi;
+using ::android::hardware::wifi::V1_0::IWifiApIface;
+using ::android::hardware::wifi::V1_0::IWifiChip;
+using ::android::hardware::wifi::V1_0::IWifiNanIface;
+using ::android::hardware::wifi::V1_0::IWifiP2pIface;
+using ::android::hardware::wifi::V1_0::IWifiRttController;
+using ::android::hardware::wifi::V1_0::IWifiStaIface;
+using ::android::hardware::wifi::V1_0::ChipModeId;
+using ::android::hardware::wifi::V1_0::ChipId;
+using ::android::hardware::wifi::V1_0::IfaceType;
+using ::android::hardware::wifi::V1_0::WifiStatus;
+using ::android::hardware::wifi::V1_0::WifiStatusCode;
+using ::android::sp;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+
+const char kWifiServiceName[] = "wifi";
+
+void stopFramework() {
+    ASSERT_EQ(std::system("svc wifi disable"), 0);
+    sleep(5);
+}
+
+void startFramework() { ASSERT_EQ(std::system("svc wifi enable"), 0); }
+
+sp<IWifi> getWifi() {
+    sp<IWifi> wifi = IWifi::getService(kWifiServiceName);
+    return wifi;
+}
+
+sp<IWifiChip> getWifiChip() {
+    sp<IWifi> wifi = getWifi();
+    if (!wifi.get()) {
+        return nullptr;
+    }
+
+    bool operation_failed = false;
+    wifi->start([&](WifiStatus status) {
+        if (status.code != WifiStatusCode::SUCCESS) {
+            operation_failed = true;
+        }
+    });
+    if (operation_failed) {
+        return nullptr;
+    }
+
+    std::vector<ChipId> wifi_chip_ids;
+    wifi->getChipIds(
+        [&](const WifiStatus& status, const hidl_vec<ChipId>& chip_ids) {
+            if (status.code != WifiStatusCode::SUCCESS) {
+                operation_failed = true;
+            }
+            wifi_chip_ids = chip_ids;
+        });
+    // We don't expect more than 1 chip currently.
+    if (operation_failed || wifi_chip_ids.size() != 1) {
+        return nullptr;
+    }
+
+    sp<IWifiChip> wifi_chip;
+    wifi->getChip(wifi_chip_ids[0],
+                  [&](const WifiStatus& status, const sp<IWifiChip>& chip) {
+                      if (status.code != WifiStatusCode::SUCCESS) {
+                          operation_failed = true;
+                      }
+                      wifi_chip = chip;
+                  });
+    if (operation_failed) {
+        return nullptr;
+    }
+    return wifi_chip;
+}
+
+// Since we currently only support one iface of each type. Just iterate thru the
+// modes of operation and find the mode ID to use for that iface type.
+bool findModeToSupportIfaceType(IfaceType type,
+                                const std::vector<IWifiChip::ChipMode>& modes,
+                                ChipModeId* mode_id) {
+    for (const auto& mode : modes) {
+        std::vector<IWifiChip::ChipIfaceCombination> combinations =
+            mode.availableCombinations;
+        for (const auto& combination : combinations) {
+            std::vector<IWifiChip::ChipIfaceCombinationLimit> iface_limits =
+                combination.limits;
+            for (const auto& iface_limit : iface_limits) {
+                std::vector<IfaceType> iface_types = iface_limit.types;
+                for (const auto& iface_type : iface_types) {
+                    if (iface_type == type) {
+                        *mode_id = mode.id;
+                        return true;
+                    }
+                }
+            }
+        }
+    }
+    return false;
+}
+
+bool configureChipToSupportIfaceType(const sp<IWifiChip>& wifi_chip,
+                                     IfaceType type) {
+    bool operation_failed = false;
+    std::vector<IWifiChip::ChipMode> chip_modes;
+    wifi_chip->getAvailableModes(
+        [&](WifiStatus status, const hidl_vec<IWifiChip::ChipMode>& modes) {
+            if (status.code != WifiStatusCode::SUCCESS) {
+                operation_failed = true;
+            }
+            chip_modes = modes;
+        });
+    if (operation_failed) {
+        return false;
+    }
+
+    ChipModeId mode_id;
+    if (!findModeToSupportIfaceType(type, chip_modes, &mode_id)) {
+        return false;
+    }
+
+    wifi_chip->configureChip(mode_id, [&](WifiStatus status) {
+        if (status.code != WifiStatusCode::SUCCESS) {
+            operation_failed = true;
+        }
+    });
+    if (operation_failed) {
+        return false;
+    }
+    return true;
+}
+
+sp<IWifiApIface> getWifiApIface() {
+    sp<IWifiChip> wifi_chip = getWifiChip();
+    if (!wifi_chip.get()) {
+        return nullptr;
+    }
+    if (!configureChipToSupportIfaceType(wifi_chip, IfaceType::AP)) {
+        return nullptr;
+    }
+
+    bool operation_failed = false;
+    sp<IWifiApIface> wifi_ap_iface;
+    wifi_chip->createApIface(
+        [&](const WifiStatus& status, const sp<IWifiApIface>& iface) {
+            if (status.code != WifiStatusCode::SUCCESS) {
+                operation_failed = true;
+            }
+            wifi_ap_iface = iface;
+        });
+    if (operation_failed) {
+        return nullptr;
+    }
+    return wifi_ap_iface;
+}
+
+sp<IWifiNanIface> getWifiNanIface() {
+    sp<IWifiChip> wifi_chip = getWifiChip();
+    if (!wifi_chip.get()) {
+        return nullptr;
+    }
+    if (!configureChipToSupportIfaceType(wifi_chip, IfaceType::NAN)) {
+        return nullptr;
+    }
+
+    bool operation_failed = false;
+    sp<IWifiNanIface> wifi_nan_iface;
+    wifi_chip->createNanIface(
+        [&](const WifiStatus& status, const sp<IWifiNanIface>& iface) {
+            if (status.code != WifiStatusCode::SUCCESS) {
+                operation_failed = true;
+            }
+            wifi_nan_iface = iface;
+        });
+    if (operation_failed) {
+        return nullptr;
+    }
+    return wifi_nan_iface;
+}
+
+sp<IWifiP2pIface> getWifiP2pIface() {
+    sp<IWifiChip> wifi_chip = getWifiChip();
+    if (!wifi_chip.get()) {
+        return nullptr;
+    }
+    if (!configureChipToSupportIfaceType(wifi_chip, IfaceType::P2P)) {
+        return nullptr;
+    }
+
+    bool operation_failed = false;
+    sp<IWifiP2pIface> wifi_p2p_iface;
+    wifi_chip->createP2pIface(
+        [&](const WifiStatus& status, const sp<IWifiP2pIface>& iface) {
+            if (status.code != WifiStatusCode::SUCCESS) {
+                operation_failed = true;
+            }
+            wifi_p2p_iface = iface;
+        });
+    if (operation_failed) {
+        return nullptr;
+    }
+    return wifi_p2p_iface;
+}
+
+sp<IWifiStaIface> getWifiStaIface() {
+    sp<IWifiChip> wifi_chip = getWifiChip();
+    if (!wifi_chip.get()) {
+        return nullptr;
+    }
+    if (!configureChipToSupportIfaceType(wifi_chip, IfaceType::STA)) {
+        return nullptr;
+    }
+
+    bool operation_failed = false;
+    sp<IWifiStaIface> wifi_sta_iface;
+    wifi_chip->createStaIface(
+        [&](const WifiStatus& status, const sp<IWifiStaIface>& iface) {
+            if (status.code != WifiStatusCode::SUCCESS) {
+                operation_failed = true;
+            }
+            wifi_sta_iface = iface;
+        });
+    if (operation_failed) {
+        return nullptr;
+    }
+    return wifi_sta_iface;
+}
+
+sp<IWifiRttController> getWifiRttController() {
+    sp<IWifiChip> wifi_chip = getWifiChip();
+    if (!wifi_chip.get()) {
+        return nullptr;
+    }
+    sp<IWifiStaIface> wifi_sta_iface = getWifiStaIface();
+    if (!wifi_sta_iface.get()) {
+        return nullptr;
+    }
+
+    bool operation_failed = false;
+    sp<IWifiRttController> wifi_rtt_controller;
+    wifi_chip->createRttController(
+        wifi_sta_iface, [&](const WifiStatus& status,
+                            const sp<IWifiRttController>& controller) {
+            if (status.code != WifiStatusCode::SUCCESS) {
+                operation_failed = true;
+            }
+            wifi_rtt_controller = controller;
+        });
+    if (operation_failed) {
+        return nullptr;
+    }
+    return wifi_rtt_controller;
+}
+
+void stopWifi() {
+    sp<IWifi> wifi = getWifi();
+    ASSERT_NE(wifi, nullptr);
+    wifi->stop([](const WifiStatus& status) {
+        ASSERT_EQ(status.code, WifiStatusCode::SUCCESS);
+    });
+}
diff --git a/wifi/1.0/vts/functional/wifi_hidl_test_utils.h b/wifi/1.0/vts/functional/wifi_hidl_test_utils.h
new file mode 100644
index 0000000..08933d9
--- /dev/null
+++ b/wifi/1.0/vts/functional/wifi_hidl_test_utils.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <android/hardware/wifi/1.0/IWifi.h>
+#include <android/hardware/wifi/1.0/IWifiApIface.h>
+#include <android/hardware/wifi/1.0/IWifiChip.h>
+#include <android/hardware/wifi/1.0/IWifiNanIface.h>
+#include <android/hardware/wifi/1.0/IWifiP2pIface.h>
+#include <android/hardware/wifi/1.0/IWifiRttController.h>
+#include <android/hardware/wifi/1.0/IWifiStaIface.h>
+
+// Used to stop the android framework (wifi service) before every
+// test.
+void stopFramework();
+void startFramework();
+
+// Helper functions to obtain references to the various HIDL interface objects.
+// Note: We only have a single instance of each of these objects currently.
+// These helper functions should be modified to return vectors if we support
+// multiple instances.
+android::sp<android::hardware::wifi::V1_0::IWifi> getWifi();
+android::sp<android::hardware::wifi::V1_0::IWifiChip> getWifiChip();
+android::sp<android::hardware::wifi::V1_0::IWifiApIface> getWifiApIface();
+android::sp<android::hardware::wifi::V1_0::IWifiNanIface> getWifiNanIface();
+android::sp<android::hardware::wifi::V1_0::IWifiP2pIface> getWifiP2pIface();
+android::sp<android::hardware::wifi::V1_0::IWifiStaIface> getWifiStaIface();
+android::sp<android::hardware::wifi::V1_0::IWifiRttController>
+getWifiRttController();
+// Used to trigger IWifi.stop() at the end of every test.
+void stopWifi();
diff --git a/wifi/1.0/vts/functional/wifi_nan_iface_hidl_test.cpp b/wifi/1.0/vts/functional/wifi_nan_iface_hidl_test.cpp
new file mode 100644
index 0000000..a8be48c
--- /dev/null
+++ b/wifi/1.0/vts/functional/wifi_nan_iface_hidl_test.cpp
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Nanache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <android-base/logging.h>
+
+#include <android/hardware/wifi/1.0/IWifiNanIface.h>
+
+#include <gtest/gtest.h>
+
+#include "wifi_hidl_test_utils.h"
+
+using ::android::hardware::wifi::V1_0::IWifiNanIface;
+using ::android::sp;
+
+/**
+ * Fixture to use for all NAN Iface HIDL interface tests.
+ */
+class WifiNanIfaceHidlTest : public ::testing::Test {
+   public:
+    virtual void SetUp() override {}
+
+    virtual void TearDown() override { stopWifi(); }
+
+   protected:
+};
+
+/*
+ * Create:
+ * Ensures that an instance of the IWifiNanIface proxy object is
+ * successfully created.
+ */
+TEST(WifiNanIfaceHidlTestNoFixture, Create) {
+    EXPECT_NE(nullptr, getWifiNanIface().get());
+    stopWifi();
+}
diff --git a/wifi/1.0/vts/functional/wifi_p2p_iface_hidl_test.cpp b/wifi/1.0/vts/functional/wifi_p2p_iface_hidl_test.cpp
new file mode 100644
index 0000000..e29226d
--- /dev/null
+++ b/wifi/1.0/vts/functional/wifi_p2p_iface_hidl_test.cpp
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the P2pache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <android-base/logging.h>
+
+#include <android/hardware/wifi/1.0/IWifiP2pIface.h>
+
+#include <gtest/gtest.h>
+
+#include "wifi_hidl_test_utils.h"
+
+using ::android::hardware::wifi::V1_0::IWifiP2pIface;
+using ::android::sp;
+
+/**
+ * Fixture to use for all P2P Iface HIDL interface tests.
+ */
+class WifiP2pIfaceHidlTest : public ::testing::Test {
+   public:
+    virtual void SetUp() override {}
+
+    virtual void TearDown() override { stopWifi(); }
+
+   protected:
+};
+
+/*
+ * Create:
+ * Ensures that an instance of the IWifiP2pIface proxy object is
+ * successfully created.
+ */
+TEST(WifiP2pIfaceHidlTestNoFixture, Create) {
+    EXPECT_NE(nullptr, getWifiP2pIface().get());
+    stopWifi();
+}
diff --git a/wifi/1.0/vts/functional/wifi_rtt_controller_hidl_test.cpp b/wifi/1.0/vts/functional/wifi_rtt_controller_hidl_test.cpp
new file mode 100644
index 0000000..7aee761
--- /dev/null
+++ b/wifi/1.0/vts/functional/wifi_rtt_controller_hidl_test.cpp
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <android-base/logging.h>
+
+#include <android/hardware/wifi/1.0/IWifiRttController.h>
+
+#include <gtest/gtest.h>
+
+#include "wifi_hidl_test_utils.h"
+
+using ::android::hardware::wifi::V1_0::IWifiRttController;
+using ::android::sp;
+
+/**
+ * Fixture to use for all RTT controller HIDL interface tests.
+ */
+class WifiRttControllerHidlTest : public ::testing::Test {
+   public:
+    virtual void SetUp() override {}
+
+    virtual void TearDown() override { stopWifi(); }
+
+   protected:
+};
+
+/*
+ * Create:
+ * Ensures that an instance of the IWifiRttController proxy object is
+ * successfully created.
+ */
+TEST(WifiRttControllerHidlTestNoFixture, Create) {
+    EXPECT_NE(nullptr, getWifiRttController().get());
+    stopWifi();
+}
diff --git a/wifi/1.0/vts/functional/wifi_sta_iface_hidl_test.cpp b/wifi/1.0/vts/functional/wifi_sta_iface_hidl_test.cpp
new file mode 100644
index 0000000..770763c
--- /dev/null
+++ b/wifi/1.0/vts/functional/wifi_sta_iface_hidl_test.cpp
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Staache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <android-base/logging.h>
+
+#include <android/hardware/wifi/1.0/IWifiStaIface.h>
+
+#include <gtest/gtest.h>
+
+#include "wifi_hidl_test_utils.h"
+
+using ::android::hardware::wifi::V1_0::IWifiStaIface;
+using ::android::sp;
+
+/**
+ * Fixture to use for all STA Iface HIDL interface tests.
+ */
+class WifiStaIfaceHidlTest : public ::testing::Test {
+   public:
+    virtual void SetUp() override {}
+
+    virtual void TearDown() override { stopWifi(); }
+
+   protected:
+};
+
+/*
+ * Create:
+ * Ensures that an instance of the IWifiStaIface proxy object is
+ * successfully created.
+ */
+TEST(WifiStaIfaceHidlTestNoFixture, Create) {
+    EXPECT_NE(nullptr, getWifiStaIface().get());
+    stopWifi();
+}
diff --git a/wifi/Android.bp b/wifi/Android.bp
index ea43db4..d4e0fda 100644
--- a/wifi/Android.bp
+++ b/wifi/Android.bp
@@ -1,5 +1,6 @@
 // This is an autogenerated file, do not edit.
 subdirs = [
     "1.0",
+    "1.0/vts/functional",
     "supplicant/1.0",
 ]