Merge "Revert "Update cas@1.0 hal to cas@1.1""
diff --git a/.clang-format b/.clang-format
deleted file mode 100644
index 3494682..0000000
--- a/.clang-format
+++ /dev/null
@@ -1,25 +0,0 @@
-#
-# Copyright (C) 2017 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-BasedOnStyle: Google
-CommentPragmas: NOLINT:.*
-DerivePointerAlignment: false
-AllowShortFunctionsOnASingleLine: Inline
-ColumnLimit: 100
-TabWidth: 4
-UseTab: Never
-IndentWidth: 4
-ContinuationIndentWidth: 8
diff --git a/.clang-format b/.clang-format
new file mode 120000
index 0000000..ddcf5a2
--- /dev/null
+++ b/.clang-format
@@ -0,0 +1 @@
+../../build/soong/scripts/system-clang-format
\ No newline at end of file
diff --git a/audio/core/all-versions/vts/functional/5.0/AudioPrimaryHidlHalTest.cpp b/audio/core/all-versions/vts/functional/5.0/AudioPrimaryHidlHalTest.cpp
new file mode 100644
index 0000000..bdb17cd
--- /dev/null
+++ b/audio/core/all-versions/vts/functional/5.0/AudioPrimaryHidlHalTest.cpp
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2019 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 <math.h>
+
+// pull in all the <= 4.0 tests
+#include "4.0/AudioPrimaryHidlHalTest.cpp"
+
+TEST_P(InputStreamTest, SetMicrophoneDirection) {
+    doc::test("Make sure setMicrophoneDirection correctly handles valid & invalid arguments");
+
+    // MicrophoneDirection dir = MicrophoneDirection::FRONT;
+    for (MicrophoneDirection dir : android::hardware::hidl_enum_range<MicrophoneDirection>()) {
+        ASSERT_RESULT(okOrNotSupported, stream->setMicrophoneDirection(dir));
+    }
+
+    // Bogus values
+    for (auto dir : {42, -1, 4}) {
+        ASSERT_RESULT(invalidArgsOrNotSupported,
+                      stream->setMicrophoneDirection(MicrophoneDirection(dir)));
+    }
+}
+
+TEST_P(InputStreamTest, SetMicrophoneFieldDimension) {
+    doc::test("Make sure setMicrophoneFieldDimension correctly handles valid & invalid arguments");
+
+    // Valid zoom values -1.0 -> 1.0
+    float incr = 0.1f;
+    for (float val = -1.0f; val <= 1.0; val += incr) {
+        ASSERT_RESULT(okOrNotSupported, stream->setMicrophoneFieldDimension(val));
+    }
+
+    // Bogus values
+    for (float val = 1.0f + incr; val <= 10.0f; val += incr) {
+        ASSERT_RESULT(invalidArgsOrNotSupported, stream->setMicrophoneFieldDimension(val));
+        ASSERT_RESULT(invalidArgsOrNotSupported, stream->setMicrophoneFieldDimension(-val));
+    }
+    // Some extremes
+    ASSERT_RESULT(invalidArgsOrNotSupported, stream->setMicrophoneFieldDimension(NAN));
+    ASSERT_RESULT(invalidArgsOrNotSupported, stream->setMicrophoneFieldDimension(-NAN));
+    ASSERT_RESULT(invalidArgsOrNotSupported, stream->setMicrophoneFieldDimension(INFINITY));
+    ASSERT_RESULT(invalidArgsOrNotSupported, stream->setMicrophoneFieldDimension(-INFINITY));
+}
diff --git a/audio/core/all-versions/vts/functional/Android.bp b/audio/core/all-versions/vts/functional/Android.bp
index 6498289..f434e42 100644
--- a/audio/core/all-versions/vts/functional/Android.bp
+++ b/audio/core/all-versions/vts/functional/Android.bp
@@ -73,8 +73,7 @@
     name: "VtsHalAudioV5_0TargetTest",
     defaults: ["VtsHalAudioTargetTest_defaults"],
     srcs: [
-        // for now the tests are the same as V4
-        "4.0/AudioPrimaryHidlHalTest.cpp",
+        "5.0/AudioPrimaryHidlHalTest.cpp",
     ],
     static_libs: [
         "android.hardware.audio@5.0",
diff --git a/audio/effect/5.0/types.hal b/audio/effect/5.0/types.hal
index 84e1108..4b6c196 100644
--- a/audio/effect/5.0/types.hal
+++ b/audio/effect/5.0/types.hal
@@ -53,6 +53,7 @@
  * | Volume         | 6..8   | 0 none
  * | management     |        | 1 implements volume control
  * |                |        | 2 requires volume indication
+ * |                |        | 3 monitors requested volume
  * |                |        | 4 reserved
  * +----------------+--------+--------------------------------------------------
  * | Device         | 9..11  | 0 none
@@ -136,6 +137,7 @@
     VOLUME_MASK = ((1 << VOLUME_SIZE) -1) << VOLUME_SHIFT,
     VOLUME_CTRL = 1 << VOLUME_SHIFT,
     VOLUME_IND = 2 << VOLUME_SHIFT,
+    VOLUME_MONITOR = 3 << VOLUME_SHIFT,
     VOLUME_NONE = 0 << VOLUME_SHIFT,
 
     // Device indication
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h
index 7614cad..08cdffa 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h
@@ -198,6 +198,15 @@
 
     {.config =
          {
+             .prop = toInt(VehicleProperty::INFO_DRIVER_SEAT),
+             .access = VehiclePropertyAccess::READ,
+             .changeMode = VehiclePropertyChangeMode::STATIC,
+             .areaConfigs = {VehicleAreaConfig{.areaId = (0)}},
+         },
+     .initialValue = {.int32Values = {SEAT_1_LEFT}}},
+
+    {.config =
+         {
              .prop = toInt(VehicleProperty::INFO_FUEL_DOOR_LOCATION),
              .access = VehiclePropertyAccess::READ,
              .changeMode = VehiclePropertyChangeMode::STATIC,
@@ -321,6 +330,8 @@
              .access = VehiclePropertyAccess::READ,
              .changeMode = VehiclePropertyChangeMode::CONTINUOUS,
              .areaConfigs = {VehicleAreaConfig{.areaId = (0)}},
+             .minSampleRate = 1.0f,
+             .maxSampleRate = 2.0f,
          },
      .initialValue = {.floatValues = {100.0f}}},  // units in meters
 
@@ -328,6 +339,8 @@
          {.prop = toInt(VehicleProperty::TIRE_PRESSURE),
           .access = VehiclePropertyAccess::READ,
           .changeMode = VehiclePropertyChangeMode::CONTINUOUS,
+          .minSampleRate = 1.0f,
+          .maxSampleRate = 2.0f,
           .areaConfigs =
               {VehicleAreaConfig{
                    .areaId = WHEEL_FRONT_LEFT, .minFloatValue = 100.0f, .maxFloatValue = 300.0f,
diff --git a/biometrics/face/1.0/types.hal b/biometrics/face/1.0/types.hal
index a488d67..89e809b 100644
--- a/biometrics/face/1.0/types.hal
+++ b/biometrics/face/1.0/types.hal
@@ -281,9 +281,62 @@
     TOO_SIMILAR = 15,
 
     /**
+     * The magnitude of the pan angle of the user’s face with respect to the sensor’s
+     * capture plane is too high.
+     *
+     * The pan angle is defined as the angle swept out by the user’s face turning
+     * their neck left and right. The pan angle would be zero if the user faced the
+     * camera directly.
+     *
+     * The user should be informed to look more directly at the camera.
+     */
+    PAN_TOO_EXTREME = 16,
+
+    /**
+     * The magnitude of the tilt angle of the user’s face with respect to the sensor’s
+     * capture plane is too high.
+     *
+     * The tilt angle is defined as the angle swept out by the user’s face looking up
+     * and down. The pan angle would be zero if the user faced the camera directly.
+     *
+     * The user should be informed to look more directly at the camera.
+     */
+    TILT_TOO_EXTREME = 17,
+
+    /**
+     * The magnitude of the roll angle of the user’s face with respect to the sensor’s
+     * capture plane is too high.
+     *
+     * The roll angle is defined as the angle swept out by the user’s face tilting their head
+     * towards their shoulders to the left and right. The pan angle would be zero if the user
+     * faced the camera directly.
+     *
+     * The user should be informed to look more directly at the camera.
+     */
+    ROLL_TOO_EXTREME = 18,
+
+   /**
+     * The user’s face has been obscured by some object.
+     *
+     * The user should be informed to remove any objects from the line of sight from
+     * the sensor to the user’s face.
+     */
+    FACE_OBSCURED = 19,
+
+    /**
+     * This message represents the earliest message sent at the beginning of the authentication
+     * pipeline. It is expected to be used to measure latency. For example, in a camera-based
+     * authentication system it's expected to be sent prior to camera initialization. Note this
+     * should be sent whenever authentication is restarted (see IBiometricsFace#userActivity).
+     * The framework will measure latency based on the time between the last START message and the
+     * onAuthenticated callback.
+     */
+    START = 20,
+
+    /**
      * Used to enable a vendor-specific acquisition message.
      */
-    VENDOR = 16
+    VENDOR = 21
 };
 
 /**
diff --git a/camera/device/3.2/default/CameraDeviceSession.cpp b/camera/device/3.2/default/CameraDeviceSession.cpp
index fd785df..f2d7a47 100644
--- a/camera/device/3.2/default/CameraDeviceSession.cpp
+++ b/camera/device/3.2/default/CameraDeviceSession.cpp
@@ -44,13 +44,15 @@
 static constexpr int METADATA_SHRINK_REL_THRESHOLD = 2;
 
 HandleImporter CameraDeviceSession::sHandleImporter;
+buffer_handle_t CameraDeviceSession::sEmptyBuffer = nullptr;
+
 const int CameraDeviceSession::ResultBatcher::NOT_BATCHED;
 
 CameraDeviceSession::CameraDeviceSession(
     camera3_device_t* device,
     const camera_metadata_t* deviceInfo,
     const sp<ICameraDeviceCallback>& callback) :
-        camera3_callback_ops({&sProcessCaptureResult, &sNotify}),
+        camera3_callback_ops({&sProcessCaptureResult, &sNotify, nullptr, nullptr}),
         mDevice(device),
         mDeviceVersion(device->common.version),
         mFreeBufEarly(shouldFreeBufEarly()),
@@ -246,10 +248,50 @@
     }
 }
 
+Status CameraDeviceSession::importBuffer(int32_t streamId,
+        uint64_t bufId, buffer_handle_t buf,
+        /*out*/buffer_handle_t** outBufPtr,
+        bool allowEmptyBuf) {
+
+    if (buf == nullptr && bufId == BUFFER_ID_NO_BUFFER) {
+        if (allowEmptyBuf) {
+            *outBufPtr = &sEmptyBuffer;
+            return Status::OK;
+        } else {
+            ALOGE("%s: bufferId %" PRIu64 " has null buffer handle!", __FUNCTION__, bufId);
+            return Status::ILLEGAL_ARGUMENT;
+        }
+    }
+
+    Mutex::Autolock _l(mInflightLock);
+    CirculatingBuffers& cbs = mCirculatingBuffers[streamId];
+    if (cbs.count(bufId) == 0) {
+        // Register a newly seen buffer
+        buffer_handle_t importedBuf = buf;
+        sHandleImporter.importBuffer(importedBuf);
+        if (importedBuf == nullptr) {
+            ALOGE("%s: output buffer for stream %d is invalid!", __FUNCTION__, streamId);
+            return Status::INTERNAL_ERROR;
+        } else {
+            cbs[bufId] = importedBuf;
+        }
+    }
+    *outBufPtr = &cbs[bufId];
+    return Status::OK;
+}
+
 Status CameraDeviceSession::importRequest(
         const CaptureRequest& request,
         hidl_vec<buffer_handle_t*>& allBufPtrs,
         hidl_vec<int>& allFences) {
+    return importRequestImpl(request, allBufPtrs, allFences);
+}
+
+Status CameraDeviceSession::importRequestImpl(
+        const CaptureRequest& request,
+        hidl_vec<buffer_handle_t*>& allBufPtrs,
+        hidl_vec<int>& allFences,
+        bool allowEmptyBuf) {
     bool hasInputBuf = (request.inputBuffer.streamId != -1 &&
             request.inputBuffer.bufferId != 0);
     size_t numOutputBufs = request.outputBuffers.size();
@@ -277,25 +319,15 @@
     }
 
     for (size_t i = 0; i < numBufs; i++) {
-        buffer_handle_t buf = allBufs[i];
-        uint64_t bufId = allBufIds[i];
-        CirculatingBuffers& cbs = mCirculatingBuffers[streamIds[i]];
-        if (cbs.count(bufId) == 0) {
-            if (buf == nullptr) {
-                ALOGE("%s: bufferId %" PRIu64 " has null buffer handle!", __FUNCTION__, bufId);
-                return Status::ILLEGAL_ARGUMENT;
-            }
-            // Register a newly seen buffer
-            buffer_handle_t importedBuf = buf;
-            sHandleImporter.importBuffer(importedBuf);
-            if (importedBuf == nullptr) {
-                ALOGE("%s: output buffer %zu is invalid!", __FUNCTION__, i);
-                return Status::INTERNAL_ERROR;
-            } else {
-                cbs[bufId] = importedBuf;
-            }
+        Status st = importBuffer(
+                streamIds[i], allBufIds[i], allBufs[i], &allBufPtrs[i],
+                // Disallow empty buf for input stream, otherwise follow
+                // the allowEmptyBuf argument.
+                (hasInputBuf && i == numOutputBufs) ? false : allowEmptyBuf);
+        if (st != Status::OK) {
+            // Detailed error logs printed in importBuffer
+            return st;
         }
-        allBufPtrs[i] = &cbs[bufId];
     }
 
     // All buffers are imported. Now validate output buffer acquire fences
@@ -1271,18 +1303,26 @@
         ATRACE_END();
 
         // free all imported buffers
+        Mutex::Autolock _l(mInflightLock);
         for(auto& pair : mCirculatingBuffers) {
             CirculatingBuffers& buffers = pair.second;
             for (auto& p2 : buffers) {
                 sHandleImporter.freeBuffer(p2.second);
             }
+            buffers.clear();
         }
+        mCirculatingBuffers.clear();
 
         mClosed = true;
     }
     return Void();
 }
 
+uint64_t CameraDeviceSession::getCapResultBufferId(const buffer_handle_t&, int) {
+    // No need to fill in bufferId by default
+    return BUFFER_ID_NO_BUFFER;
+}
+
 status_t CameraDeviceSession::constructCaptureResult(CaptureResult& result,
                                                  const camera3_capture_result *hal_result) {
     uint32_t frameNumber = hal_result->frame_number;
@@ -1396,6 +1436,14 @@
         result.outputBuffers[i].streamId =
                 static_cast<Camera3Stream*>(hal_result->output_buffers[i].stream)->mId;
         result.outputBuffers[i].buffer = nullptr;
+        if (hal_result->output_buffers[i].buffer != nullptr) {
+            result.outputBuffers[i].bufferId = getCapResultBufferId(
+                    *(hal_result->output_buffers[i].buffer),
+                    result.outputBuffers[i].streamId);
+        } else {
+            result.outputBuffers[i].bufferId = 0;
+        }
+
         result.outputBuffers[i].status = (BufferStatus) hal_result->output_buffers[i].status;
         // skip acquire fence since it's of no use to camera service
         if (hal_result->output_buffers[i].release_fence != -1) {
diff --git a/camera/device/3.2/default/CameraDeviceSession.h b/camera/device/3.2/default/CameraDeviceSession.h
index bcee259..a96c245 100644
--- a/camera/device/3.2/default/CameraDeviceSession.h
+++ b/camera/device/3.2/default/CameraDeviceSession.h
@@ -161,6 +161,7 @@
     std::map<uint32_t, bool> mInflightRawBoostPresent;
     ::android::hardware::camera::common::V1_0::helper::CameraMetadata mOverridenRequest;
 
+    static const uint64_t BUFFER_ID_NO_BUFFER = 0;
     // buffers currently ciculating between HAL and camera service
     // key: bufferId sent via HIDL interface
     // value: imported buffer_handle_t
@@ -171,6 +172,7 @@
     std::map<int, CirculatingBuffers> mCirculatingBuffers;
 
     static HandleImporter sHandleImporter;
+    static buffer_handle_t sEmptyBuffer;
 
     bool mInitFail;
     bool mFirstRequest = false;
@@ -301,11 +303,23 @@
     Status initStatus() const;
 
     // Validate and import request's input buffer and acquire fence
-    Status importRequest(
+    virtual Status importRequest(
             const CaptureRequest& request,
             hidl_vec<buffer_handle_t*>& allBufPtrs,
             hidl_vec<int>& allFences);
 
+    Status importRequestImpl(
+            const CaptureRequest& request,
+            hidl_vec<buffer_handle_t*>& allBufPtrs,
+            hidl_vec<int>& allFences,
+            // Optional argument for ICameraDeviceSession@3.5 impl
+            bool allowEmptyBuf = false);
+
+    Status importBuffer(int32_t streamId,
+            uint64_t bufId, buffer_handle_t buf,
+            /*out*/buffer_handle_t** outBufPtr,
+            bool allowEmptyBuf);
+
     static void cleanupInflightFences(
             hidl_vec<int>& allFences, size_t numFences);
 
@@ -332,6 +346,11 @@
     static callbacks_process_capture_result_t sProcessCaptureResult;
     static callbacks_notify_t sNotify;
 
+    // By default camera service uses frameNumber/streamId pair to retrieve the buffer that
+    // was sent to HAL. Override this implementation if HAL is using buffers from buffer management
+    // APIs to send output buffer.
+    virtual uint64_t getCapResultBufferId(const buffer_handle_t& buf, int streamId);
+
     status_t constructCaptureResult(CaptureResult& result,
                                 const camera3_capture_result *hal_result);
 
diff --git a/camera/device/3.4/default/CameraDeviceSession.cpp b/camera/device/3.4/default/CameraDeviceSession.cpp
index f2e031c..e52577c 100644
--- a/camera/device/3.4/default/CameraDeviceSession.cpp
+++ b/camera/device/3.4/default/CameraDeviceSession.cpp
@@ -87,6 +87,14 @@
 Return<void> CameraDeviceSession::configureStreams_3_4(
         const StreamConfiguration& requestedConfiguration,
         ICameraDeviceSession::configureStreams_3_4_cb _hidl_cb)  {
+    configureStreams_3_4_Impl(requestedConfiguration, _hidl_cb);
+    return Void();
+}
+
+void CameraDeviceSession::configureStreams_3_4_Impl(
+        const StreamConfiguration& requestedConfiguration,
+        ICameraDeviceSession::configureStreams_3_4_cb _hidl_cb,
+        uint32_t streamConfigCounter)  {
     Status status = initStatus();
     HalStreamConfiguration outStreams;
 
@@ -97,7 +105,7 @@
                 ALOGE("%s: trying to configureStreams with physical camera id with V3.2 callback",
                         __FUNCTION__);
                 _hidl_cb(Status::INTERNAL_ERROR, outStreams);
-                return Void();
+                return;
             }
         }
     }
@@ -109,7 +117,7 @@
         ALOGE("%s: trying to configureStreams while there are still %zu inflight buffers!",
                 __FUNCTION__, mInflightBuffers.size());
         _hidl_cb(Status::INTERNAL_ERROR, outStreams);
-        return Void();
+        return;
     }
 
     if (!mInflightAETriggerOverrides.empty()) {
@@ -117,7 +125,7 @@
                 " trigger overrides!", __FUNCTION__,
                 mInflightAETriggerOverrides.size());
         _hidl_cb(Status::INTERNAL_ERROR, outStreams);
-        return Void();
+        return;
     }
 
     if (!mInflightRawBoostPresent.empty()) {
@@ -125,12 +133,12 @@
                 " boost overrides!", __FUNCTION__,
                 mInflightRawBoostPresent.size());
         _hidl_cb(Status::INTERNAL_ERROR, outStreams);
-        return Void();
+        return;
     }
 
     if (status != Status::OK) {
         _hidl_cb(status, outStreams);
-        return Void();
+        return;
     }
 
     const camera_metadata_t *paramBuffer = nullptr;
@@ -139,11 +147,12 @@
     }
 
     camera3_stream_configuration_t stream_list{};
+    stream_list.stream_configuration_counter = streamConfigCounter;
     hidl_vec<camera3_stream_t*> streams;
     stream_list.session_parameters = paramBuffer;
     if (!preProcessConfigurationLocked_3_4(requestedConfiguration, &stream_list, &streams)) {
         _hidl_cb(Status::INTERNAL_ERROR, outStreams);
-        return Void();
+        return;
     }
 
     ATRACE_BEGIN("camera3->configure_streams");
@@ -168,7 +177,7 @@
     }
 
     _hidl_cb(status, outStreams);
-    return Void();
+    return;
 }
 
 bool CameraDeviceSession::preProcessConfigurationLocked_3_4(
diff --git a/camera/device/3.4/default/include/device_v3_4_impl/CameraDeviceSession.h b/camera/device/3.4/default/include/device_v3_4_impl/CameraDeviceSession.h
index fdc8a5a..00500b1 100644
--- a/camera/device/3.4/default/include/device_v3_4_impl/CameraDeviceSession.h
+++ b/camera/device/3.4/default/include/device_v3_4_impl/CameraDeviceSession.h
@@ -87,6 +87,12 @@
     void postProcessConfigurationFailureLocked_3_4(
             const StreamConfiguration& requestedConfiguration);
 
+    void configureStreams_3_4_Impl(
+            const StreamConfiguration& requestedConfiguration,
+            ICameraDeviceSession::configureStreams_3_4_cb _hidl_cb,
+            // Optional argument for ICameraDeviceSession@3.5 impl
+            uint32_t streamConfigCounter = 0);
+
     Return<void> processCaptureRequest_3_4(
             const hidl_vec<V3_4::CaptureRequest>& requests,
             const hidl_vec<V3_2::BufferCache>& cachesToRemove,
diff --git a/camera/device/3.5/default/CameraDeviceSession.cpp b/camera/device/3.5/default/CameraDeviceSession.cpp
index 963893a..0770f04 100644
--- a/camera/device/3.5/default/CameraDeviceSession.cpp
+++ b/camera/device/3.5/default/CameraDeviceSession.cpp
@@ -15,8 +15,10 @@
  */
 
 #define LOG_TAG "CamDevSession@3.5-impl"
+#define ATRACE_TAG ATRACE_TAG_CAMERA
 #include <android/log.h>
 
+#include <vector>
 #include <utils/Trace.h>
 #include "CameraDeviceSession.h"
 
@@ -33,13 +35,26 @@
     const sp<V3_2::ICameraDeviceCallback>& callback) :
         V3_4::implementation::CameraDeviceSession(device, deviceInfo, callback) {
 
-    mHasCallback_3_5 = false;
+    mCallback_3_5 = nullptr;
 
     auto castResult = ICameraDeviceCallback::castFrom(callback);
     if (castResult.isOk()) {
         sp<ICameraDeviceCallback> callback3_5 = castResult;
         if (callback3_5 != nullptr) {
-            mHasCallback_3_5 = true;
+            mCallback_3_5 = callback3_5;
+        }
+    }
+
+    if (mCallback_3_5 != nullptr) {
+        camera_metadata_entry bufMgrVersion = mDeviceInfo.find(
+                ANDROID_INFO_SUPPORTED_BUFFER_MANAGEMENT_VERSION);
+        if (bufMgrVersion.count > 0) {
+            mSupportBufMgr = (bufMgrVersion.data.u8[0] ==
+                    ANDROID_INFO_SUPPORTED_BUFFER_MANAGEMENT_VERSION_HIDL_DEVICE_3_5);
+            if (mSupportBufMgr) {
+                request_stream_buffers = sRequestStreamBuffers;
+                return_stream_buffers = sReturnStreamBuffers;
+            }
         }
     }
 }
@@ -50,14 +65,297 @@
 Return<void> CameraDeviceSession::configureStreams_3_5(
         const StreamConfiguration& requestedConfiguration,
         ICameraDeviceSession::configureStreams_3_5_cb _hidl_cb)  {
-    return configureStreams_3_4(requestedConfiguration.v3_4, _hidl_cb);
+    configureStreams_3_4_Impl(requestedConfiguration.v3_4, _hidl_cb,
+            requestedConfiguration.streamConfigCounter);
+    return Void();
 }
 
 Return<void> CameraDeviceSession::signalStreamFlush(
-        const hidl_vec<int32_t>& /*requests*/, uint32_t /*streamConfigCounter*/) {
+        const hidl_vec<int32_t>& streamIds, uint32_t streamConfigCounter) {
+    std::vector<camera3_stream_t*> streams(streamIds.size());
+    {
+        Mutex::Autolock _l(mInflightLock);
+        for (size_t i = 0; i < streamIds.size(); i++) {
+            int32_t id = streamIds[i];
+            if (mStreamMap.count(id) == 0) {
+                ALOGE("%s: unknown streamId %d", __FUNCTION__, id);
+                return Void();
+            }
+            streams[i] = &mStreamMap[id];
+        }
+    }
+    if (mDevice->ops->signal_stream_flush != nullptr) {
+        mDevice->ops->signal_stream_flush(mDevice,
+                streamConfigCounter, streams.size(), streams.data());
+    }
     return Void();
 }
 
+Status CameraDeviceSession::importRequest(
+        const CaptureRequest& request,
+        hidl_vec<buffer_handle_t*>& allBufPtrs,
+        hidl_vec<int>& allFences) {
+    if (mSupportBufMgr) {
+        return importRequestImpl(request, allBufPtrs, allFences, /*allowEmptyBuf*/ true);
+    }
+    return importRequestImpl(request, allBufPtrs, allFences, /*allowEmptyBuf*/ false);
+}
+
+void CameraDeviceSession::pushBufferId(
+        const buffer_handle_t& buf, uint64_t bufferId, int streamId) {
+    std::lock_guard<std::mutex> lock(mBufferIdMapLock);
+
+    // emplace will return existing entry if there is one.
+    auto pair = mBufferIdMaps.emplace(streamId, BufferIdMap{});
+    BufferIdMap& bIdMap = pair.first->second;
+    bIdMap[buf] = bufferId;
+}
+
+uint64_t CameraDeviceSession::popBufferId(
+        const buffer_handle_t& buf, int streamId) {
+    std::lock_guard<std::mutex> lock(mBufferIdMapLock);
+
+    auto streamIt = mBufferIdMaps.find(streamId);
+    if (streamIt == mBufferIdMaps.end()) {
+        return BUFFER_ID_NO_BUFFER;
+    }
+    BufferIdMap& bIdMap = streamIt->second;
+    auto it = bIdMap.find(buf);
+    if (it == bIdMap.end()) {
+        return BUFFER_ID_NO_BUFFER;
+    }
+    uint64_t bufId = it->second;
+    bIdMap.erase(it);
+    if (bIdMap.empty()) {
+        mBufferIdMaps.erase(streamIt);
+    }
+    return bufId;
+}
+
+uint64_t CameraDeviceSession::getCapResultBufferId(const buffer_handle_t& buf, int streamId) {
+    if (mSupportBufMgr) {
+        return popBufferId(buf, streamId);
+    }
+    return BUFFER_ID_NO_BUFFER;
+}
+
+Camera3Stream* CameraDeviceSession::getStreamPointer(int32_t streamId) {
+    Mutex::Autolock _l(mInflightLock);
+    if (mStreamMap.count(streamId) == 0) {
+        ALOGE("%s: unknown streamId %d", __FUNCTION__, streamId);
+        return nullptr;
+    }
+    return &mStreamMap[streamId];
+}
+
+void CameraDeviceSession::cleanupInflightBufferFences(
+        std::vector<int>& fences, std::vector<std::pair<buffer_handle_t, int>>& bufs) {
+    hidl_vec<int> hFences = fences;
+    cleanupInflightFences(hFences, fences.size());
+    for (auto& p : bufs) {
+        popBufferId(p.first, p.second);
+    }
+}
+
+camera3_buffer_request_status_t CameraDeviceSession::requestStreamBuffers(
+        uint32_t num_buffer_reqs,
+        const camera3_buffer_request_t *buffer_reqs,
+        /*out*/uint32_t *num_returned_buf_reqs,
+        /*out*/camera3_stream_buffer_ret_t *returned_buf_reqs) {
+    ATRACE_CALL();
+    *num_returned_buf_reqs = 0;
+    hidl_vec<BufferRequest> hBufReqs(num_buffer_reqs);
+    for (size_t i = 0; i < num_buffer_reqs; i++) {
+        hBufReqs[i].streamId =
+                static_cast<Camera3Stream*>(buffer_reqs[i].stream)->mId;
+        hBufReqs[i].numBuffersRequested = buffer_reqs[i].num_buffers_requested;
+    }
+
+    ATRACE_BEGIN("HIDL requestStreamBuffers");
+    BufferRequestStatus status;
+    hidl_vec<StreamBufferRet> bufRets;
+    auto err = mCallback_3_5->requestStreamBuffers(hBufReqs,
+            [&status, &bufRets]
+            (BufferRequestStatus s, const hidl_vec<StreamBufferRet>& rets) {
+                status = s;
+                bufRets = std::move(rets);
+            });
+    if (!err.isOk()) {
+        ALOGE("%s: Transaction error: %s", __FUNCTION__, err.description().c_str());
+        return CAMERA3_BUF_REQ_FAILED_UNKNOWN;
+    }
+    ATRACE_END();
+
+    if (status == BufferRequestStatus::OK || status == BufferRequestStatus::FAILED_PARTIAL) {
+        if (bufRets.size() != num_buffer_reqs) {
+            ALOGE("%s: expect %d buffer requests returned, only got %zu",
+                    __FUNCTION__, num_buffer_reqs, bufRets.size());
+            return CAMERA3_BUF_REQ_FAILED_UNKNOWN;
+        }
+
+        for (size_t i = 0; i < num_buffer_reqs; i++) {
+            // maybe we can query all streams in one call to avoid frequent locking device here?
+            Camera3Stream* stream = getStreamPointer(bufRets[i].streamId);
+            if (stream == nullptr) {
+                ALOGE("%s: unknown streamId %d", __FUNCTION__, bufRets[i].streamId);
+                return CAMERA3_BUF_REQ_FAILED_UNKNOWN;
+            }
+            returned_buf_reqs[i].stream = stream;
+        }
+
+        std::vector<int> importedFences;
+        std::vector<std::pair<buffer_handle_t, int>> importedBuffers;
+        for (size_t i = 0; i < num_buffer_reqs; i++) {
+            int streamId = bufRets[i].streamId;
+            switch (bufRets[i].val.getDiscriminator()) {
+                case StreamBuffersVal::hidl_discriminator::error:
+                    returned_buf_reqs[i].num_output_buffers = 0;
+                    switch (bufRets[i].val.error()) {
+                        case StreamBufferRequestError::NO_BUFFER_AVAILABLE:
+                            returned_buf_reqs[i].status = CAMERA3_PS_BUF_REQ_NO_BUFFER_AVAILABLE;
+                            break;
+                        case StreamBufferRequestError::MAX_BUFFER_EXCEEDED:
+                            returned_buf_reqs[i].status = CAMERA3_PS_BUF_REQ_MAX_BUFFER_EXCEEDED;
+                            break;
+                        case StreamBufferRequestError::STREAM_DISCONNECTED:
+                            returned_buf_reqs[i].status = CAMERA3_PS_BUF_REQ_STREAM_DISCONNECTED;
+                            break;
+                        case StreamBufferRequestError::UNKNOWN_ERROR:
+                            returned_buf_reqs[i].status = CAMERA3_PS_BUF_REQ_UNKNOWN_ERROR;
+                            break;
+                        default:
+                            ALOGE("%s: Unknown StreamBufferRequestError %d",
+                                    __FUNCTION__, bufRets[i].val.error());
+                            cleanupInflightBufferFences(importedFences, importedBuffers);
+                            return CAMERA3_BUF_REQ_FAILED_UNKNOWN;
+                    }
+                    break;
+                case StreamBuffersVal::hidl_discriminator::buffers: {
+                    const hidl_vec<StreamBuffer>& hBufs = bufRets[i].val.buffers();
+                    camera3_stream_buffer_t* outBufs = returned_buf_reqs[i].output_buffers;
+                    for (size_t b = 0; b < hBufs.size(); b++) {
+                        const StreamBuffer& hBuf = hBufs[b];
+                        camera3_stream_buffer_t& outBuf = outBufs[b];
+                        // maybe add importBuffers API to avoid frequent locking device?
+                        Status s = importBuffer(streamId,
+                                hBuf.bufferId, hBuf.buffer.getNativeHandle(),
+                                /*out*/&(outBuf.buffer),
+                                /*allowEmptyBuf*/false);
+                        if (s != Status::OK) {
+                            ALOGE("%s: import stream %d bufferId %" PRIu64 " failed!",
+                                    __FUNCTION__, streamId, hBuf.bufferId);
+                            cleanupInflightBufferFences(importedFences, importedBuffers);
+                            // Buffer import should never fail - restart HAL since something is very
+                            // wrong.
+                            assert(false);
+                            return CAMERA3_BUF_REQ_FAILED_UNKNOWN;
+                        }
+
+                        pushBufferId(*(outBuf.buffer), hBuf.bufferId, streamId);
+                        importedBuffers.push_back(std::make_pair(*(outBuf.buffer), streamId));
+
+                        if (!sHandleImporter.importFence(
+                                hBuf.acquireFence,
+                                outBuf.acquire_fence)) {
+                            ALOGE("%s: stream %d bufferId %" PRIu64 "acquire fence is invalid",
+                                    __FUNCTION__, streamId, hBuf.bufferId);
+                            cleanupInflightBufferFences(importedFences, importedBuffers);
+                            return CAMERA3_BUF_REQ_FAILED_UNKNOWN;
+                        }
+                        importedFences.push_back(outBuf.acquire_fence);
+                        outBuf.stream = returned_buf_reqs[i].stream;
+                        outBuf.status = CAMERA3_BUFFER_STATUS_OK;
+                        outBuf.release_fence = -1;
+                    }
+                    returned_buf_reqs[i].status = CAMERA3_PS_BUF_REQ_OK;
+                } break;
+                default:
+                    ALOGE("%s: unknown StreamBuffersVal discrimator!", __FUNCTION__);
+                    cleanupInflightBufferFences(importedFences, importedBuffers);
+                    return CAMERA3_BUF_REQ_FAILED_UNKNOWN;
+            }
+        }
+
+        *num_returned_buf_reqs = num_buffer_reqs;
+
+        return (status == BufferRequestStatus::OK) ?
+                CAMERA3_BUF_REQ_OK : CAMERA3_BUF_REQ_FAILED_PARTIAL;
+    }
+
+    switch (status) {
+        case BufferRequestStatus::FAILED_CONFIGURING:
+            return CAMERA3_BUF_REQ_FAILED_CONFIGURING;
+        case BufferRequestStatus::FAILED_ILLEGAL_ARGUMENTS:
+            return CAMERA3_BUF_REQ_FAILED_ILLEGAL_ARGUMENTS;
+        case BufferRequestStatus::FAILED_UNKNOWN:
+        default:
+            return CAMERA3_BUF_REQ_FAILED_UNKNOWN;
+    }
+}
+
+void CameraDeviceSession::returnStreamBuffers(
+        uint32_t num_buffers,
+        const camera3_stream_buffer_t* const* buffers) {
+    ATRACE_CALL();
+    hidl_vec<StreamBuffer> hBufs(num_buffers);
+
+    for (size_t i = 0; i < num_buffers; i++) {
+        hBufs[i].streamId =
+                static_cast<Camera3Stream*>(buffers[i]->stream)->mId;
+        hBufs[i].buffer = nullptr; // use bufferId
+        hBufs[i].bufferId = popBufferId(*(buffers[i]->buffer), hBufs[i].streamId);
+        if (hBufs[i].bufferId == BUFFER_ID_NO_BUFFER) {
+            ALOGE("%s: unknown buffer is returned to stream %d",
+                    __FUNCTION__, hBufs[i].streamId);
+        }
+        // ERROR since the buffer is not for application to consume
+        hBufs[i].status = BufferStatus::ERROR;
+        // skip acquire fence since it's of no use to camera service
+        if (buffers[i]->release_fence != -1) {
+            native_handle_t* handle = native_handle_create(/*numFds*/1, /*numInts*/0);
+            handle->data[0] = buffers[i]->release_fence;
+            hBufs[i].releaseFence.setTo(handle, /*shouldOwn*/true);
+        }
+    }
+
+    mCallback_3_5->returnStreamBuffers(hBufs);
+    return;
+}
+
+/**
+ * Static callback forwarding methods from HAL to instance
+ */
+camera3_buffer_request_status_t CameraDeviceSession::sRequestStreamBuffers(
+        const struct camera3_callback_ops *cb,
+        uint32_t num_buffer_reqs,
+        const camera3_buffer_request_t *buffer_reqs,
+        /*out*/uint32_t *num_returned_buf_reqs,
+        /*out*/camera3_stream_buffer_ret_t *returned_buf_reqs) {
+    CameraDeviceSession *d =
+            const_cast<CameraDeviceSession*>(static_cast<const CameraDeviceSession*>(cb));
+
+    if (num_buffer_reqs == 0 || buffer_reqs == nullptr || num_returned_buf_reqs == nullptr ||
+            returned_buf_reqs == nullptr) {
+        ALOGE("%s: bad argument: numBufReq %d, bufReqs %p, numRetBufReq %p, retBufReqs %p",
+                __FUNCTION__, num_buffer_reqs, buffer_reqs,
+                num_returned_buf_reqs, returned_buf_reqs);
+        return CAMERA3_BUF_REQ_FAILED_ILLEGAL_ARGUMENTS;
+    }
+
+    return d->requestStreamBuffers(num_buffer_reqs, buffer_reqs,
+            num_returned_buf_reqs, returned_buf_reqs);
+}
+
+void CameraDeviceSession::sReturnStreamBuffers(
+        const struct camera3_callback_ops *cb,
+        uint32_t num_buffers,
+        const camera3_stream_buffer_t* const* buffers) {
+    CameraDeviceSession *d =
+            const_cast<CameraDeviceSession*>(static_cast<const CameraDeviceSession*>(cb));
+
+    d->returnStreamBuffers(num_buffers, buffers);
+}
+
 } // namespace implementation
 }  // namespace V3_5
 }  // namespace device
diff --git a/camera/device/3.5/default/include/device_v3_5_impl/CameraDeviceSession.h b/camera/device/3.5/default/include/device_v3_5_impl/CameraDeviceSession.h
index ec34769..4f7284c 100644
--- a/camera/device/3.5/default/include/device_v3_5_impl/CameraDeviceSession.h
+++ b/camera/device/3.5/default/include/device_v3_5_impl/CameraDeviceSession.h
@@ -21,6 +21,7 @@
 #include <android/hardware/camera/device/3.5/ICameraDeviceSession.h>
 #include <android/hardware/camera/device/3.5/ICameraDeviceCallback.h>
 #include <../../3.4/default/include/device_v3_4_impl/CameraDeviceSession.h>
+#include <unordered_map>
 
 namespace android {
 namespace hardware {
@@ -30,11 +31,14 @@
 namespace implementation {
 
 using namespace ::android::hardware::camera::device;
+using ::android::hardware::camera::device::V3_2::BufferStatus;
 using ::android::hardware::camera::device::V3_2::CaptureRequest;
+using ::android::hardware::camera::device::V3_2::StreamBuffer;
 using ::android::hardware::camera::device::V3_5::StreamConfiguration;
 using ::android::hardware::camera::device::V3_4::HalStreamConfiguration;
 using ::android::hardware::camera::device::V3_5::ICameraDeviceSession;
 using ::android::hardware::camera::device::V3_5::ICameraDeviceCallback;
+using ::android::hardware::camera::device::V3_2::implementation::Camera3Stream;
 using ::android::hardware::camera::common::V1_0::Status;
 using ::android::hardware::camera::common::V1_0::helper::HandleImporter;
 using ::android::hardware::Return;
@@ -44,6 +48,25 @@
 using ::android::sp;
 using ::android::Mutex;
 
+
+/**
+ * Function pointer types with C calling convention to
+ * use for HAL callback functions.
+ */
+extern "C" {
+    typedef camera3_buffer_request_status_t (callbacks_request_stream_buffer_t)(
+            const struct camera3_callback_ops *,
+            uint32_t num_buffer_reqs,
+            const camera3_buffer_request_t *buffer_reqs,
+            /*out*/uint32_t *num_returned_buf_reqs,
+            /*out*/camera3_stream_buffer_ret_t *returned_buf_reqs);
+
+    typedef void (callbacks_return_stream_buffer_t)(
+            const struct camera3_callback_ops *,
+            uint32_t num_buffers,
+            const camera3_stream_buffer_t* const* buffers);
+}
+
 struct CameraDeviceSession : public V3_4::implementation::CameraDeviceSession {
 
     CameraDeviceSession(camera3_device_t*,
@@ -62,12 +85,85 @@
             ICameraDeviceSession::configureStreams_3_5_cb _hidl_cb);
 
     Return<void> signalStreamFlush(
-            const hidl_vec<int32_t>& requests,
+            const hidl_vec<int32_t>& streamIds,
             uint32_t streamConfigCounter);
 
+    virtual Status importRequest(
+            const CaptureRequest& request,
+            hidl_vec<buffer_handle_t*>& allBufPtrs,
+            hidl_vec<int>& allFences) override;
 
-    // Whether this camera device session is created with version 3.5 callback.
-    bool mHasCallback_3_5;
+    /**
+     * Static callback forwarding methods from HAL to instance
+     */
+    static callbacks_request_stream_buffer_t sRequestStreamBuffers;
+    static callbacks_return_stream_buffer_t sReturnStreamBuffers;
+
+    camera3_buffer_request_status_t requestStreamBuffers(
+            uint32_t num_buffer_reqs,
+            const camera3_buffer_request_t *buffer_reqs,
+            /*out*/uint32_t *num_returned_buf_reqs,
+            /*out*/camera3_stream_buffer_ret_t *returned_buf_reqs);
+
+    void returnStreamBuffers(
+            uint32_t num_buffers,
+            const camera3_stream_buffer_t* const* buffers);
+
+    struct BufferHasher {
+        size_t operator()(const buffer_handle_t& buf) const {
+            if (buf == nullptr)
+                return 0;
+
+            size_t result = 1;
+            result = 31 * result + buf->numFds;
+            for (int i = 0; i < buf->numFds; i++) {
+                result = 31 * result + buf->data[i];
+            }
+            return result;
+        }
+    };
+
+    struct BufferComparator {
+        bool operator()(const buffer_handle_t& buf1, const buffer_handle_t& buf2) const {
+            if (buf1->numFds == buf2->numFds) {
+                for (int i = 0; i < buf1->numFds; i++) {
+                    if (buf1->data[i] != buf2->data[i]) {
+                        return false;
+                    }
+                }
+                return true;
+            }
+            return false;
+        }
+    };
+
+    Camera3Stream* getStreamPointer(int32_t streamId);
+
+    // Register buffer to mBufferIdMaps so we can find corresponding bufferId
+    // when the buffer is returned to camera service
+    void pushBufferId(const buffer_handle_t& buf, uint64_t bufferId, int streamId);
+
+    // Method to pop buffer's bufferId from mBufferIdMaps
+    // BUFFER_ID_NO_BUFFER is returned if no matching buffer is found
+    uint64_t popBufferId(const buffer_handle_t& buf, int streamId);
+
+    // Method to cleanup imported buffer/fences if requestStreamBuffers fails half way
+    void cleanupInflightBufferFences(
+            std::vector<int>& fences, std::vector<std::pair<buffer_handle_t, int>>& bufs);
+
+    // Overrides the default constructCaptureResult behavior for buffer management APIs
+    virtual uint64_t getCapResultBufferId(const buffer_handle_t& buf, int streamId) override;
+
+    std::mutex mBufferIdMapLock; // protecting mBufferIdMaps and mNextBufferId
+    typedef std::unordered_map<const buffer_handle_t, uint64_t,
+            BufferHasher, BufferComparator> BufferIdMap;
+    // stream ID -> per stream buffer ID map for buffers coming from requestStreamBuffers API
+    // Entries are created during requestStreamBuffers when a stream first request a buffer, and
+    // deleted in returnStreamBuffers/processCaptureResult* when all buffers are returned
+    std::unordered_map<int, BufferIdMap> mBufferIdMaps;
+
+    sp<ICameraDeviceCallback> mCallback_3_5;
+    bool mSupportBufMgr;
 
 private:
 
diff --git a/camera/metadata/3.4/types.hal b/camera/metadata/3.4/types.hal
index 28c56c8..9bbc90d 100644
--- a/camera/metadata/3.4/types.hal
+++ b/camera/metadata/3.4/types.hal
@@ -73,6 +73,28 @@
      */
     ANDROID_DEPTH_AVAILABLE_RECOMMENDED_DEPTH_STREAM_CONFIGURATIONS = android.hardware.camera.metadata@3.2::CameraMetadataTag:ANDROID_DEPTH_END,
 
+    /** android.depth.availableDynamicDepthStreamConfigurations [static, enum[], ndk_public]
+     *
+     * <p>The available dynamic depth dataspace stream
+     * configurations that this camera device supports
+     * (i.e. format, width, height, output/input stream).</p>
+     */
+    ANDROID_DEPTH_AVAILABLE_DYNAMIC_DEPTH_STREAM_CONFIGURATIONS,
+
+    /** android.depth.availableDynamicDepthMinFrameDurations [static, int64[], ndk_public]
+     *
+     * <p>This lists the minimum frame duration for each
+     * format/size combination for dynamic depth output streams.</p>
+     */
+    ANDROID_DEPTH_AVAILABLE_DYNAMIC_DEPTH_MIN_FRAME_DURATIONS,
+
+    /** android.depth.availableDynamicDepthStallDurations [static, int64[], ndk_public]
+     *
+     * <p>This lists the maximum stall duration for each
+     * output format/size combination for dynamic depth streams.</p>
+     */
+    ANDROID_DEPTH_AVAILABLE_DYNAMIC_DEPTH_STALL_DURATIONS,
+
     ANDROID_DEPTH_END_3_4,
 
     /** android.logicalMultiCamera.activePhysicalId [dynamic, byte, public]
@@ -136,3 +158,11 @@
 enum CameraMetadataEnumAndroidInfoSupportedBufferManagementVersion : uint32_t {
     ANDROID_INFO_SUPPORTED_BUFFER_MANAGEMENT_VERSION_HIDL_DEVICE_3_5,
 };
+
+/** android.depth.availableDynamicDepthStreamConfigurations enumeration values
+ * @see ANDROID_DEPTH_AVAILABLE_DYNAMIC_DEPTH_STREAM_CONFIGURATIONS
+ */
+enum CameraMetadataEnumAndroidDepthAvailableDynamicDepthStreamConfigurations : uint32_t {
+    ANDROID_DEPTH_AVAILABLE_DYNAMIC_DEPTH_STREAM_CONFIGURATIONS_OUTPUT,
+    ANDROID_DEPTH_AVAILABLE_DYNAMIC_DEPTH_STREAM_CONFIGURATIONS_INPUT,
+};
diff --git a/camera/provider/2.4/default/CameraProvider.cpp b/camera/provider/2.4/default/CameraProvider.cpp
index 488b9af..e02cc7e 100644
--- a/camera/provider/2.4/default/CameraProvider.cpp
+++ b/camera/provider/2.4/default/CameraProvider.cpp
@@ -41,11 +41,8 @@
 const char *kExternalProviderName = "external/0";
 // "device@<version>/legacy/<id>"
 const std::regex kDeviceNameRE("device@([0-9]+\\.[0-9]+)/legacy/(.+)");
-const char *kHAL3_2 = "3.2";
-const char *kHAL3_3 = "3.3";
 const char *kHAL3_4 = "3.4";
 const char *kHAL3_5 = "3.5";
-const char *kHAL1_0 = "1.0";
 const int kMaxCameraDeviceNameLen = 128;
 const int kMaxCameraIdLen = 16;
 
@@ -143,7 +140,6 @@
         int new_status) {
     CameraProvider* cp = const_cast<CameraProvider*>(
             static_cast<const CameraProvider*>(callbacks));
-    bool found = false;
 
     if (cp == nullptr) {
         ALOGE("%s: callback ops is null", __FUNCTION__);
@@ -155,17 +151,23 @@
     snprintf(cameraId, sizeof(cameraId), "%d", camera_id);
     std::string cameraIdStr(cameraId);
     cp->mCameraStatusMap[cameraIdStr] = (camera_device_status_t) new_status;
-    if (cp->mCallbacks != nullptr) {
-        CameraDeviceStatus status = (CameraDeviceStatus) new_status;
-        for (auto const& deviceNamePair : cp->mCameraDeviceNames) {
-            if (cameraIdStr.compare(deviceNamePair.first) == 0) {
-                cp->mCallbacks->cameraDeviceStatusChange(
-                        deviceNamePair.second, status);
-                found = true;
-            }
-        }
 
-        switch (status) {
+    if (cp->mCallbacks == nullptr) {
+        // For camera connected before mCallbacks is set, the corresponding
+        // addDeviceNames() would be called later in setCallbacks().
+        return;
+    }
+
+    bool found = false;
+    CameraDeviceStatus status = (CameraDeviceStatus)new_status;
+    for (auto const& deviceNamePair : cp->mCameraDeviceNames) {
+        if (cameraIdStr.compare(deviceNamePair.first) == 0) {
+            cp->mCallbacks->cameraDeviceStatusChange(deviceNamePair.second, status);
+            found = true;
+        }
+    }
+
+    switch (status) {
         case CameraDeviceStatus::PRESENT:
         case CameraDeviceStatus::ENUMERATING:
             if (!found) {
@@ -176,7 +178,6 @@
             if (found) {
                 cp->removeDeviceNames(camera_id);
             }
-        }
     }
 }
 
@@ -222,22 +223,6 @@
     return cameraId;
 }
 
-int CameraProvider::getCameraDeviceVersion(const hidl_string& deviceName) {
-    std::string deviceVersion;
-    bool match = matchDeviceName(deviceName, &deviceVersion, nullptr);
-    if (!match) {
-        return -1;
-    }
-    if (deviceVersion == kHAL3_3) {
-        return CAMERA_DEVICE_API_VERSION_3_3;
-    } else if (deviceVersion == kHAL3_2) {
-        return CAMERA_DEVICE_API_VERSION_3_2;
-    } else if (deviceVersion == kHAL1_0) {
-        return CAMERA_DEVICE_API_VERSION_1_0;
-    }
-    return 0;
-}
-
 std::string CameraProvider::getHidlDeviceName(
         std::string cameraId, int deviceVersion) {
     // Maybe consider create a version check method and SortedVec to speed up?
@@ -245,9 +230,16 @@
             deviceVersion != CAMERA_DEVICE_API_VERSION_3_2 &&
             deviceVersion != CAMERA_DEVICE_API_VERSION_3_3 &&
             deviceVersion != CAMERA_DEVICE_API_VERSION_3_4 &&
-            deviceVersion != CAMERA_DEVICE_API_VERSION_3_5) {
+            deviceVersion != CAMERA_DEVICE_API_VERSION_3_5 &&
+            deviceVersion != CAMERA_DEVICE_API_VERSION_3_6) {
         return hidl_string("");
     }
+
+    // Supported combinations:
+    // CAMERA_DEVICE_API_VERSION_1_0 -> ICameraDevice@1.0
+    // CAMERA_DEVICE_API_VERSION_3_[2-4] -> ICameraDevice@[3.2|3.3]
+    // CAMERA_DEVICE_API_VERSION_3_5 + CAMERA_MODULE_API_VERSION_2_4 -> ICameraDevice@3.4
+    // CAMERA_DEVICE_API_VERSION_3_[5-6] + CAMERA_MODULE_API_VERSION_2_5 -> ICameraDevice@3.5
     bool isV1 = deviceVersion == CAMERA_DEVICE_API_VERSION_1_0;
     int versionMajor = isV1 ? 1 : 3;
     int versionMinor = isV1 ? 0 : mPreferredHal3MinorVersion;
@@ -257,6 +249,8 @@
         } else {
             versionMinor = 4;
         }
+    } else if (deviceVersion == CAMERA_DEVICE_API_VERSION_3_6) {
+        versionMinor = 5;
     }
     char deviceName[kMaxCameraDeviceNameLen];
     snprintf(deviceName, sizeof(deviceName), "device@%d.%d/legacy/%s",
@@ -356,7 +350,8 @@
 
     // device_version undefined in CAMERA_MODULE_API_VERSION_1_0,
     // All CAMERA_MODULE_API_VERSION_1_0 devices are backward-compatible
-    if (mModule->getModuleApiVersion() >= CAMERA_MODULE_API_VERSION_2_0) {
+    uint16_t moduleVersion = mModule->getModuleApiVersion();
+    if (moduleVersion >= CAMERA_MODULE_API_VERSION_2_0) {
         // Verify the device version is in the supported range
         switch (info.device_version) {
             case CAMERA_DEVICE_API_VERSION_1_0:
@@ -366,6 +361,20 @@
             case CAMERA_DEVICE_API_VERSION_3_5:
                 // in support
                 break;
+            case CAMERA_DEVICE_API_VERSION_3_6:
+                /**
+                 * ICameraDevice@3.5 contains APIs from both
+                 * CAMERA_DEVICE_API_VERSION_3_6 and CAMERA_MODULE_API_VERSION_2_5
+                 * so we require HALs to uprev both for simplified supported combinations.
+                 * HAL can still opt in individual new APIs indepedently.
+                 */
+                if (moduleVersion < CAMERA_MODULE_API_VERSION_2_5) {
+                    ALOGE("%s: Device %d has unsupported version combination:"
+                            "HAL version %x and module version %x",
+                            __FUNCTION__, id, info.device_version, moduleVersion);
+                    return NO_INIT;
+                }
+                break;
             case CAMERA_DEVICE_API_VERSION_2_0:
             case CAMERA_DEVICE_API_VERSION_2_1:
             case CAMERA_DEVICE_API_VERSION_3_0:
@@ -439,8 +448,22 @@
 
 // Methods from ::android::hardware::camera::provider::V2_4::ICameraProvider follow.
 Return<Status> CameraProvider::setCallback(const sp<ICameraProviderCallback>& callback)  {
+    if (callback == nullptr) {
+        return Status::ILLEGAL_ARGUMENT;
+    }
+
     Mutex::Autolock _l(mCbLock);
     mCallbacks = callback;
+
+    // Add and report all presenting external cameras.
+    for (auto const& statusPair : mCameraStatusMap) {
+        int id = std::stoi(statusPair.first);
+        auto status = static_cast<CameraDeviceStatus>(statusPair.second);
+        if (id >= mNumberOfLegacyCameras && status != CameraDeviceStatus::NOT_PRESENT) {
+            addDeviceNames(id, status, true);
+        }
+    }
+
     return Status::OK;
 }
 
@@ -452,6 +475,11 @@
 Return<void> CameraProvider::getCameraIdList(getCameraIdList_cb _hidl_cb)  {
     std::vector<hidl_string> deviceNameList;
     for (auto const& deviceNamePair : mCameraDeviceNames) {
+        if (std::stoi(deviceNamePair.first) >= mNumberOfLegacyCameras) {
+            // External camera devices must be reported through the device status change callback,
+            // not in this list.
+            continue;
+        }
         if (mCameraStatusMap[deviceNamePair.first] == CAMERA_DEVICE_STATUS_PRESENT) {
             deviceNameList.push_back(deviceNamePair.second);
         }
@@ -552,10 +580,11 @@
         return Void();
     }
 
-    // ICameraDevice 3.4 or upper
     sp<android::hardware::camera::device::V3_2::implementation::CameraDevice> deviceImpl;
+
+    // ICameraDevice 3.4 or upper
     if (deviceVersion >= kHAL3_4) {
-        ALOGV("Constructing v3.4 camera device");
+        ALOGV("Constructing v3.4+ camera device");
         if (deviceVersion == kHAL3_4) {
             deviceImpl = new android::hardware::camera::device::V3_4::implementation::CameraDevice(
                     mModule, cameraId, mCameraDeviceNames);
diff --git a/camera/provider/2.4/default/CameraProvider.h b/camera/provider/2.4/default/CameraProvider.h
index 0f0959f..10e9b0d 100644
--- a/camera/provider/2.4/default/CameraProvider.h
+++ b/camera/provider/2.4/default/CameraProvider.h
@@ -98,7 +98,6 @@
 
     // extract legacy camera ID/device version from a HIDL device name
     static std::string getLegacyCameraId(const hidl_string& deviceName);
-    static int getCameraDeviceVersion(const hidl_string& deviceName);
 
     // convert conventional HAL status to HIDL Status
     static Status getHidlStatus(int);
diff --git a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
index 1556c08..211240a 100644
--- a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
+++ b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
@@ -5521,6 +5521,24 @@
         ADD_FAILURE() << "ANDROID_REQUEST_CHARACTERISTIC_KEYS_NEEDING_PERMISSION "
             << " per API contract should never be set by Hal!";
     }
+    retcode = find_camera_metadata_ro_entry(metadata,
+            ANDROID_DEPTH_AVAILABLE_DYNAMIC_DEPTH_STREAM_CONFIGURATIONS, &entry);
+    if ((0 == retcode) || (entry.count > 0)) {
+        ADD_FAILURE() << "ANDROID_DEPTH_AVAILABLE_DYNAMIC_DEPTH_STREAM_CONFIGURATIONS"
+            << " per API contract should never be set by Hal!";
+    }
+    retcode = find_camera_metadata_ro_entry(metadata,
+            ANDROID_DEPTH_AVAILABLE_DYNAMIC_DEPTH_MIN_FRAME_DURATIONS, &entry);
+    if ((0 == retcode) || (entry.count > 0)) {
+        ADD_FAILURE() << "ANDROID_DEPTH_AVAILABLE_DYNAMIC_DEPTH_MIN_FRAME_DURATIONS"
+            << " per API contract should never be set by Hal!";
+    }
+    retcode = find_camera_metadata_ro_entry(metadata,
+            ANDROID_DEPTH_AVAILABLE_DYNAMIC_DEPTH_STALL_DURATIONS, &entry);
+    if ((0 == retcode) || (entry.count > 0)) {
+        ADD_FAILURE() << "ANDROID_DEPTH_AVAILABLE_DYNAMIC_DEPTH_STALL_DURATIONS"
+            << " per API contract should never be set by Hal!";
+    }
 }
 
 void CameraHidlTest::verifyMonochromeCharacteristics(const CameraMetadata& chars,
diff --git a/compatibility_matrices/Android.mk b/compatibility_matrices/Android.mk
index 6be6930..425e376 100644
--- a/compatibility_matrices/Android.mk
+++ b/compatibility_matrices/Android.mk
@@ -17,8 +17,9 @@
 LOCAL_PATH := $(call my-dir)
 
 BUILD_FRAMEWORK_COMPATIBILITY_MATRIX := $(LOCAL_PATH)/compatibility_matrix.mk
+my_empty_manifest := $(LOCAL_PATH)/manifest.empty.xml
 
-# Framework Compatibility Matrix (common to all FCM versions)
+# System Compatibility Matrix (common to all FCM versions)
 
 include $(CLEAR_VARS)
 include $(LOCAL_PATH)/clear_vars.mk
@@ -26,6 +27,7 @@
 LOCAL_MODULE_STEM := compatibility_matrix.device.xml
 # define LOCAL_MODULE_CLASS for local-generated-sources-dir.
 LOCAL_MODULE_CLASS := ETC
+LOCAL_MODULE_RELATIVE_PATH := vintf
 
 ifndef DEVICE_FRAMEWORK_COMPATIBILITY_MATRIX_FILE
 LOCAL_SRC_FILES := compatibility_matrix.empty.xml
@@ -37,10 +39,9 @@
 # Enforce that DEVICE_FRAMEWORK_COMPATIBILITY_MATRIX_FILE does not specify required HALs
 # by checking it against an empty manifest. But the empty manifest needs to contain
 # BOARD_SEPOLICY_VERS to be compatible with DEVICE_FRAMEWORK_COMPATIBILITY_MATRIX_FILE.
-my_manifest_src_file := $(LOCAL_PATH)/manifest.empty.xml
 my_gen_check_manifest := $(local-generated-sources-dir)/manifest.check.xml
-$(my_gen_check_manifest): PRIVATE_SRC_FILE := $(my_manifest_src_file)
-$(my_gen_check_manifest): $(my_manifest_src_file) $(HOST_OUT_EXECUTABLES)/assemble_vintf
+$(my_gen_check_manifest): PRIVATE_SRC_FILE := $(my_empty_manifest)
+$(my_gen_check_manifest): $(my_empty_manifest) $(HOST_OUT_EXECUTABLES)/assemble_vintf
 	BOARD_SEPOLICY_VERS=$(BOARD_SEPOLICY_VERS) \
 	VINTF_IGNORE_TARGET_FCM_VERSION=true \
 		$(HOST_OUT_EXECUTABLES)/assemble_vintf -i $(PRIVATE_SRC_FILE) -o $@
@@ -49,7 +50,6 @@
 LOCAL_ASSEMBLE_VINTF_FLAGS += -c "$(my_gen_check_manifest)"
 
 my_gen_check_manifest :=
-my_manifest_src_file :=
 
 endif # DEVICE_FRAMEWORK_COMPATIBILITY_MATRIX_FILE
 
@@ -61,18 +61,57 @@
 
 include $(BUILD_FRAMEWORK_COMPATIBILITY_MATRIX)
 
+# Product Compatibility Matrix
+
+include $(CLEAR_VARS)
+include $(LOCAL_PATH)/clear_vars.mk
+LOCAL_MODULE := product_compatibility_matrix.xml
+
+ifndef DEVICE_PRODUCT_COMPATIBILITY_MATRIX_FILE
+my_framework_matrix_deps :=
+include $(BUILD_PHONY_PACKAGE)
+else # DEVICE_PRODUCT_COMPATIBILITY_MATRIX_FILE
+
+LOCAL_MODULE_STEM := compatibility_matrix.xml
+LOCAL_PRODUCT_MODULE := true
+LOCAL_MODULE_CLASS := ETC
+LOCAL_MODULE_RELATIVE_PATH := vintf
+
+# DEVICE_PRODUCT_COMPATIBILITY_MATRIX_FILE specify an absolute path
+LOCAL_GENERATED_SOURCES := $(DEVICE_PRODUCT_COMPATIBILITY_MATRIX_FILE)
+
+# Enforce that DEVICE_PRODUCT_COMPATIBILITY_MATRIX_FILE does not specify required HALs
+# by checking it against an empty manifest.
+LOCAL_GEN_FILE_DEPENDENCIES += $(my_empty_manifest)
+LOCAL_ASSEMBLE_VINTF_FLAGS += -c "$(my_empty_manifest)"
+
+my_framework_matrix_deps := $(LOCAL_MODULE)
+
+include $(BUILD_FRAMEWORK_COMPATIBILITY_MATRIX)
+
+endif # DEVICE_PRODUCT_COMPATIBILITY_MATRIX_FILE
+
 my_system_matrix_deps := \
     framework_compatibility_matrix.legacy.xml \
     framework_compatibility_matrix.1.xml \
     framework_compatibility_matrix.2.xml \
     framework_compatibility_matrix.3.xml \
     framework_compatibility_matrix.current.xml \
-    framework_compatibility_matrix.device.xml
+    framework_compatibility_matrix.device.xml \
 
-# Phony target that installs all framework compatibility matrix files
+my_framework_matrix_deps += \
+    $(my_system_matrix_deps)
+
+# Phony target that installs all system compatibility matrix files
+include $(CLEAR_VARS)
+LOCAL_MODULE := system_compatibility_matrix.xml
+LOCAL_REQUIRED_MODULES := $(my_system_matrix_deps)
+include $(BUILD_PHONY_PACKAGE)
+
+# Phony target that installs all framework compatibility matrix files (system + product)
 include $(CLEAR_VARS)
 LOCAL_MODULE := framework_compatibility_matrix.xml
-LOCAL_REQUIRED_MODULES := $(my_system_matrix_deps)
+LOCAL_REQUIRED_MODULES := $(my_framework_matrix_deps)
 include $(BUILD_PHONY_PACKAGE)
 
 # Final Framework Compatibility Matrix for OTA
@@ -80,7 +119,7 @@
 include $(LOCAL_PATH)/clear_vars.mk
 LOCAL_MODULE := verified_assembled_system_matrix.xml
 LOCAL_MODULE_PATH := $(PRODUCT_OUT)
-LOCAL_REQUIRED_MODULES := $(my_system_matrix_deps)
+LOCAL_REQUIRED_MODULES := $(my_framework_matrix_deps)
 LOCAL_GENERATED_SOURCES := $(call module-installed-files,$(LOCAL_REQUIRED_MODULES))
 LOCAL_ADD_VBMETA_VERSION_OVERRIDE := true
 
@@ -97,4 +136,6 @@
 BUILT_SYSTEM_MATRIX := $(LOCAL_BUILT_MODULE)
 
 my_system_matrix_deps :=
+my_framework_matrix_deps :=
+my_empty_manifest :=
 BUILD_FRAMEWORK_COMPATIBILITY_MATRIX :=
diff --git a/compatibility_matrices/CleanSpec.mk b/compatibility_matrices/CleanSpec.mk
new file mode 100644
index 0000000..9b150ed
--- /dev/null
+++ b/compatibility_matrices/CleanSpec.mk
@@ -0,0 +1,47 @@
+# Copyright 2019 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.
+#
+
+# If you don't need to do a full clean build but would like to touch
+# a file or delete some intermediate files, add a clean step to the end
+# of the list.  These steps will only be run once, if they haven't been
+# run before.
+#
+# E.g.:
+#     $(call add-clean-step, touch -c external/sqlite/sqlite3.h)
+#     $(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/STATIC_LIBRARIES/libz_intermediates)
+#
+# Always use "touch -c" and "rm -f" or "rm -rf" to gracefully deal with
+# files that are missing or have been moved.
+#
+# Use $(PRODUCT_OUT) to get to the "out/target/product/blah/" directory.
+# Use $(OUT_DIR) to refer to the "out" directory.
+#
+# If you need to re-do something that's already mentioned, just copy
+# the command and add it to the bottom of the list.  E.g., if a change
+# that you made last week required touching a file and a change you
+# made today requires touching the same file, just copy the old
+# touch step and add it to the end of the list.
+#
+# ************************************************
+# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
+# ************************************************
+
+# For example:
+#$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/AndroidTests_intermediates)
+#$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/core_intermediates)
+#$(call add-clean-step, find $(OUT_DIR) -type f -name "IGTalkSession*" -print0 | xargs -0 rm -f)
+#$(call add-clean-step, rm -rf $(PRODUCT_OUT)/data/*)
+
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/etc/vintf/compatibility_matrix.device.xml)
diff --git a/compatibility_matrices/compatibility_matrix.mk b/compatibility_matrices/compatibility_matrix.mk
index bafc84b..d22e510 100644
--- a/compatibility_matrices/compatibility_matrix.mk
+++ b/compatibility_matrices/compatibility_matrix.mk
@@ -17,7 +17,8 @@
 ##### Input Variables:
 # LOCAL_MODULE: required. Module name for the build system.
 # LOCAL_MODULE_CLASS: optional. Default is ETC.
-# LOCAL_MODULE_PATH: optional. Path of output file. Default is $(TARGET_OUT)/etc/vintf.
+# LOCAL_MODULE_PATH / LOCAL_MODULE_RELATIVE_PATH: required. (Relative) path of output file.
+#       If not defined, LOCAL_MODULE_RELATIVE_PATH will be "vintf".
 # LOCAL_MODULE_STEM: optional. Name of output file. Default is $(LOCAL_MODULE).
 # LOCAL_SRC_FILES: required. Local source files provided to assemble_vintf
 #       (command line argument -i).
@@ -48,7 +49,9 @@
 endif
 
 ifndef LOCAL_MODULE_PATH
-LOCAL_MODULE_PATH := $(TARGET_OUT)/etc/vintf
+ifndef LOCAL_MODULE_RELATIVE_PATH
+$(error Either LOCAL_MODULE_PATH or LOCAL_MODULE_RELATIVE_PATH must be defined.)
+endif
 endif
 
 GEN := $(local-generated-sources-dir)/$(LOCAL_MODULE_STEM)
diff --git a/configstore/1.2/ISurfaceFlingerConfigs.hal b/configstore/1.2/ISurfaceFlingerConfigs.hal
index 7e5f706..431b3fc 100644
--- a/configstore/1.2/ISurfaceFlingerConfigs.hal
+++ b/configstore/1.2/ISurfaceFlingerConfigs.hal
@@ -15,7 +15,7 @@
  */
 package android.hardware.configstore@1.2;
 
-import android.hardware.graphics.common@1.1::PixelFormat;
+import android.hardware.graphics.common@1.2::PixelFormat;
 import android.hardware.graphics.common@1.2::Dataspace;
 import @1.1::ISurfaceFlingerConfigs;
 import @1.0::OptionalBool;
diff --git a/configstore/1.2/default/SurfaceFlingerConfigs.cpp b/configstore/1.2/default/SurfaceFlingerConfigs.cpp
index d38b402..714442b 100644
--- a/configstore/1.2/default/SurfaceFlingerConfigs.cpp
+++ b/configstore/1.2/default/SurfaceFlingerConfigs.cpp
@@ -27,8 +27,8 @@
 namespace V1_2 {
 namespace implementation {
 
-using ::android::hardware::graphics::common::V1_1::PixelFormat;
 using ::android::hardware::graphics::common::V1_2::Dataspace;
+using ::android::hardware::graphics::common::V1_2::PixelFormat;
 
 // ::android::hardware::configstore::V1_0::ISurfaceFlingerConfigs implementation.
 Return<void> SurfaceFlingerConfigs::vsyncEventPhaseOffsetNs(vsyncEventPhaseOffsetNs_cb _hidl_cb) {
diff --git a/configstore/1.2/vts/functional/VtsHalConfigstoreV1_2TargetTest.cpp b/configstore/1.2/vts/functional/VtsHalConfigstoreV1_2TargetTest.cpp
index 881b591..d7f4dcf 100644
--- a/configstore/1.2/vts/functional/VtsHalConfigstoreV1_2TargetTest.cpp
+++ b/configstore/1.2/vts/functional/VtsHalConfigstoreV1_2TargetTest.cpp
@@ -31,10 +31,10 @@
 using ::android::hardware::configstore::V1_0::OptionalBool;
 using ::android::hardware::configstore::V1_0::OptionalInt64;
 using ::android::hardware::configstore::V1_0::OptionalUInt64;
-using ::android::hardware::configstore::V1_2::ISurfaceFlingerConfigs;
 using ::android::hardware::configstore::V1_2::DisplayPrimaries;
-using ::android::hardware::graphics::common::V1_1::PixelFormat;
+using ::android::hardware::configstore::V1_2::ISurfaceFlingerConfigs;
 using ::android::hardware::graphics::common::V1_2::Dataspace;
+using ::android::hardware::graphics::common::V1_2::PixelFormat;
 
 #define ASSERT_OK(ret) ASSERT_TRUE(ret.isOk())
 #define EXPECT_OK(ret) EXPECT_TRUE(ret.isOk())
diff --git a/current.txt b/current.txt
index 3b87306..478cbc5 100644
--- a/current.txt
+++ b/current.txt
@@ -399,8 +399,9 @@
 417ab60fe1ef786778047e4486f3d868ebce570d91addd8fe4251515213072de android.hardware.neuralnetworks@1.0::types
 e22e8135d061d0e9c4c1a70c25c19fdba10f4d3cda9795ef25b6392fc520317c android.hardware.neuralnetworks@1.1::types
 1d4a5776614c08b5d794a5ec5ab04697260cbd4b3441d5935cd53ee71d19da02 android.hardware.radio@1.0::IRadioResponse
-271187e261b30c01a33011aea257c07a2d2f05b72943ebee89e973e997849973 android.hardware.radio@1.0::types
+ed9da80ec0c96991fd03f0a46107815d0e50f764656e49dba4980fa5c31d5bc3 android.hardware.radio@1.0::types
 1d19720d4fd38b1095f0f555a4bd92b3b12c9b1d0f560b0e9a474cd6dcc20db6 android.hardware.radio@1.2::IRadio
+cd1757867a5e3a3faa362e785239515870d1a3c9ce756c6f0cf0f0fd8aac2547 android.hardware.radio@1.2::types
 e78cf871f9fd1c072874e481e06e18e2681763cf2aa38c1fd777d53bab4eb69b android.hardware.sensors@1.0::types
 3d01e29e8129186f7567c4f9c8bee7480a0768e587b1be9b28adb0a6cbec6bf2 android.hardware.tv.cec@1.0::types
 1722ad002317b1fae1400de709e90f442d94ef22864e05f7a12af48c32e8edc8 android.hardware.usb@1.1::types
diff --git a/gnss/measurement_corrections/1.0/types.hal b/gnss/measurement_corrections/1.0/types.hal
index 5f20734..edf26bf 100644
--- a/gnss/measurement_corrections/1.0/types.hal
+++ b/gnss/measurement_corrections/1.0/types.hal
@@ -79,18 +79,35 @@
  * toaGpsNanosecondsOfWeek
  */
 struct MeasurementCorrections {
-    /** Represents latitude in degrees. */
+    /** Represents latitude in degrees at which the corrections are computed.. */
     double latitudeDegrees;
 
-    /** Represents longitude in degrees. */
+    /** Represents longitude in degrees at which the corrections are computed.. */
     double longitudeDegrees;
 
     /**
-     * Represents altitude in meters above the WGS 84 reference ellipsoid.
+     * Represents altitude in meters above the WGS 84 reference ellipsoid at which the corrections
+     * are computed.
      */
     double altitudeMeters;
 
-    /** Time Of Applicability, GPS time of week */
+    /**
+     * Represents the horizontal uncertainty (68% confidence) in meters on the device position at
+     * which the corrections are provided.
+     *
+     * This value is useful for example to judge how accurate the provided corrections are.
+     */
+    double horizontalPositionUncertaintyMeters;
+
+    /**
+     * Represents the vertical uncertainty (68% confidence) in meters on the device position at
+     * which the corrections are provided.
+     *
+     * This value is useful for example to judge how accurate the provided corrections are.
+     */
+    double verticalPositionUncertaintyMeters;
+
+    /** Time Of Applicability, GPS time of week in nanoseconds. */
     uint64_t toaGpsNanosecondsOfWeek;
 
     /**
diff --git a/graphics/allocator/2.0/default/android.hardware.graphics.allocator@2.0-service.rc b/graphics/allocator/2.0/default/android.hardware.graphics.allocator@2.0-service.rc
index 6eee71f..a2a881a 100644
--- a/graphics/allocator/2.0/default/android.hardware.graphics.allocator@2.0-service.rc
+++ b/graphics/allocator/2.0/default/android.hardware.graphics.allocator@2.0-service.rc
@@ -1,5 +1,6 @@
 service vendor.gralloc-2-0 /vendor/bin/hw/android.hardware.graphics.allocator@2.0-service
     class hal animation
+    interface android.hardware.graphics.allocator@2.0::IAllocator default
     user system
     group graphics drmrpc
     capabilities SYS_NICE
diff --git a/graphics/common/1.2/types.hal b/graphics/common/1.2/types.hal
index 392a12e..3da6176 100644
--- a/graphics/common/1.2/types.hal
+++ b/graphics/common/1.2/types.hal
@@ -25,7 +25,8 @@
 /**
  * Hdr
  */
-@export(name="android_hdr_v1_2_t", value_prefix="HAL_HDR_")
+@export(name="android_hdr_v1_2_t", value_prefix="HAL_HDR_",
+        export_parent="false")
 enum Hdr : @1.0::Hdr {
     HDR10_PLUS = 4,
 };
@@ -41,6 +42,13 @@
      * Use full range, sRGB transfer and BT2020 standard
      */
     DISPLAY_BT2020 = STANDARD_BT2020 | TRANSFER_SRGB | RANGE_FULL,
+
+    /**
+     * ISO 16684-1:2011(E)
+     *
+     * Embedded depth metadata following the dynamic depth specification.
+     */
+    DYNAMIC_DEPTH = 0x1002,
 };
 
 enum ColorMode : @1.1::ColorMode {
@@ -96,3 +104,18 @@
  */
 typedef int32_t[4] Rect;
 
+/**
+ * Pixel formats for graphics buffers.
+ */
+@export(name="android_pixel_format_v1_2_t", value_prefix="HAL_PIXEL_FORMAT_",
+        export_parent="false")
+enum PixelFormat : @1.1::PixelFormat {
+    /**
+     * 24-bit format that has 8-bit H, S, and V components, in that order,
+     * from the lowest memory address to the highest memory address.
+     *
+     * The component values are unsigned normalized to the range [0, 1], whose
+     * interpretation is defined by the dataspace.
+    */
+    HSV_888 = 0x37,
+};
diff --git a/graphics/composer/2.3/IComposerClient.hal b/graphics/composer/2.3/IComposerClient.hal
index cf78dea..a3b7792 100644
--- a/graphics/composer/2.3/IComposerClient.hal
+++ b/graphics/composer/2.3/IComposerClient.hal
@@ -17,7 +17,7 @@
 package android.hardware.graphics.composer@2.3;
 
 import android.hardware.graphics.common@1.1::RenderIntent;
-import android.hardware.graphics.common@1.1::PixelFormat;
+import android.hardware.graphics.common@1.2::PixelFormat;
 import android.hardware.graphics.common@1.2::ColorMode;
 import android.hardware.graphics.common@1.2::Dataspace;
 import android.hardware.graphics.common@1.2::Hdr;
diff --git a/graphics/composer/2.3/utils/hal/include/composer-hal/2.3/ComposerClient.h b/graphics/composer/2.3/utils/hal/include/composer-hal/2.3/ComposerClient.h
index edc203e..a272e72 100644
--- a/graphics/composer/2.3/utils/hal/include/composer-hal/2.3/ComposerClient.h
+++ b/graphics/composer/2.3/utils/hal/include/composer-hal/2.3/ComposerClient.h
@@ -123,7 +123,7 @@
     Return<void> getDisplayedContentSamplingAttributes(
         uint64_t display,
         IComposerClient::getDisplayedContentSamplingAttributes_cb hidl_cb) override {
-        common::V1_1::PixelFormat format;
+        PixelFormat format;
         common::V1_2::Dataspace dataspace;
         hidl_bitfield<IComposerClient::FormatColorComponent> componentMask;
         Error error =
diff --git a/graphics/composer/2.3/utils/hal/include/composer-hal/2.3/ComposerHal.h b/graphics/composer/2.3/utils/hal/include/composer-hal/2.3/ComposerHal.h
index 882621f..a0812ad 100644
--- a/graphics/composer/2.3/utils/hal/include/composer-hal/2.3/ComposerHal.h
+++ b/graphics/composer/2.3/utils/hal/include/composer-hal/2.3/ComposerHal.h
@@ -25,11 +25,11 @@
 namespace V2_3 {
 namespace hal {
 
-using common::V1_1::PixelFormat;
 using common::V1_1::RenderIntent;
 using common::V1_2::ColorMode;
 using common::V1_2::Dataspace;
 using common::V1_2::Hdr;
+using common::V1_2::PixelFormat;
 using V2_1::Display;
 using V2_1::Error;
 using V2_1::Layer;
diff --git a/graphics/composer/2.3/utils/passthrough/include/composer-passthrough/2.3/HwcHal.h b/graphics/composer/2.3/utils/passthrough/include/composer-passthrough/2.3/HwcHal.h
index 9fb6d4b..41e333a 100644
--- a/graphics/composer/2.3/utils/passthrough/include/composer-passthrough/2.3/HwcHal.h
+++ b/graphics/composer/2.3/utils/passthrough/include/composer-passthrough/2.3/HwcHal.h
@@ -34,11 +34,11 @@
 
 namespace detail {
 
-using common::V1_1::PixelFormat;
 using common::V1_1::RenderIntent;
 using common::V1_2::ColorMode;
 using common::V1_2::Dataspace;
 using common::V1_2::Hdr;
+using common::V1_2::PixelFormat;
 using V2_1::Display;
 using V2_1::Error;
 
@@ -91,14 +91,16 @@
 
     Error getClientTargetSupport_2_3(Display display, uint32_t width, uint32_t height,
                                      PixelFormat format, Dataspace dataspace) override {
-        return getClientTargetSupport_2_2(display, width, height, format,
+        return getClientTargetSupport_2_2(display, width, height,
+                                          static_cast<common::V1_1::PixelFormat>(format),
                                           static_cast<common::V1_1::Dataspace>(dataspace));
     }
 
     Error getReadbackBufferAttributes_2_3(Display display, PixelFormat* outFormat,
                                           Dataspace* outDataspace) override {
         return getReadbackBufferAttributes(
-            display, outFormat, reinterpret_cast<common::V1_1::Dataspace*>(outDataspace));
+                display, reinterpret_cast<common::V1_1::PixelFormat*>(outFormat),
+                reinterpret_cast<common::V1_1::Dataspace*>(outDataspace));
     }
 
     Error getDisplayIdentificationData(Display display, uint8_t* outPort,
diff --git a/graphics/composer/2.3/utils/vts/include/composer-vts/2.3/ComposerVts.h b/graphics/composer/2.3/utils/vts/include/composer-vts/2.3/ComposerVts.h
index 7add322..ad4ef0b 100644
--- a/graphics/composer/2.3/utils/vts/include/composer-vts/2.3/ComposerVts.h
+++ b/graphics/composer/2.3/utils/vts/include/composer-vts/2.3/ComposerVts.h
@@ -32,11 +32,11 @@
 namespace V2_3 {
 namespace vts {
 
-using common::V1_1::PixelFormat;
 using common::V1_1::RenderIntent;
 using common::V1_2::ColorMode;
 using common::V1_2::Dataspace;
 using common::V1_2::Hdr;
+using common::V1_2::PixelFormat;
 using V2_1::Display;
 using V2_1::Error;
 using V2_3::IComposer;
diff --git a/graphics/composer/2.3/vts/functional/VtsHalGraphicsComposerV2_3TargetTest.cpp b/graphics/composer/2.3/vts/functional/VtsHalGraphicsComposerV2_3TargetTest.cpp
index dca7406..de74e28 100644
--- a/graphics/composer/2.3/vts/functional/VtsHalGraphicsComposerV2_3TargetTest.cpp
+++ b/graphics/composer/2.3/vts/functional/VtsHalGraphicsComposerV2_3TargetTest.cpp
@@ -36,10 +36,10 @@
 namespace {
 
 using common::V1_0::BufferUsage;
-using common::V1_1::PixelFormat;
 using common::V1_1::RenderIntent;
 using common::V1_2::ColorMode;
 using common::V1_2::Dataspace;
+using common::V1_2::PixelFormat;
 using mapper::V2_0::IMapper;
 using mapper::V2_0::vts::Gralloc;
 
@@ -492,9 +492,6 @@
 }
 
 TEST_F(GraphicsComposerHidlTest, GetDisplayedContentSamplingAttributes) {
-    using common::V1_1::PixelFormat;
-    using common::V1_2::Dataspace;
-
     int constexpr invalid = -1;
     auto format = static_cast<PixelFormat>(invalid);
     auto dataspace = static_cast<Dataspace>(invalid);
diff --git a/input/classifier/1.0/Android.bp b/input/classifier/1.0/Android.bp
index c3c6fc6..6815a51 100644
--- a/input/classifier/1.0/Android.bp
+++ b/input/classifier/1.0/Android.bp
@@ -7,29 +7,12 @@
         enabled: true,
     },
     srcs: [
-        "types.hal",
         "IInputClassifier.hal",
     ],
     interfaces: [
+        "android.hardware.input.common@1.0",
         "android.hidl.base@1.0",
     ],
-    types: [
-        "Action",
-        "Axis",
-        "Button",
-        "Classification",
-        "EdgeFlag",
-        "Flag",
-        "Meta",
-        "MotionEvent",
-        "PointerCoords",
-        "PointerProperties",
-        "PolicyFlag",
-        "Source",
-        "SourceClass",
-        "ToolType",
-        "VideoFrame",
-    ],
     gen_java: true,
 }
 
diff --git a/input/classifier/1.0/IInputClassifier.hal b/input/classifier/1.0/IInputClassifier.hal
index edc1138..7397fea 100644
--- a/input/classifier/1.0/IInputClassifier.hal
+++ b/input/classifier/1.0/IInputClassifier.hal
@@ -16,6 +16,9 @@
 
 package android.hardware.input.classifier@1.0;
 
+import android.hardware.input.common@1.0::Classification;
+import android.hardware.input.common@1.0::MotionEvent;
+
 interface IInputClassifier {
 
   /**
@@ -23,4 +26,16 @@
    */
   classify(MotionEvent event) generates (Classification classification);
 
+  /**
+   * Called by the framework to reset the HAL internal state. The reset may be called
+   * to prevent an inconsistent stream of events to be sent to the HAL.
+   */
+  reset();
+
+  /**
+   * Called by the framework to reset the HAL internal state for a specific device.
+   * The reset may be called once device reset is received by the framework.
+   */
+  resetDevice(int32_t deviceId);
+
 };
diff --git a/input/classifier/1.0/default/InputClassifier.cpp b/input/classifier/1.0/default/InputClassifier.cpp
index c463361..a78bbc5 100644
--- a/input/classifier/1.0/default/InputClassifier.cpp
+++ b/input/classifier/1.0/default/InputClassifier.cpp
@@ -21,7 +21,7 @@
 #include <log/log.h>
 #include <utils/Timers.h>
 
-using namespace android::hardware::input::classifier::V1_0;
+using namespace android::hardware::input::common::V1_0;
 
 namespace android {
 namespace hardware {
@@ -57,6 +57,18 @@
     return Classification::NONE;
 }
 
+Return<void> InputClassifier::reset() {
+    // We don't have any internal state in this example implementation,
+    // so no work needed here.
+    return Void();
+}
+
+Return<void> InputClassifier::resetDevice(int32_t /*deviceId*/) {
+    // We don't have any internal per-device state in this example implementation,
+    // so no work needed here.
+    return Void();
+}
+
 }  // namespace implementation
 }  // namespace V1_0
 }  // namespace classifier
diff --git a/input/classifier/1.0/default/InputClassifier.h b/input/classifier/1.0/default/InputClassifier.h
index 0858ecb..eef370e 100644
--- a/input/classifier/1.0/default/InputClassifier.h
+++ b/input/classifier/1.0/default/InputClassifier.h
@@ -31,8 +31,12 @@
 
 struct InputClassifier : public IInputClassifier {
     // Methods from ::android::hardware::input::classifier::V1_0::IInputClassifier follow.
-    Return<Classification> classify(
-        const ::android::hardware::input::classifier::V1_0::MotionEvent& event) override;
+
+    Return<android::hardware::input::common::V1_0::Classification> classify(
+            const android::hardware::input::common::V1_0::MotionEvent& event) override;
+
+    Return<void> reset() override;
+    Return<void> resetDevice(int32_t deviceId) override;
 };
 
 }  // namespace implementation
diff --git a/input/common/1.0/Android.bp b/input/common/1.0/Android.bp
new file mode 100644
index 0000000..68a77f1
--- /dev/null
+++ b/input/common/1.0/Android.bp
@@ -0,0 +1,34 @@
+// This file is autogenerated by hidl-gen -Landroidbp.
+
+hidl_interface {
+    name: "android.hardware.input.common@1.0",
+    root: "android.hardware",
+    vndk: {
+        enabled: true,
+    },
+    srcs: [
+        "types.hal",
+    ],
+    interfaces: [
+        "android.hidl.base@1.0",
+    ],
+    types: [
+        "Action",
+        "Axis",
+        "Button",
+        "Classification",
+        "EdgeFlag",
+        "Flag",
+        "Meta",
+        "MotionEvent",
+        "PointerCoords",
+        "PointerProperties",
+        "PolicyFlag",
+        "Source",
+        "SourceClass",
+        "ToolType",
+        "VideoFrame",
+    ],
+    gen_java: true,
+}
+
diff --git a/input/classifier/1.0/types.hal b/input/common/1.0/types.hal
similarity index 99%
rename from input/classifier/1.0/types.hal
rename to input/common/1.0/types.hal
index 244ecd9..1a07f3b 100644
--- a/input/classifier/1.0/types.hal
+++ b/input/common/1.0/types.hal
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package android.hardware.input.classifier@1.0;
+package android.hardware.input.common@1.0;
 
 
 /**
@@ -435,12 +435,12 @@
 };
 
 enum SourceClass: uint8_t {
-    NONE = 1 << 0,
-    BUTTON = 1 << 1,
-    POINTER = 1 << 2,
-    NAVIGATION = 1 << 3,
-    POSITION = 1 << 4,
-    JOYSTICK = 1 << 5,
+    NONE = 0 << 0,
+    BUTTON = 1 << 0,
+    POINTER = 1 << 1,
+    NAVIGATION = 1 << 2,
+    POSITION = 1 << 3,
+    JOYSTICK = 1 << 4,
 };
 
 /**
diff --git a/media/c2/1.0/Android.bp b/media/c2/1.0/Android.bp
index c37c22b..56c78b2 100644
--- a/media/c2/1.0/Android.bp
+++ b/media/c2/1.0/Android.bp
@@ -13,6 +13,7 @@
         "IComponentListener.hal",
         "IComponentStore.hal",
         "IConfigurable.hal",
+        "IInputSink.hal",
         "IInputSurface.hal",
         "IInputSurfaceConnection.hal",
     ],
diff --git a/media/c2/1.0/IComponent.hal b/media/c2/1.0/IComponent.hal
index deb9255..7fd551f 100644
--- a/media/c2/1.0/IComponent.hal
+++ b/media/c2/1.0/IComponent.hal
@@ -22,13 +22,19 @@
 import IConfigurable;
 import IComponentInterface;
 import IComponentListener;
+import IInputSurface;
+import IInputSurfaceConnection;
 
 /**
- * Interface for a Codec 2.0 component corresponding to API level 1.0 or
- * below. Components have two states: stopped and running. The running
- * state has three sub-states: executing, tripped and error.
+ * Interface for a Codec2 component corresponding to API level 1.0 or below.
+ * Components have two states: stopped and running. The running state has three
+ * sub-states: executing, tripped and error.
+ *
+ * All methods in `IComponent` must not block. If a method call cannot be
+ * completed in a timely manner, it must return `TIMED_OUT` in the return
+ * status.
  */
-interface IComponent extends IComponentInterface {
+interface IComponent {
 
     // METHODS AVAILABLE WHEN RUNNING
     // =========================================================================
@@ -38,44 +44,42 @@
      *
      * This method must be supported in running (including tripped) states.
      *
-     * This method must return within 1ms
+     * It is acceptable for this method to return `OK` and return an error value
+     * using the IComponentListener::onWorkDone() callback.
      *
-     * It is acceptable for this method to return OK and return an error value
-     * using the onWorkDone() callback.
-     *
-     * @param workBundle WorkBundle object containing Works to queue to the
-     * component.
+     * @param workBundle `WorkBundle` object containing a list of `Work` objects
+     *     to queue to the component.
      * @return status Status of the call, which may be
-     *   - OK        - Works in \p workBundle were successfully queued.
-     *   - BAD_INDEX - Some component(s) in some Work do(es) not exist.
-     *   - CANNOT_DO - The components are not tunneled.
-     *   - NO_MEMORY - Not enough memory to queue \p workBundle.
-     *   - CORRUPTED - Some unknown error prevented queuing the Works.
-     *                 (unexpected).
+     *   - `OK`        - Works in @p workBundle were successfully queued.
+     *   - `BAD_INDEX` - Some component id in some `Worklet` is not valid.
+     *   - `CANNOT_DO` - The components are not tunneled but some `Work` object
+     *                   contains tunneling information.
+     *   - `NO_MEMORY` - Not enough memory to queue @p workBundle.
+     *   - `TIMED_OUT` - The operation cannot be finished in a timely manner.
+     *   - `CORRUPTED` - Some unknown error occurred.
      */
     queue(WorkBundle workBundle) generates (Status status);
 
     /**
-     * Discards and abandons any pending work for the component.
+     * Discards and abandons any pending `Work` items for the component.
      *
      * This method must be supported in running (including tripped) states.
      *
-     * This method must return within 5ms.
+     * `Work` that could be immediately abandoned/discarded must be returned in
+     * @p flushedWorkBundle. The order in which queued `Work` items are
+     * discarded can be arbitrary.
      *
-     * Work that could be immediately abandoned/discarded must be returned in
-     * \p flushedWorks; this can be done in an arbitrary order.
-     *
-     * Work that could not be abandoned or discarded immediately must be marked
-     * to be discarded at the earliest opportunity, and must be returned via
-     * the onWorkDone() callback. This must be completed within 500ms.
+     * `Work` that could not be abandoned or discarded immediately must be
+     * marked to be discarded at the earliest opportunity, and must be returned
+     * via IComponentListener::onWorkDone(). This must be completed within
+     * 500ms.
      *
      * @return status Status of the call, which may be
-     *   - OK        - The component has been successfully flushed.
-     *   - TIMED_OUT - The flush could not be completed within the time limit.
-     *                 (unexpected)
-     *   - CORRUPTED - Some unknown error prevented flushing from
-     *                 completion. (unexpected)
-     * @return flushedWorkBundle WorkBundle object containing flushed Works.
+     *   - `OK`        - The component has been successfully flushed.
+     *   - `TIMED_OUT` - The operation cannot be finished in a timely manner.
+     *   - `CORRUPTED` - Some unknown error occurred.
+     * @return flushedWorkBundle `WorkBundle` object containing flushed `Work`
+     *     items.
      */
     flush(
         ) generates (
@@ -87,42 +91,39 @@
      * Drains the component, and optionally downstream components. This is a
      * signalling method; as such it does not wait for any work completion.
      *
-     * Marks last work item as "drain-till-here", so component is notified not
-     * to wait for further work before it processes work already queued. This
-     * method can also be used to set the end-of-stream flag after work has been
-     * queued. Client can continue to queue further work immediately after this
-     * method returns.
+     * The last `Work` item is marked as "drain-till-here", so the component is
+     * notified not to wait for further `Work` before it processes what is
+     * already queued. This method can also be used to set the end-of-stream
+     * flag after `Work` has been queued. Client can continue to queue further
+     * `Work` immediately after this method returns.
      *
      * This method must be supported in running (including tripped) states.
      *
-     * This method must return within 1ms.
-     *
-     * Work that is completed must be returned via the onWorkDone() callback.
+     * `Work` that is completed must be returned via
+     * IComponentListener::onWorkDone().
      *
      * @param withEos Whether to drain the component with marking end-of-stream.
      * @return status Status of the call, which may be
-     *   - OK        - The drain request has been successfully recorded.
-     *   - TIMED_OUT - The flush could not be completed within the time limit.
-     *                 (unexpected)
-     *   - CORRUPTED - Some unknown error prevented flushing from completion.
-     *                 (unexpected)
+     *   - `OK`        - The drain request has been successfully recorded.
+     *   - `TIMED_OUT` - The operation cannot be finished in a timely manner.
+     *   - `CORRUPTED` - Some unknown error occurred.
      */
     drain(bool withEos) generates (Status status);
 
     /**
      * Starts using a surface for output.
      *
-     * @param blockPoolId The id of the BlockPool to be associated with the
-     * output surface.
-     * @param surface A surface to use for codec output.
+     * This method must not block.
+     *
+     * @param blockPoolId Id of the `C2BlockPool` to be associated with the
+     *     output surface.
+     * @param surface Output surface.
      * @return status Status of the call, which may be
-     *   - OK        - The operation completed successfully.
-     *   - CANNOT_DO - The component does not support an output surface.
-     *   - REFUSED   - The output surface cannot be accessed.
-     *   - TIMED_OUT - The component could not be connected within the time
-     *                 limit. (unexpected)
-     *   - CORRUPTED - Some unknown error prevented connecting the component.
-     *                 (unexpected)
+     *   - `OK`        - The operation completed successfully.
+     *   - `CANNOT_DO` - The component does not support an output surface.
+     *   - `REFUSED`   - The output surface cannot be accessed.
+     *   - `TIMED_OUT` - The operation cannot be finished in a timely manner.
+     *   - `CORRUPTED` - Some unknown error occurred.
      */
     setOutputSurface(
             uint64_t blockPoolId,
@@ -132,65 +133,101 @@
         );
 
     /**
-     * Starts using a persistent OMX input surface for a component.
+     * Starts using an input surface.
      *
      * The component must be in running state.
      *
-     * @param producer Producer component of an OMX persistent input surface.
-     * @param source Source component of an OMX persistent input surface.
+     * @param inputSurface Input surface to connect to.
      * @return status Status of the call, which may be
-     *   - OK        - The operation completed successfully.
-     *   - CANNOT_DO - The component does not support an input surface.
-     *   - BAD_STATE - Component is not in running state.
-     *   - DUPLICATE - The component is already connected to an input surface.
-     *   - REFUSED   - The input surface is already in use.
-     *   - NO_MEMORY - Not enough memory to start the component.
-     *   - TIMED_OUT - The component could not be connected within the time
-     *                 limit. (unexpected)
-     *   - CORRUPTED - Some unknown error prevented connecting the component.
-     *                 (unexpected)
+     *   - `OK`        - The operation completed successfully.
+     *   - `CANNOT_DO` - The component does not support an input surface.
+     *   - `BAD_STATE` - The component is not in running state.
+     *   - `DUPLICATE` - The component is already connected to an input surface.
+     *   - `REFUSED`   - The input surface is already in use.
+     *   - `NO_MEMORY` - Not enough memory to start the component.
+     *   - `TIMED_OUT` - The operation cannot be finished in a timely manner.
+     *   - `CORRUPTED` - Some unknown error occurred.
+     * @return connection `IInputSurfaceConnection` object, which can be used to
+     *     query and configure properties of the connection. This cannot be
+     *     null.
+     */
+    connectToInputSurface(
+            IInputSurface inputSurface
+        ) generates (
+            Status status,
+            IInputSurfaceConnection connection
+        );
+
+    /**
+     * Starts using an OMX input surface.
+     *
+     * The component must be in running state.
+     *
+     * This method is similar to connectToInputSurface(), but it takes an OMX
+     * input surface (as a pair of `IGraphicBufferProducer` and
+     * `IGraphicBufferSource`) instead of Codec2's own `IInputSurface`.
+     *
+     * @param producer Producer component of an OMX input surface.
+     * @param source Source component of an OMX input surface.
+     * @return status Status of the call, which may be
+     *   - `OK`        - The operation completed successfully.
+     *   - `CANNOT_DO` - The component does not support an OMX input surface.
+     *   - `BAD_STATE` - The component is not in running state.
+     *   - `DUPLICATE` - The component is already connected to an input surface.
+     *   - `REFUSED`   - The input surface is already in use.
+     *   - `NO_MEMORY` - Not enough memory to start the component.
+     *   - `TIMED_OUT` - The operation cannot be finished in a timely manner.
+     *   - `CORRUPTED` - Some unknown error occurred.
+     * @return connection `IInputSurfaceConnection` object, which can be used to
+     *     query and configure properties of the connection. This cannot be
+     *     null.
      */
     connectToOmxInputSurface(
             IGraphicBufferProducer producer,
             IGraphicBufferSource source
-        ) generates (Status status);
+        ) generates (
+            Status status,
+            IInputSurfaceConnection connection
+        );
 
     /**
      * Stops using an input surface.
      *
-     * This call is used for both Codec 2.0 and OMX input surfaces.
-     *
      * The component must be in running state.
      *
      * @return status Status of the call, which may be
-     *   - OK        - The operation completed successfully.
-     *   - CANNOT_DO - The component does not support an input surface.
-     *   - BAD_STATE - Component is not in running state.
-     *   - NOT_FOUND - The component is not connected to an input surface.
-     *   - TIMED_OUT - The component could not be connected within the time
-     *                 limit. (unexpected)
-     *   - CORRUPTED - Some unknown error prevented connecting the component.
-     *                 (unexpected)
+     *   - `OK`        - The operation completed successfully.
+     *   - `CANNOT_DO` - The component does not support an input surface.
+     *   - `BAD_STATE` - The component is not in running state.
+     *   - `NOT_FOUND` - The component is not connected to an input surface.
+     *   - `TIMED_OUT` - The operation cannot be finished in a timely manner.
+     *   - `CORRUPTED` - Some unknown error occurred.
      */
     disconnectFromInputSurface() generates (Status Status);
 
     /**
-     * Creates a local block pool backed by the given allocator and returns its
-     * identifier.
+     * Creates a local `C2BlockPool` backed by the given allocator and returns
+     * its id.
      *
-     * This call must return within 100 msec.
+     * The returned @p blockPoolId is the only way the client can refer to a
+     * `C2BlockPool` object in the component. The id can be passed to
+     * setOutputSurface() or used in some C2Param objects later.
      *
-     * @param allocatorId The Codec 2.0 allocator ID
+     * The created `C2BlockPool` object can be destroyed by calling
+     * destroyBlockPool(), reset() or release(). reset() and release() must
+     * destroy all `C2BlockPool` objects that have been created.
+     *
+     * @param allocatorId Id of a `C2Allocator`.
      * @return status Status of the call, which may be
-     *   - OK        - The operation completed successfully.
-     *   - NO_MEMORY - Not enough memory to create the pool.
-     *   - BAD_VALUE - Invalid allocator.
-     *   - TIMED_OUT - The pool could not be created within the time
-     *                 limit. (unexpected)
-     *   - CORRUPTED - Some unknown error prevented creating the pool.
-     *                 (unexpected)
-     * @return blockPoolId The Codec 2.0 blockpool ID for the created pool.
-     * @return configurable Configuration interface for the created pool.
+     *   - `OK`        - The operation completed successfully.
+     *   - `NO_MEMORY` - Not enough memory to create the pool.
+     *   - `BAD_VALUE` - @p allocatorId is not recognized.
+     *   - `TIMED_OUT` - The operation cannot be finished in a timely manner.
+     *   - `CORRUPTED` - Some unknown error occurred.
+     * @return blockPoolId Id of the created C2BlockPool object. This may be
+     *     used in setOutputSurface() if the allocator
+     * @return configurable Configuration interface for the created pool. This
+     *     must not be null.
      */
     createBlockPool(uint32_t allocatorId) generates (
         Status status,
@@ -201,17 +238,13 @@
     /**
      * Destroys a local block pool previously created by createBlockPool().
      *
-     * This call must return within 100 msec.
-     *
-     * @param blockPoolId The block pool id previously returned by
+     * @param blockPoolId Id of a `C2BlockPool` that was previously returned by
      *      createBlockPool().
      * @return status Status of the call, which may be
-     *   - OK        - The operation completed successfully.
-     *   - NOT_FOUND - The supplied blockPoolId is not valid.
-     *   - TIMED_OUT - The pool could not be destroyedwithin the time limit.
-     *                 (unexpected)
-     *   - CORRUPTED - Some unknown error prevented destruction of the pool.
-     *                 (unexpected)
+     *   - `OK`        - The operation completed successfully.
+     *   - `NOT_FOUND` - The supplied blockPoolId is not valid.
+     *   - `TIMED_OUT` - The operation cannot be finished in a timely manner.
+     *   - `CORRUPTED` - Some unknown error occurred.
      */
     destroyBlockPool(uint64_t blockPoolId) generates (Status status);
 
@@ -223,28 +256,24 @@
      *
      * This method must be supported in stopped state as well as tripped state.
      *
-     * If the return value is OK, the component must be in the running state.
-     * If the return value is BAD_STATE or DUPLICATE, no state change is
-     * expected as a response to this call.
-     * Otherwise, the component must be in the stopped state.
+     * If the return value is `OK`, the component must be in the running state.
+     * If the return value is `BAD_STATE` or `DUPLICATE`, no state change is
+     * expected as a response to this call. Otherwise, the component must be in
+     * the stopped state.
      *
      * If a component is in the tripped state and start() is called while the
-     * component configuration still results in a trip, start must succeed and
-     * a new onTripped callback must be used to communicate the configuration
+     * component configuration still results in a trip, start() must succeed and
+     * a new onTripped() callback must be used to communicate the configuration
      * conflict that results in the new trip.
      *
-     * This method must return within 500ms.
-     *
      * @return status Status of the call, which may be
-     *   - OK        - The component has started successfully.
-     *   - BAD_STATE - Component is not in stopped or tripped state.
-     *   - DUPLICATE - When called during another start call from another
-     *                 thread.
-     *   - NO_MEMORY - Not enough memory to start the component.
-     *   - TIMED_OUT - The component could not be started within the time limit.
-     *                 (unexpected)
-     *   - CORRUPTED - Some unknown error prevented starting the component.
-     *                 (unexpected)
+     *   - `OK`        - The component has started successfully.
+     *   - `BAD_STATE` - Component is not in stopped or tripped state.
+     *   - `DUPLICATE` - When called during another start call from another
+     *                   thread.
+     *   - `NO_MEMORY` - Not enough memory to start the component.
+     *   - `TIMED_OUT` - The operation cannot be finished in a timely manner.
+     *   - `CORRUPTED` - Some unknown error occurred.
      */
     start() generates (Status status);
 
@@ -255,22 +284,22 @@
      *
      * This method must return withing 500ms.
      *
-     * Upon this call, all pending work must be abandoned.
-     * If the return value is BAD_STATE or DUPLICATE, no state change is
-     * expected as a response to this call.
-     * For all other return values, the component must be in the stopped state.
+     * Upon this call, all pending `Work` must be abandoned.
+     *
+     * If the return value is `BAD_STATE` or `DUPLICATE`, no state change is
+     * expected as a response to this call. For all other return values, the
+     * component must be in the stopped state.
      *
      * This does not alter any settings and tunings that may have resulted in a
      * tripped state.
      *
      * @return status Status of the call, which may be
-     *   - OK        - The component has stopped successfully.
-     *   - BAD_STATE - Component is not in running state.
-     *   - DUPLICATE - When called during another stop call from another thread.
-     *   - TIMED_OUT - The component could not be stopped within the time limit.
-     *                 (unexpected)
-     *   - CORRUPTED - Some unknown error prevented starting the component.
-     *                 (unexpected)
+     *   - `OK`        - The component has stopped successfully.
+     *   - `BAD_STATE` - Component is not in running state.
+     *   - `DUPLICATE` - When called during another stop call from another
+     *                   thread.
+     *   - `TIMED_OUT` - The operation cannot be finished in a timely manner.
+     *   - `CORRUPTED` - Some unknown error occurred.
      */
     stop() generates (Status status);
 
@@ -284,25 +313,24 @@
      *
      * This method must return withing 500ms.
      *
-     * After this call returns all work must have been abandoned, all references
-     * must have been released.
+     * When this call returns, if @p status is `OK`, all `Work` items must
+     * have been abandoned, and all resources (including `C2BlockPool` objects
+     * previously created by createBlockPool()) must have been released.
      *
-     * If the return value is BAD_STATE or DUPLICATE, no state change is
-     * expected as a response to this call.
-     * For all other return values, the component shall be in the stopped state.
+     * If the return value is `BAD_STATE` or `DUPLICATE`, no state change is
+     * expected as a response to this call. For all other return values, the
+     * component must be in the stopped state.
      *
-     * This brings settings back to their default - "guaranteeing" no tripped
+     * This brings settings back to their default, "guaranteeing" no tripped
      * state.
      *
      * @return status Status of the call, which may be
-     *   - OK        - The component has been reset.
-     *   - BAD_STATE - Component is in released state.
-     *   - DUPLICATE - When called during another reset call from another
-     *                 thread.
-     *   - TIMED_OUT - The component could not be reset within the time limit.
-     *                 (unexpected)
-     *   - CORRUPTED - Some unknown error prevented resetting the component.
-     *                 (unexpected)
+     *   - `OK`        - The component has been reset.
+     *   - `BAD_STATE` - Component is in released state.
+     *   - `DUPLICATE` - When called during another reset call from another
+     *                   thread.
+     *   - `TIMED_OUT` - The operation cannot be finished in a timely manner.
+     *   - `CORRUPTED` - Some unknown error occurred.
      */
     reset() generates (Status status);
 
@@ -311,19 +339,27 @@
      *
      * This method must be supported in stopped state.
      *
-     * This method must return withing 500ms. Upon return all references must
-     * be abandoned.
+     * This method destroys the component. Upon return, if @p status is `OK` or
+     * `DUPLICATE`, all resources must have been released.
      *
      * @return status Status of the call, which may be
-     *   - OK        - The component has been released.
-     *   - BAD_STATE - The component is running.
-     *   - DUPLICATE - The component is already released.
-     *   - TIMED_OUT - The component could not be released within the time
-     *                 limit. (unexpected)
-     *   - CORRUPTED - Some unknown error prevented releasing the component.
-     *                 (unexpected)
+     *   - `OK`        - The component has been released.
+     *   - `BAD_STATE` - The component is running.
+     *   - `DUPLICATE` - The component is already released.
+     *   - `TIMED_OUT` - The operation cannot be finished in a timely manner.
+     *   - `CORRUPTED` - Some unknown error occurred.
      */
     release() generates (Status status);
 
+    /**
+     * Returns the @ref IComponentInterface instance associated to this
+     * component.
+     *
+     * An @p IConfigurable instance for the component can be obtained by calling
+     * IComponentInterface::getConfigurable() on the returned @p intf.
+     *
+     * @return intf `IComponentInterface` instance. This must not be null.
+     */
+    getInterface() generates (IComponentInterface intf);
 };
 
diff --git a/media/c2/1.0/IComponentInterface.hal b/media/c2/1.0/IComponentInterface.hal
index d4b30b1..a007d02 100644
--- a/media/c2/1.0/IComponentInterface.hal
+++ b/media/c2/1.0/IComponentInterface.hal
@@ -19,21 +19,20 @@
 import IConfigurable;
 
 /**
- * Component interface object. This object contains all of the configuration of
+ * Component interface object. This object contains all of the configurations of
  * a potential or actual component. It can be created and used independently of
- * an actual Codec 2.0 component instance to query support and parameters for
- * various component settings and configurations for a potential component.
- * Actual components also expose this interface.
+ * an actual Codec2 component to query supported parameters for various
+ * component settings, and configurations for a potential component.
+ *
+ * An actual component exposes this interface via IComponent::getInterface().
  */
-interface IComponentInterface extends IConfigurable {
-    /*
-     * There are no additional methods to IConfigurable interface.
+interface IComponentInterface {
+    /**
+     * Returns the @ref IConfigurable instance associated to this component
+     * interface.
      *
-     * Component interfaces have no states.
-     *
-     * The name of the component or component interface object is a unique name
-     * for that component or component interface 'class'; however, multiple
-     * instances of that component must have the same name.
+     * @return configurable `IConfigurable` instance. This must not be null.
      */
+    getConfigurable() generates (IConfigurable configurable);
 };
 
diff --git a/media/c2/1.0/IComponentListener.hal b/media/c2/1.0/IComponentListener.hal
index eb71ecb..70d5fb2 100644
--- a/media/c2/1.0/IComponentListener.hal
+++ b/media/c2/1.0/IComponentListener.hal
@@ -17,54 +17,112 @@
 package android.hardware.media.c2@1.0;
 
 /**
- * This callback interface is used for handling notifications from IComponent.
+ * Callback interface for handling notifications from @ref IComponent.
  */
 interface IComponentListener {
 
     /**
-     * Notify the listener that some works have been completed.
+     * Notify the listener that some `Work` items have been completed.
+     *
+     * All the input buffers in the returned `Work` objects must not be used by
+     * the component after onWorkDone() is called.
+     *
+     * @param workBundle List of completed `Work` objects.
      */
     oneway onWorkDone(WorkBundle workBundle);
 
     /**
      * Notify the listener that the component is tripped.
+     *
+     * @param settingResults List of failures.
      */
     oneway onTripped(vec<SettingResult> settingResults);
 
     /**
      * Notify the listener of an error.
      *
-     * @param status Error type. \p status may be `OK`, which means that an
-     *     error has occurred, but the error type is unknown.
-     * @param errorCode Additional error code. The framework may not recognize
-     *     this.
+     * @param status Error type. @p status may be `OK`, which means that an
+     *     error has occurred, but the error type does not fit into the type
+     *     `Status`. In this case, additional information is provided by
+     *     @p errorCode.
+     * @param errorCode Additional error information. The framework may not
+     *     recognize the meaning of this value.
      */
     oneway onError(Status status, uint32_t errorCode);
 
     /**
-     * Information about rendering of a frame.
+     * Information about rendering of a frame to a `Surface`.
      */
     struct RenderedFrame {
         /**
-         * Id of the buffer queue containing the rendered buffer.
+         * Id of the `BufferQueue` containing the rendered buffer.
+         *
+         * This value must have been obtained by an earlier call to
+         * IGraphicBufferProducer::getUniqueId().
          */
         uint64_t bufferQueueId;
         /**
          * Id of the slot of the rendered buffer.
+         *
+         * This value must have been obtained by an earlier call to
+         * IGraphicBufferProducer::dequeueBuffer() or
+         * IGraphicBufferProducer::attachBuffer().
          */
         int32_t slotId;
         /**
-         * Timestamp of the rendering (consistent with timestamps in
-         * the associated BufferQueue).
+         * Timestamp the rendering happened.
+         *
+         * The reference point for the timestamp is determined by the
+         * `BufferQueue` that performed the rendering.
          */
         int64_t timestampNs;
     };
 
     /**
-     * Notify the listener that frames are rendered.
+     * Notify the listener that frames have been rendered.
      *
-     * @param renderedFrames List of information about renderings of frames.
+     * @param renderedFrames List of @ref RenderedFrame objects.
      */
     oneway onFramesRendered(vec<RenderedFrame> renderedFrames);
+
+    /**
+     * Identifying information for an input buffer previously queued to the
+     * component via IComponent::queue().
+     */
+    struct InputBuffer {
+        /**
+         * This value comes from `Work::input.ordinal.frameIndex` in a `Work`
+         * object that was previously queued.
+         */
+        uint64_t frameIndex;
+        /**
+         * This value is an index into `Work::input.buffers` (which is an array)
+         * in a `Work` object that was previously queued.
+         */
+        uint32_t arrayIndex;
+    };
+
+    /**
+     * Notify the listener that some input buffers are no longer needed by the
+     * component, and hence can be released or reused by the client.
+     *
+     * Input buffers that are contained in a `Work` object returned by an
+     * earlier onWorkDone() call are assumed released, so they must not appear
+     * in any onInputBuffersReleased() calls. That means
+     * onInputBuffersReleased() must only report input buffers that are released
+     * before the output in the same `Work` item is produced. However, it is
+     * possible for an input buffer to be returned by onWorkDone() after it has
+     * been reported by onInputBuffersReleased().
+     *
+     * @note onWorkDone() and onInputBuffersReleased() both notify the client
+     * that input buffers are no longer needed. However, in order to minimize
+     * IPC calls, onInputBuffersReleased() should be called only when
+     * onWorkDone() cannot be called, e.g., the component needs more input
+     * before an output can be produced.
+     *
+     * @param inputBuffers List of `InputBuffer` objects, identifying input
+     * buffers that are no longer needed by the component.
+     */
+    oneway onInputBuffersReleased(vec<InputBuffer> inputBuffers);
 };
 
diff --git a/media/c2/1.0/IComponentStore.hal b/media/c2/1.0/IComponentStore.hal
index 4bfa170..2aa6a70 100644
--- a/media/c2/1.0/IComponentStore.hal
+++ b/media/c2/1.0/IComponentStore.hal
@@ -23,27 +23,33 @@
 import IConfigurable;
 import IInputSurface;
 
-interface IComponentStore extends IConfigurable {
+/**
+ * Entry point for Codec2 HAL.
+ *
+ * All methods in `IComponentStore` must not block. If a method call cannot be
+ * completed in a timely manner, it must return `TIMED_OUT` in the return
+ * status. The only exceptions are getPoolClientManager() and getConfigurable(),
+ * which must always return immediately.
+ */
+interface IComponentStore {
 
     /**
      * Creates a component by name.
      *
-     * This method must return within 100ms.
-     *
-     * @param name Name of the component to create. This should match one of the
+     * @param name Name of the component to create. This must match one of the
      *     names returned by listComponents().
-     * @param listener The component listener to use for the component.
-     * @param pool The buffer pool client manager of the component listener.
-     *     This must be null if the listener process does not own a buffer pool.
+     * @param listener Callback receiver.
+     * @param pool `IClientManager` object of the BufferPool in the client
+     *     process. This may be null if the client does not own a BufferPool.
      * @return status Status of the call, which may be
-     *   - OK        - The component was created successfully.
-     *   - NOT_FOUND - There is no component with the given name.
-     *   - NO_MEMORY - Not enough memory to create the component.
-     *   - TIMED_OUT - The component could not be created within the time limit.
-     *                 (unexpected)
-     *   - CORRUPTED - Some unknown error prevented the creation of the
-     *                 component. (unexpected)
-     * @return comp The created component if `Status = OK`.
+     *   - `OK`        - The component was created successfully.
+     *   - `NOT_FOUND` - There is no component with the given name.
+     *   - `NO_MEMORY` - Not enough memory to create the component.
+     *   - `TIMED_OUT` - The operation cannot be finished in a timely manner.
+     *   - `CORRUPTED` - Some unknown error occurred.
+     * @return comp The created component if @p status is `OK`.
+     *
+     * @sa IComponentListener.
      */
     createComponent(
             string name,
@@ -57,19 +63,15 @@
     /**
      * Creates a component interface by name.
      *
-     * This method must return within 100ms.
-     *
      * @param name Name of the component interface to create. This should match
      *     one of the names returned by listComponents().
      * @return status Status of the call, which may be
-     *   - OK        - The component interface was created successfully.
-     *   - NOT_FOUND - There is no component interface with the given name.
-     *   - NO_MEMORY - Not enough memory to create the component interface.
-     *   - TIMED_OUT - The component interface could not be created within the
-     *                 time limit. (unexpected)
-     *   - CORRUPTED - Some unknown error prevented the creation of the
-     *                 component interface. (unexpected)
-     * @return compIntf The created component interface if `Status = OK`.
+     *   - `OK`        - The component interface was created successfully.
+     *   - `NOT_FOUND` - There is no component interface with the given name.
+     *   - `NO_MEMORY` - Not enough memory to create the component interface.
+     *   - `TIMED_OUT` - The operation cannot be finished in a timely manner.
+     *   - `CORRUPTED` - Some unknown error occurred.
+     * @return compIntf The created component interface if @p status is `OK`.
      */
     createInterface(
             string name
@@ -83,57 +85,49 @@
      */
     struct ComponentTraits {
         /**
-         * Name of the component.
+         * Name of the component. This must be unique for each component.
+         *
+         * This name is use to identify the component to create in
+         * createComponent() and createComponentInterface().
          */
         string name;
 
         enum Domain : uint32_t {
-            AUDIO,
+            OTHER = 0,
             VIDEO,
-            OTHER = 0xffffffff,
+            AUDIO,
+            IMAGE,
         };
         /**
-         * Component domain. The framework may not recognize `OTHER`.
+         * Component domain.
          */
         Domain domain;
-        /**
-         * If #domain is `OTHER`, #domainOther can be used to provide additional
-         * information. Otherwise, #domainOther is ignored. The framework may
-         * not inspect this value.
-         */
-        uint32_t domainOther;
 
         enum Kind : uint32_t {
+            OTHER = 0,
             DECODER,
             ENCODER,
-            OTHER = 0xffffffff,
         };
         /**
-         * Component kind. The framework may not recognize `OTHER`.
+         * Component kind.
          */
         Kind kind;
-        /**
-         * If #kind is `OTHER`, #kindOther can be used to provide additional
-         * information. Otherwise, #kindOther is ignored. The framework may not
-         * inspect this value.
-         */
-        uint32_t kindOther;
 
         /**
-         * Rank used by MediaCodecList to determine component ordering. Lower
+         * Rank used by `MediaCodecList` to determine component ordering. Lower
          * value means higher priority.
          */
         uint32_t rank;
 
         /**
-         * Media type.
+         * MIME type.
          */
         string mediaType;
 
         /**
          * Aliases for component name for backward compatibility.
          *
-         * \note Multiple components can have the same alias (but not the same
+         * Multiple components can have the same alias (but not the same
          * component name) as long as their media types differ.
          */
         vec<string> aliases;
@@ -142,36 +136,51 @@
     /**
      * Returns the list of components supported by this component store.
      *
-     * This method must return within 500ms.
-     *
-     * @return traits List of component traits for all components supported by this store in no
-     * particular order.
+     * @return status Status of the call, which may be
+     *   - `OK`        - The operation was successful.
+     *   - `NO_MEMORY` - Not enough memory to complete this method.
+     *   - `TIMED_OUT` - The operation cannot be finished in a timely manner.
+     *   - `CORRUPTED` - Some unknown error occurred.
+     * @return traits List of component traits for all components supported by
+     *     this store (in no particular order).
      */
-    listComponents() generates (vec<ComponentTraits> traits);
+    listComponents() generates (
+            Status status,
+            vec<ComponentTraits> traits
+        );
 
     /**
      * Creates a persistent input surface that can be used as an input surface
      * for any IComponent instance
      *
-     * This method must return within 100ms.
-     *
-     * @return surface A persistent input surface
+     * @return status Status of the call, which may be
+     *   - `OK`        - The operation was successful.
+     *   - `NO_MEMORY` - Not enough memory to complete this method.
+     *   - `TIMED_OUT` - The operation cannot be finished in a timely manner.
+     *   - `CORRUPTED` - Some unknown error occurred.
+     * @return surface A persistent input surface. This may be null to indicate
+     *     an error.
      */
-    createInputSurface() generates (IInputSurface surface);
+    createInputSurface() generates (
+            Status status,
+            IInputSurface surface
+        );
 
     /**
-     * Returns a list of StructDescriptor object for a set of requested
-     * structures that this store is aware of.
+     * Returns a list of `StructDescriptor` objects for a set of requested
+     * C2Param structure indices that this store is aware of.
      *
      * This operation must be performed at best effort, e.g. the component
      * store must simply ignore all struct indices that it is not aware of.
      *
-     * @param indices struct indices to return des
+     * @param indices Indices of C2Param structures to describe.
      * @return status Status of the call, which may be
-     *   - OK        - The operation completed successfully.
-     *   - NOT_FOUND - Some indices were not known.
-     *   - NO_MEMORY - Not enough memory to complete this method.
-     * @return structs List of StructDescriptor objects.
+     *   - `OK`        - The operation completed successfully.
+     *   - `NOT_FOUND` - Some indices were not known.
+     *   - `NO_MEMORY` - Not enough memory to complete this method.
+     *   - `TIMED_OUT` - The operation cannot be finished in a timely manner.
+     *   - `CORRUPTED` - Some unknown error occurred.
+     * @return structs List of `StructDescriptor` objects.
      */
     getStructDescriptors(
             vec<ParamIndex> indices
@@ -181,33 +190,35 @@
         );
 
     /**
-     * Returns information required for using BufferPool API in buffer passing.
-     * If the returned pool is not null, the client can call registerSender() to
-     * register its IAccessor instance, hence allowing the client to send
-     * buffers to components hosted by this process.
-     *
-     * @return pool If the component store supports receiving buffers via
-     *     BufferPool API, \p pool must be a valid `IClientManager` instance.
-     *     Otherwise, \p pool must be null.
-     */
-    getPoolClientManager(
-        ) generates (
-            IClientManager pool
-        );
-
-    /**
-     * The store must copy the contents of \p src into \p dst without changing
-     * the format of \p dst.
+     * Copies the contents of @p src into @p dst without changing the format of
+     * @p dst.
      *
      * @param src Source buffer.
      * @param dst Destination buffer.
      * @return status Status of the call, which may be
-     *   - OK        - The copy is successful.
-     *   - CANNOT_DO - \p src and \p dst are not compatible.
-     *   - REFUSED   - No permission to copy.
-     *   - CORRUPTED - The copy cannot be done. (unexpected)
+     *   - `OK`        - The copy is successful.
+     *   - `CANNOT_DO` - @p src and @p dst are not compatible.
+     *   - `REFUSED`   - No permission to copy.
+     *   - `TIMED_OUT` - The operation cannot be finished in a timely manner.
+     *   - `CORRUPTED` - Some unknown error occurred.
      */
     copyBuffer(Buffer src, Buffer dst) generates (Status status);
 
+    /**
+     * Returns the `IClientManager` object for the component's BufferPool.
+     *
+     * @return pool If the component store supports receiving buffers via
+     *     BufferPool API, @p pool must be a valid `IClientManager` instance.
+     *     Otherwise, @p pool must be null.
+     */
+    getPoolClientManager() generates (IClientManager pool);
+
+    /**
+     * Returns the @ref IConfigurable instance associated to this component
+     * store.
+     *
+     * @return configurable `IConfigurable` instance. This must not be null.
+     */
+    getConfigurable() generates (IConfigurable configurable);
 };
 
diff --git a/media/c2/1.0/IConfigurable.hal b/media/c2/1.0/IConfigurable.hal
index cd4dd10..31dc4d3 100644
--- a/media/c2/1.0/IConfigurable.hal
+++ b/media/c2/1.0/IConfigurable.hal
@@ -17,43 +17,78 @@
 package android.hardware.media.c2@1.0;
 
 /**
- * Generic configuration interface used by all configurable Codec 2.0
- * components.
+ * Generic configuration interface presented by all configurable Codec2 objects.
  *
- * This interface must be supported in all states of the inheriting
- * object, and must not change the state of the inheriting object.
+ * This interface must be supported in all states of the owning object, and must
+ * not change the state of the owning object.
  */
 interface IConfigurable {
     /**
-     * Returns the name of this object. This must match the name that was
-     * supplied during the creation of the object.
+     * Returns the id of the object. This must be unique among all objects of
+     * the same type hosted by the same store.
      *
-     * @return name Name of this object.
+     * @return id Id of the object.
+     */
+    getId() generates (uint32_t id);
+
+    /**
+     * Returns the name of the object.
+     *
+     * This must match the name that was supplied during the creation of the
+     * object.
+     *
+     * @return name Name of the object.
      */
     getName() generates (string name);
 
     /**
-     * Queries a set of parameters from the object. Querying is performed at
-     * best effort: the object must query all supported parameters and skip
-     * unsupported ones, or parameters that could not be allocated. Any errors
-     * are communicated in the return value.
+     * Queries a set of parameters from the object.
      *
-     * \note Parameter values do not depend on the order of query.
+     * Querying is performed at best effort: the object must query all supported
+     * parameters and skip unsupported ones (which may include parameters that
+     * could not be allocated). Any errors are communicated in the return value.
      *
-     * This method must return within 1ms if \p mayBlock is DONT_BLOCK, and
-     * within 5ms otherwise.
+     * If @p mayBlock is false, this method must not block. All parameter
+     * queries that require blocking must be skipped.
      *
-     * @param indices List of param indices for params to be queried.
+     * If @p mayBlock is true, a query may block, but the whole method call
+     * has to complete in a timely manner, or `status = TIMED_OUT` is returned.
+     *
+     * If @p mayBlock is false, this method must not block. Otherwise, this
+     * method is allowed to block for a certain period of time before completing
+     * the operation. If the operation is not completed in a timely manner,
+     * `status = TIMED_OUT` is returned.
+     *
+     * @note The order of C2Param objects in @p param does not depend on the
+     *     order of C2Param structure indices in @p indices.
+     *
+     * \par For IComponent
+     *
+     * When the object type is @ref IComponent, this method must be supported in
+     * any state except released. This call must not change the state nor the
+     * internal configuration of the component.
+     *
+     * The blocking behavior of this method differs among states:
+     *   - In the stopped state, this must be non-blocking. @p mayBlock is
+     *     ignored. (The method operates as if @p mayBlock was false.)
+     *   - In any of the running states, this method may block momentarily if
+     *     @p mayBlock is true. However, if the call cannot be completed in a
+     *     timely manner, `status = TIMED_OUT` is returned.
+     *
+     * @param indices List of C2Param structure indices to query.
      * @param mayBlock Whether this call may block or not.
      * @return status Status of the call, which may be
-     *   - OK        - All parameters could be queried.
-     *   - BAD_INDEX - All supported parameters could be queried, but some
-     *                 parameters were not supported.
-     *   - NO_MEMORY - Could not allocate memory for a supported parameter.
-     *   - BLOCKING  - Querying some parameters requires blocking.
-     *   - CORRUPTED - Some unknown error prevented the querying of the
-     *                 parameters. (unexpected)
-     * @return params List of params queried corresponding to \p indices.
+     *   - `OK`        - All parameters could be queried.
+     *   - `BAD_INDEX` - All supported parameters could be queried, but some
+     *                   parameters were not supported.
+     *   - `NO_MEMORY` - Could not allocate memory for a supported parameter.
+     *   - `BLOCKING`  - Querying some parameters requires blocking, but
+     *                   @p mayBlock is false.
+     *   - `TIMED_OUT` - The operation cannot be finished in a timely manner.
+     *   - `CORRUPTED` - Some unknown error occurred.
+     * @return params Flattened representation of C2Param objects.
+     *
+     * @sa Params.
      */
     query(
             vec<ParamIndex> indices,
@@ -64,31 +99,60 @@
         );
 
     /**
-     * Sets a set of parameters for the object. Tuning is performed at best
-     * effort: the object must update all supported configuration at best
-     * effort and skip unsupported parameters. Any errors are communicated in
-     * the return value and in \p failures.
+     * Sets a set of parameters for the object.
      *
-     * \note Parameter tuning DOES depend on the order of the tuning parameters.
-     * E.g. some parameter update may allow some subsequent parameter update.
+     * Tuning is performed at best effort: the object must update all supported
+     * configurations at best effort and skip unsupported parameters. Any errors
+     * are communicated in the return value and in @p failures.
      *
-     * This method must return within 1ms if \p mayBlock is false, and within
-     * 5ms otherwise.
+     * A non-strict parameter update with an unsupported value shall cause an
+     * update to the closest supported value. A strict parameter update with an
+     * unsupported value shall be skipped and a failure shall be returned.
+     *
+     * If @p mayBlock is false, this method must not block. An update that
+     * requires blocking shall be skipped and a failure shall be returned.
+     *
+     * If @p mayBlock is true, an update may block, but the whole method call
+     * has to complete in a timely manner, or `status = TIMED_OUT` is returned.
+     *
+     * The final values for all parameters set are propagated back to the caller
+     * in @p params.
+     *
+     * \par For IComponent
+     *
+     * When the object type is @ref IComponent, this method must be supported in
+     * any state except released.
+     *
+     * The blocking behavior of this method differs among states:
+     *   - In the stopped state, this must be non-blocking. @p mayBlock is
+     *     ignored. (The method operates as if @p mayBlock was false.)
+     *   - In any of the running states, this method may block momentarily if
+     *     @p mayBlock is true. However, if the call cannot be completed in a
+     *     timely manner, `status = TIMED_OUT` is returned.
+     *
+     * @note Parameter tuning @e does depend on the order of the tuning
+     * parameters, e.g., some parameter update may enable some subsequent
+     * parameter update.
      *
      * @param inParams Requested parameter updates.
      * @param mayBlock Whether this call may block or not.
      * @return status Status of the call, which may be
-     *   - OK        - All parameters could be updated successfully.
-     *   - BAD_INDEX - All supported parameters could be updated successfully,
-     *                 but some parameters were not supported.
-     *   - NO_MEMORY - Some supported parameters could not be updated
-     *                 successfully because they contained unsupported values.
-     *                 These are returned in \p failures.
-     *   - BLOCKING  - Setting some parameters requires blocking.
-     *   - CORRUPTED - Some unknown error prevented the update of the
-     *                 parameters. (unexpected)
-     * @return failures List of parameter failures.
-     * @return outParams Resulting values for the configured parameters.
+     *   - `OK`        - All parameters could be updated successfully.
+     *   - `BAD_INDEX` - All supported parameters could be updated successfully,
+     *                   but some parameters were not supported.
+     *   - `NO_MEMORY` - Some supported parameters could not be updated
+     *                   successfully because they contained unsupported values.
+     *                   These are returned in @p failures.
+     *   - `BLOCKING`  - Setting some parameters requires blocking, but
+     *                   @p mayBlock is false.
+     *   - `TIMED_OUT` - The operation cannot be finished in a timely manner.
+     *   - `CORRUPTED` - Some unknown error occurred.
+     * @return failures List of update failures.
+     * @return outParams Flattened representation of configured parameters. The
+     *     order of parameters in @p outParams is based on the order of
+     *     requested updates in @p inParams.
+     *
+     * @sa SettingResult.
      */
     config(
             Params inParams,
@@ -103,22 +167,19 @@
     // =========================================================================
 
     /**
-     * Returns a selected range of the set of supported parameters.
+     * Returns a list of supported parameters within a selected range of C2Param
+     * structure indices.
      *
-     * The set of supported parameters are represented in a vector with a
-     * start index of 0, and the selected range are indices into this vector.
-     * Fewer than \p count parameters are returned if the selected range is
-     * not fully/not at all part of the available vector indices.
-     *
-     * This method must return within 1ms.
-     *
-     * @param start start index of selected range
-     * @param count size of the selected
+     * @param start The first index of the selected range.
+     * @param count The length of the selected range.
      * @return status Status of the call, which may be
-     *   - OK        - The operation completed successfully.
-     *   - NO_MEMORY - Not enough memory to complete this method.
-     * @return params Vector containing the selected range of supported
-     *     parameters.
+     *   - `OK`        - The operation completed successfully.
+     *   - `NO_MEMORY` - Not enough memory to complete this method.
+     * @return params List of supported parameters in the selected range. This
+     *     list may have fewer than @p count elements if some indices in the
+     *     range are not supported.
+     *
+     * @sa ParamDescriptor.
      */
     querySupportedParams(
             uint32_t start,
@@ -131,23 +192,42 @@
     /**
      * Retrieves the supported values for the queried fields.
      *
-     * Upon return the object must fill in the supported
-     * values for the fields listed as well as a status for each field.
-     * Object shall process all fields queried even if some queries fail.
+     * The object must process all fields queried even if some queries fail.
      *
-     * This method must return within 1ms if \p mayBlock is false, and within
-     * 5ms otherwise.
+     * If @p mayBlock is false, this method must not block. Otherwise, this
+     * method is allowed to block for a certain period of time before completing
+     * the operation. If the operation cannot be completed in a timely manner,
+     * `status = TIMED_OUT` is returned.
      *
-     * @param inFields Vector of field queries.
+     * \par For IComponent
+     *
+     * When the object type is @ref IComponent, this method must be supported in
+     * any state except released.
+     *
+     * The blocking behavior of this method differs among states:
+     *   - In the stopped state, this must be non-blocking. @p mayBlock is
+     *     ignored. (The method operates as if @p mayBlock was false.)
+     *   - In any of the running states, this method may block momentarily if
+     *     @p mayBlock is true. However, if the call cannot be completed in a
+     *     timely manner, `status = TIMED_OUT` is returned.
+     *
+     * @param inFields List of field queries.
      * @param mayBlock Whether this call may block or not.
      * @return status Status of the call, which may be
-     *   - OK        - The operation completed successfully.
-     *   - BLOCKING  - Querying some parameters requires blocking.
-     *   - NO_MEMORY - Not enough memory to complete this method.
-     *   - BAD_INDEX - At least one field was not recognized as a component
-     *                 field.
-     * @return outFields Vector containing supported values and query result
-     *     for the selected fields.
+     *   - `OK`        - The operation completed successfully.
+     *   - `BLOCKING`  - Querying some parameters requires blocking, but
+     *                   @p mayBlock is false.
+     *   - `NO_MEMORY` - Not enough memory to complete this method.
+     *   - `BAD_INDEX` - At least one field was not recognized as a component
+     *                   field.
+     *   - `BLOCKING`  - Querying some fields requires blocking, but @p mayblock
+     *                   is false.
+     *   - `TIMED_OUT` - The operation cannot be finished in a timely manner.
+     *   - `CORRUPTED` - Some unknown error occurred.
+     * @return outFields List of supported values and results for the
+     *     supplied queries.
+     *
+     * @sa FieldSupportedValuesQuery, FieldSupportedValuesQueryResult.
      */
     querySupportedValues(
             vec<FieldSupportedValuesQuery> inFields,
diff --git a/media/c2/1.0/IInputSink.hal b/media/c2/1.0/IInputSink.hal
new file mode 100644
index 0000000..809c27a
--- /dev/null
+++ b/media/c2/1.0/IInputSink.hal
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.media.c2@1.0;
+
+import android.hardware.graphics.bufferqueue@1.0::IGraphicBufferProducer;
+
+import IConfigurable;
+
+/**
+ * An `IInputSink` is a receiver of work items.
+ *
+ * An @ref IComponent instance can present itself as an `IInputSink` via a thin
+ * wrapper.
+ *
+ * @sa IInputSurface, IComponent.
+ */
+interface IInputSink {
+    /**
+     * Feeds work to the sink.
+     *
+     * @param workBundle `WorkBundle` object containing a list of `Work` objects
+     *     to queue to the component.
+     * @return status Status of the call, which may be
+     *   - `OK`        - Works in @p workBundle were successfully queued.
+     *   - `BAD_INDEX` - Some component id in some `Worklet` is not valid.
+     *   - `CANNOT_DO` - Tunneling has not been set up for this sink, but some
+     *                   `Work` object contains tunneling information.
+     *   - `NO_MEMORY` - Not enough memory to queue @p workBundle.
+     *   - `TIMED_OUT` - The operation cannot be finished in a timely manner.
+     *   - `CORRUPTED` - Some unknown error occurred.
+     */
+    queue(WorkBundle workBundle) generates (Status status);
+
+    /**
+     * Returns the @ref IConfigurable instance associated to this sink.
+     *
+     * @return configurable `IConfigurable` instance. This must not be null.
+     */
+    getConfigurable() generates (IConfigurable configurable);
+};
+
diff --git a/media/c2/1.0/IInputSurface.hal b/media/c2/1.0/IInputSurface.hal
index c083a21..d11ce15 100644
--- a/media/c2/1.0/IInputSurface.hal
+++ b/media/c2/1.0/IInputSurface.hal
@@ -19,43 +19,57 @@
 import android.hardware.graphics.bufferqueue@1.0::IGraphicBufferProducer;
 
 import IConfigurable;
-import IComponent;
+import IInputSink;
 import IInputSurfaceConnection;
 
 /**
- * Input surface that can be configured for the IComponent.
+ * Input surface for a Codec2 component.
+ *
+ * An <em>input surface</em> is an instance of `IInputSurface`, which may be
+ * created by calling IComponentStore::createInputSurface(). Once created, the
+ * client may
+ *   1. write data to it via the `IGraphicBufferProducer` interface; and
+ *   2. use it as input to a Codec2 encoder.
+ *
+ * @sa IInputSurfaceConnection, IComponentStore::createInputSurface(),
+ *     IComponent::connectToInputSurface().
  */
-interface IInputSurface extends IGraphicBufferProducer {
+interface IInputSurface {
+    /**
+     * Returns the producer interface into the internal buffer queue.
+     *
+     * @return producer `IGraphicBufferProducer` instance. This must not be
+     * null.
+     */
+    getGraphicBufferProducer() generates (IGraphicBufferProducer producer);
 
     /**
-     * Connects this input surface to a component.
+     * Returns the @ref IConfigurable instance associated to this input surface.
      *
-     * This call must return within 100 ms.
-     *
-     * @param component The component to connect to. This must have type
-     *     IComponent.
-     * @return status Status of the call, which may be
-     *   - OK        - The operation succeeded.
-     *   - BAD_STATE - The component is in running state.
-     *   - DUPLICATE - The surface is already connected to a component.
-     *   - NO_MEMORY - Could not allocate memory to connect to the component.
-     *   - CORRUPTED - Some unknown error prevented the connection. (unexpected)
-     * @return connection Connection object that is used to disconnect
-     *     from the component.
+     * @return configurable `IConfigurable` instance. This must not be null.
      */
-    connectToComponent(
-            IComponent component
+    getConfigurable() generates (IConfigurable configurable);
+
+    /**
+     * Connects the input surface to an input sink.
+     *
+     * This function is generally called from inside the implementation of
+     * IComponent::connectToInputSurface(), where @p sink is a thin wrapper of
+     * the component that consumes buffers from this surface.
+     *
+     * @param sink Input sink. See `IInputSink` for more information.
+     * @return status Status of the call, which may be
+     *   - `OK`        - Configuration successful.
+     *   - `BAD_VALUE` - @p sink is invalid.
+     *   - `CORRUPTED` - Some unknown error occurred.
+     * @return connection `IInputSurfaceConnection` object. This must not be
+     *     null if @p status is `OK`.
+     */
+    connect(
+            IInputSink sink
         ) generates (
             Status status,
             IInputSurfaceConnection connection
         );
-
-    /**
-     * Returns the Codec 2.0 configuration object for this surface.
-     *
-     * @return configurable The configuration object for this surface.
-     */
-    getConfigurable() generates (IConfigurable configurable);
-
 };
 
diff --git a/media/c2/1.0/IInputSurfaceConnection.hal b/media/c2/1.0/IInputSurfaceConnection.hal
index 500091d..035b115 100644
--- a/media/c2/1.0/IInputSurfaceConnection.hal
+++ b/media/c2/1.0/IInputSurfaceConnection.hal
@@ -16,20 +16,33 @@
 
 package android.hardware.media.c2@1.0;
 
-interface IInputSurfaceConnection {
+import IConfigurable;
 
+/**
+ * Connection between a component and an input surface.
+ *
+ * An instance of `IInputSurfaceConnection` contains an `IConfigurable`
+ * interface for querying and configuring properties of the connection.
+ */
+interface IInputSurfaceConnection {
     /**
-     * Disconnects this input surface from the component.
-     *
-     * This call must return within 100 ms.
+     * Destroys the connection between an input surface and a component.
      *
      * @return status Status of the call, which may be
-     *   - OK        - The operation succeeded.
-     *   - BAD_STATE - The component is not in running state.
-     *   - NOT_FOUND - The surface is not connected to a component.
-     *   - CORRUPTED - Some unknown error prevented the connection. (unexpected)
+     *   - `OK`        - The disconnection succeeded.
+     *   - `BAD_STATE` - The component is not in running state.
+     *   - `NOT_FOUND` - The surface is not connected to a component.
+     *   - `CORRUPTED` - Some unknown error occurred.
      */
     disconnect() generates (Status status);
 
+    /**
+     * Returns the @ref IConfigurable instance associated to this connection.
+     *
+     * This can be used to customize the connection.
+     *
+     * @return configurable `IConfigurable` instance. This must not be null.
+     */
+    getConfigurable() generates (IConfigurable configurable);
 };
 
diff --git a/media/c2/1.0/types.hal b/media/c2/1.0/types.hal
index 252d781..ec422b1 100644
--- a/media/c2/1.0/types.hal
+++ b/media/c2/1.0/types.hal
@@ -18,220 +18,278 @@
 
 import android.hardware.media.bufferpool@2.0::BufferStatusMessage;
 
+/**
+ * Common return values for Codec2 operations.
+ */
 enum Status : int32_t {
-    /** operation completed successfully */
+    /** Operation completed successfully. */
     OK        = 0,
 
     // bad input
 
-    /** argument has invalid value (user error) */
+    /** Argument has invalid value (user error). */
     BAD_VALUE = -22,
-    /** argument uses invalid index (user error) */
+    /** Argument uses invalid index (user error). */
     BAD_INDEX = -75,
-    /** argument/index is valid but not possible */
+    /** Argument/Index is valid but not possible. */
     CANNOT_DO = -2147483646,
 
     // bad sequencing of events
 
-    /** object already exists */
+    /** Object already exists. */
     DUPLICATE = -17,
-    /** object not found */
+    /** Object not found. */
     NOT_FOUND = -2,
-    /** operation is not permitted in the current state */
+    /** Operation is not permitted in the current state. */
     BAD_STATE = -38,
-    /** operation would block but blocking is not permitted */
+    /** Operation would block but blocking is not permitted. */
     BLOCKING  = -9930,
 
     // bad environment
 
-    /** not enough memory to complete operation */
+    /** Not enough memory to complete operation. */
     NO_MEMORY = -12,
-    /** missing permission to complete operation */
+    /** Missing permission to complete operation. */
     REFUSED   = -1,
 
-    /** operation did not complete within timeout */
+    /** Operation did not complete within timeout. */
     TIMED_OUT = -110,
 
     // missing functionality
 
-    /** operation is not implemented/supported (optional only) */
+    /** Operation is not implemented/supported (optional only). */
     OMITTED   = -74,
 
     // unknown fatal
 
-    /** some unexpected error prevented the operation */
+    /** Some unexpected error prevented the operation. */
     CORRUPTED = -2147483648,
 
     // uninitialized
 
-    /** status has not been initialized */
+    /** Status has not been initialized. */
     NO_INIT   = -19,
 };
 
 /**
- * Codec 2.0 parameter index
+ * C2Param structure index.
+ *
+ * This is a number that is unique for each C2Param structure type.
+ *
+ * @sa Codec 2.0 standard.
  */
 typedef uint32_t ParamIndex;
 
 /**
- * Codec 2.0 parameter structure
+ * Flattened representation of C2Param objects.
  *
- * The description of a Params is provided by supplying a ParamIndex to
- * IComponentStore::getStructDescriptors().
+ * The `Params` type is an array of bytes made up by concatenating a list of
+ * C2Param objects. The start index (offset into @ref Params) of each C2Param
+ * object in the list is divisible by 8. Up to 7 padding bytes may be added
+ * after each C2Param object to achieve this 64-bit alignment.
+ *
+ * Each C2Param object has the following layout:
+ * - 4 bytes: C2Param structure index (of type @ref ParamIndex) identifying the
+ *   type of the C2Param object.
+ * - 4 bytes: size of the C2Param object (unsigned 4-byte integer).
+ * - (size - 8) bytes: data of the C2Param object.
+ *
+ * In order to interpret each C2Param object correctly, its structure must be
+ * described by IComponentStore::getStructDescriptors().
+ *
+ * @note Please refer to the Codec 2.0 standard for the list of standard
+ * parameter structures.
+ *
+ * @sa Codec 2.0 standard.
  */
 typedef vec<uint8_t> Params;
 
 /**
- * Struct uniquely specifying a field in an arbitrary parameter structure.
+ * Identifying information of a field relative to a known C2Param structure.
+ *
+ * Within a given C2Param structure, each field is uniquely identified by @ref
+ * FieldId.
  */
 struct FieldId {
-    /** Offset of the field in bytes */
+    /** Offset of the field in bytes. */
     uint32_t offset;
-    /** Size of the field in bytes */
+    /** Size of the field in bytes. */
     uint32_t size;
 };
 
 /**
- * Struct representing a location of a field in a parameter with a given index.
+ * Reference to a field in a C2Param structure.
  */
 struct ParamField {
-    /** Index of the parameter */
+    /** Index of the C2Param structure. */
     ParamIndex index;
-    /** Field identifier */
+    /** Identifier of the field inside the C2Param structure. */
     FieldId fieldId;
 };
 
 /**
- * Struct describing basic properties of a parameter with a given index.
+ * Usage description of a C2Param structure.
+ *
+ * @ref ParamDescriptor is returned by IConfigurable::querySupportedParams().
  */
 struct ParamDescriptor {
-    /** Parameter index */
+    /**
+     * Index of the C2Param structure being described.
+     */
     ParamIndex index;
 
     enum Attrib : uint32_t {
         /**
-         * Parameter is required to be specified.
+         * The parameter is required to be specified.
          */
         REQUIRED   = 1u << 0,
         /**
-         * Parameter retains its value.
+         * The parameter retains its value.
          */
         PERSISTENT = 1u << 1,
         /**
-         * Parameter is strict.
+         * The parameter is strict.
          */
         STRICT     = 1u << 2,
         /**
-         * Parameter is publicly read-only.
+         * The parameter is publicly read-only.
          */
         READ_ONLY  = 1u << 3,
         /**
-         * Parameter must not be visible to clients.
+         * The parameter must not be visible to clients.
          */
         HIDDEN     = 1u << 4,
         /**
-         * Parameter must not be used by framework (other than testing).
+         * The parameter must not be used by framework (other than testing).
          */
         INTERNAL   = 1u << 5,
         /**
-         * Parameter is publicly constant (hence read-only).
+         * The parameter is publicly constant (hence read-only).
          */
         CONST      = 1u << 6,
     };
-    /** Parameter attributes */
     bitfield<Attrib> attrib;
 
-    /** Parameter name */
+    /**
+     * Name of the structure. This must be unique for each structure.
+     */
     string name;
 
-    /** index of other parameters that this parameter depends on */
+    /**
+     * Indices of other C2Param structures that this C2Param structure depends
+     * on.
+     */
     vec<ParamIndex> dependencies;
 };
 
-// Generic way to describe supported numeric values for Codec 2.0 interfaces.
+// Generic way to describe supported numeric values for Codec2 interfaces.
 
 /**
- * An untyped value that can fit on 64 bits - the type of which is communicated
- * via a separate channel (FieldType).
+ * An untyped value that can fit in 64 bits, the type of which is communicated
+ * via a separate channel (@ref FieldSupportedValues.type).
  */
 typedef uint64_t PrimitiveValue;
 
 /*
- * Generic supported values for a field.
+ * Description of supported values for a field.
  *
- * This can be either a range or a set of values. The range can be linear or
- * geometric with clear minimum and maximum values, and can have an optional
- * step size or geometric ratio. Values can optionally represent flags.
+ * This can be a continuous range or a discrete set of values.
  */
 struct FieldSupportedValues {
+    /**
+     * Used if #type is `RANGE`.
+     *
+     * If the `step` member is 0, and `num` and `denom` are both 1, the `Range`
+     * structure represents a closed interval bounded by `min` and `max`.
+     *
+     * Otherwise, the #Range structure represents a finite sequence of numbers
+     * produced from the following recurrence relation:
+     *
+     * @code
+     * v[0] = min
+     * v[i] = v[i - 1] * num / denom + step ; i >= 1
+     * @endcode
+     *
+     * Both the ratio `num / denom` and the value `step` must be positive. The
+     * last number in the sequence described by this #Range structure is the
+     * largest number in the sequence that is smaller than or equal to `max`.
+     *
+     * @note
+     * The division in the formula may truncate the result if the data type of
+     * these values is an integral type.
+     */
     struct Range {
+        /**
+         * Lower end of the range (inclusive).
+         */
         PrimitiveValue min;
+        /**
+         * Upper end of the range (inclusive).
+         */
         PrimitiveValue max;
+        /**
+         * The non-homogeneous term in the recurrence relation.
+         */
         PrimitiveValue step;
+        /**
+         * The numerator of the scale coefficient in the recurrence relation.
+         */
         PrimitiveValue num;
+        /**
+         * The denominator of the scale coefficient in the recurrence relation.
+         */
         PrimitiveValue denom;
     };
 
     enum Type : int32_t {
         /** No supported values */
-        EMPTY,
-        /** Numeric range that can be continuous or discrete */
+        EMPTY = 0,
+        /** Numeric range, described in a #Range structure */
         RANGE,
         /** List of values */
         VALUES,
         /** List of flags that can be OR-ed */
         FLAGS,
-        /** Other representations */
-        OTHER = 0xffffffff,
     };
     /**
-     * Type of the supported values. The framework may not recognize `OTHER`.
+     * Type of the supported values.
      */
     Type type;
-    /**
-     * Codec2.0 type code of the supported values.
-     *   * If #type is `OTHER`, #typeOther can be used to give more information.
-     *     In this case, the interpretation of this structure is
-     *     implementation-defined.
-     *   * For all other values of #type, #typeOther is not used.
-     * The framework may not inspect this value.
-     */
-    int32_t typeOther;
-
-    /*
-     * If #type = EMPTY, #range and #value are unused.
-     */
 
     /**
-     * If #type = RANGE, #range will specify the range of possible values.
+     * When #type is #Type.RANGE, #range shall specify the range of possible
+     * values.
      *
-     * The intended type of members of #range will be clear in the context where
-     * FieldSupportedValues is used.
+     * The intended type of members of #range shall be clear in the context
+     * where `FieldSupportedValues` is used.
      */
     Range range;
 
     /**
-     * If #type is `VALUES` or `FLAGS`, #value will list supported values.
+     * When #type is #Type.VALUES or #Type.FLAGS, #value shall list supported
+     * values/flags.
      *
-     * The intended type of components of #value will be clear in the context
-     * where FieldSupportedValues is used.
+     * The intended type of components of #value shall be clear in the context
+     * where `FieldSupportedValues` is used.
      */
     vec<PrimitiveValue> values;
 };
 
 /**
- * Supported values for a specific field.
+ * Supported values for a field.
  *
  * This is a pair of the field specifier together with an optional supported
  * values object. This structure is used when reporting parameter configuration
  * failures and conflicts.
  */
 struct ParamFieldValues {
-    /** the field or parameter */
+    /**
+     * Reference to a field or a C2Param structure.
+     */
     ParamField paramOrField;
 
     /**
-     * optional supported values for the field if paramOrField specifies an
+     * Optional supported values for the field if #paramOrField specifies an
      * actual field that is numeric (non struct, blob or string). Supported
      * values for arrays (including string and blobs) describe the supported
      * values for each element (character for string, and bytes for blobs). It
@@ -241,18 +299,18 @@
 };
 
 /**
- * Field descriptor.
+ * Description of a field inside a C2Param structure.
  */
 struct FieldDescriptor {
 
-    /** Field id */
+    /** Location of the field in the C2Param structure */
     FieldId fieldId;
 
     /**
-     * Possible types of a field.
+     * Possible types of the field.
      */
     enum Type : uint32_t {
-        NO_INIT,
+        NO_INIT = 0,
         INT32,
         UINT32,
         CNTR32,
@@ -261,186 +319,227 @@
         CNTR64,
         FLOAT,
         /**
-         * Fixed-size string (POD)
+         * Fixed-size string (POD).
          */
         STRING = 0x100,
         /**
-         * blobs have no sub-elements and can be thought of as byte arrays.
-         * However, bytes cannot be individually addressed by clients.
+         * A blob has no sub-elements and can be thought of as an array of
+         * bytes. However, bytes cannot be individually addressed by clients.
          */
         BLOB,
         /**
-         * Structs. Marked with this flag in addition to their coreIndex.
+         * The field is a structure that may contain other fields.
          */
-        STRUCT_FLAG = 0x20000,
+        STRUCT = 0x20000,
     };
     /**
      * Type of the field.
      */
     bitfield<Type> type;
 
-    /** Extent of the field */
-    uint32_t length;
-    /*
-     * Note: the last member of a param struct can be of arbitrary length (e.g.
-     * if it is T[] array, which extends to the last byte of the parameter.)
-     * This is marked with extent 0.
+    /**
+     * If #type is #Type.STRUCT, #structIndex is the C2Param structure index;
+     * otherwise, #structIndex is not used.
      */
+    ParamIndex structIndex;
 
-    /** Name of the field */
+    /**
+     * Extent of the field.
+     * - For a non-array field, #extent is 1.
+     * - For a fixed-length array field, #extent is the length. An array field
+     *   of length 1 is indistinguishable from a non-array field.
+     * - For a variable-length array field, #extent is 0. This can only occur as
+     *   the last member of a C2Param structure.
+     */
+    uint32_t extent;
+
+    /**
+     * Name of the field. This must be unique for each field in the same
+     * structure.
+     */
     string name;
-    /** Named value type */
+
+    /**
+     * Named value type. This is used for defining an enum value for a numeric
+     * type.
+     */
     struct NamedValue {
+        /**
+         * Name of the enum value. This must be unique for each enum value in
+         * the same field.
+         */
         string name;
+        /**
+         * Underlying value of the enum value. Multiple enum names may have the
+         * same underlying value.
+         */
         PrimitiveValue value;
     };
-    /** Named values for the field */
+    /**
+     * List of enum values. This is not used when #type is not one of the
+     * numeric types.
+     */
     vec<NamedValue> namedValues;
 };
 
 /**
- * Struct descriptor.
+ * Description of a C2Param structure. It consists of an index and a list of
+ * `FieldDescriptor`s.
  */
 struct StructDescriptor {
-    /** Struct type */
+    /**
+     * Index of the structure.
+     */
     ParamIndex type;
-    /** Field descriptors for each field */
+    /**
+     * List of fields in the structure.
+     *
+     * Fields are ordered by their offsets. A field that is a structure is
+     * ordered before its members.
+     */
     vec<FieldDescriptor> fields;
 };
 
 /**
- * Information describing the reason a parameter settings may fail, or
- * may be overriden.
+ * Information describing the reason the parameter settings may fail, or may be
+ * overridden.
  */
 struct SettingResult {
-    /** Failure code (of Codec 2.0 SettingResult failure type) */
+    /** Failure code */
     enum Failure : uint32_t {
-        /** Parameter is read-only and cannot be set. */
-        READ_ONLY,
-        /** Parameter mismatches input data. */
-        MISMATCH,
-        /** Parameter does not accept value. */
-        BAD_VALUE,
         /** Parameter is not supported. */
         BAD_TYPE,
         /** Parameter is not supported on the specific port. */
         BAD_PORT,
         /** Parameter is not supported on the specific stream. */
         BAD_INDEX,
-        /** Parameter is in conflict with an/other setting(s). */
+        /** Parameter is read-only and cannot be set. */
+        READ_ONLY,
+        /** Parameter mismatches input data. */
+        MISMATCH,
+        /** Strict parameter does not accept value for the field at all. */
+        BAD_VALUE,
+        /**
+         * Strict parameter field value is in conflict with an/other
+         * setting(s).
+         */
         CONFLICT,
         /**
-         * Parameter is out of range due to other settings. (This failure mode
-         * can only be used for strict parameters.)
+         * Parameter field is out of range due to other settings. (This failure
+         * mode can only be used for strict calculated parameters.)
          */
         UNSUPPORTED,
         /**
+         * Field does not access the requested parameter value at all. It has
+         * been corrected to the closest supported value. This failure mode is
+         * provided to give guidance as to what are the currently supported
+         * values for this field (which may be a subset of the at-all-potential
+         * values).
+         */
+        INFO_BAD_VALUE,
+        /**
          * Requested parameter value is in conflict with an/other setting(s)
          * and has been corrected to the closest supported value. This failure
-         * mode is given to provide suggestion to the client as to how to enable
-         * the requested parameter value. */
-        INFO_CONFLICT,
-        /**
-         * This failure mode is reported when all the above failure modes do not
-         * apply.
+         * mode is given to provide guidance as to what are the currently
+         * supported values as well as to optionally provide suggestion to the
+         * client as to how to enable the requested parameter value.
          */
-        OTHER = 0xffffffff,
+        INFO_CONFLICT,
     };
-    /**
-     * The failure type. The framework might not recognize `OTHER`.
-     */
     Failure failure;
-    /**
-     * The failure code.
-     *   * If #failure is `OTHER`, #failureOther can be used to give more
-     *     information.
-     *   * For all other values of #failure, #failureOther is not used.
-     * The framework may not inspect this value.
-     */
-    uint32_t failureOther;
 
     /**
-     * Failing (or corrected) field. Currently supported values for the field.
-     * This is set if different from the globally supported values (e.g. due to
-     * restrictions by another param or input data)
+     * Failing (or corrected) field or parameter and optionally, currently
+     * supported values for the field. Values must only be set for field
+     * failures other than `BAD_VALUE`, and only if they are different from the
+     * globally supported values (e.g. due to restrictions by another parameter
+     * or input data).
      */
     ParamFieldValues field;
 
     /**
-     * Conflicting parameters or fields with
-     * (optional) suggested values for any conflicting fields to avoid the conflict.
+     * Conflicting parameters or fields with (optional) suggested values for any
+     * conflicting fields to avoid the conflict. Values must only be set for
+     * `CONFLICT`, `UNSUPPORTED` or `INFO_CONFLICT` failure code.
      */
     vec<ParamFieldValues> conflicts;
 };
 
 /**
- * Data structure for ordering Work objects. Each member is used for comparing
- * urgency in the same fashion: a smaller value indicates that the associated
- * Work object is more urgent.
+ * Ordering information of @ref FrameData objects. Each member is used for
+ * comparing urgency: a smaller difference from a reference value indicates that
+ * the associated Work object is more urgent. The reference value for each
+ * member is initialized the first time it is communicated between the client
+ * and the codec, and it may be updated to later values that are communicated.
+ *
+ * Each member of `WorkOrdinal` is stored as an unsigned integer, but the actual
+ * order it represents is derived by subtracting the reference value, then
+ * interpreting the result as a signed number with the same storage size (using
+ * two's complement).
+ *
+ * @note `WorkOrdinal` is the HIDL counterpart of `C2WorkOrdinalStruct` in the
+ * Codec 2.0 standard.
  */
 struct WorkOrdinal {
     /**
-     * Timestamp in microseconds - can wrap around.
+     * Timestamp in microseconds.
      */
     uint64_t timestampUs;
     /**
-     * Frame index - can wrap around.
+     * Frame index.
      */
     uint64_t frameIndex;
     /**
-     * Component specific frame ordinal - can wrap around.
+     * Component specific frame ordinal.
      */
     uint64_t customOrdinal;
 };
 
 /**
- * A structure that holds information of a Block. There are two types of Blocks:
- * NATIVE and POOLED. Each type has its own way of identifying blocks.
+ * Storage type for `BaseBlock`.
+ *
+ * A `BaseBlock` is a representation of a codec memory block. Coded data,
+ * decoded data, codec-specific data, and other codec-related data are all sent
+ * in the form of BaseBlocks.
  */
-struct BaseBlock {
-    enum Type : int32_t {
-        NATIVE,
-        POOLED,
-    };
+safe_union BaseBlock {
     /**
-     * There are two types of blocks: NATIVE and POOLED.
-     */
-    Type type;
-
-    /**
-     * A "NATIVE" block is represented by a native handle.
+     * #nativeBlock is the opaque representation of a buffer.
      */
     handle nativeBlock;
-
-    /*
-     * A "POOLED" block is represented by `BufferStatusMessage`.
+    /**
+     * #pooledBlock is a reference to a buffer handled by a BufferPool.
      */
     BufferStatusMessage pooledBlock;
 };
 
 /**
- * A Block in transfer consists of an index into an array of BaseBlock plus some
- * extra information. One BaseBlock may occur in multiple blocks in one
- * `WorkBundle`.
+ * Reference to a @ref BaseBlock within a @ref WorkBundle.
+ *
+ * `Block` contains additional attributes that `BaseBlock` does not. These
+ * attributes may differ among `Block` objects that refer to the same
+ * `BaseBlock` in the same `WorkBundle`.
  */
 struct Block {
     /**
-     * Identity of the BaseBlock within a WorkBundle. This is an index into the
-     * `baseBlocks` array of a `WorkBundle` object.
+     * Identity of a `BaseBlock` within a `WorkBundle`. This is an index into
+     * #WorkBundle.baseBlocks.
      */
     uint32_t index;
     /**
-     * Metadata associated with the block.
+     * Metadata associated with this `Block`.
      */
     Params meta;
     /**
-     * Fence for synchronizing block access.
+     * Fence for synchronizing `Block` access.
      */
     handle fence;
 };
 
 /**
- * Type of buffers processed by a component.
+ * A codec buffer, which is a collection of @ref Block objects and metadata.
+ *
+ * This is a part of @ref FrameData.
  */
 struct Buffer {
     /**
@@ -454,23 +553,37 @@
 };
 
 /**
- * An extension of Buffer that also contains an index.
+ * An extension of @ref Buffer that also contains a C2Param structure index.
+ *
+ * This is a part of @ref FrameData.
  */
 struct InfoBuffer {
+    /**
+     * A C2Param structure index.
+     */
     ParamIndex index;
+    /**
+     * Associated @ref Buffer object.
+     */
     Buffer buffer;
 };
 
 /**
- * This structure represents a frame with its metadata. A frame consists of an
- * ordered set of buffers, configuration changes, and info buffers along with
- * some non-configuration metadata.
+ * Data for an input frame or an output frame.
+ *
+ * This structure represents a @e frame with its metadata. A @e frame consists
+ * of an ordered set of buffers, configuration changes, and info buffers along
+ * with some non-configuration metadata.
+ *
+ * @note `FrameData` is the HIDL counterpart of `C2FrameData` in the Codec 2.0
+ * standard.
  */
 struct FrameData {
     enum Flags : uint32_t {
         /**
-         * For input frames: no output frame will be generated when processing
+         * For input frames: no output frame shall be generated when processing
          * this frame, but metadata must still be processed.
+         *
          * For output frames: this frame must be discarded but metadata is still
          * valid.
          */
@@ -482,92 +595,178 @@
         END_OF_STREAM = (1 << 1),
         /**
          * This frame must be discarded with its metadata.
-         * This flag is only set by components - e.g. as a response to the flush
+         *
+         * This flag is only set by components, e.g. as a response to the flush
          * command.
          */
         DISCARD_FRAME = (1 << 2),
         /**
+         * This frame is not the last frame produced for the input.
+         *
+         * This flag is normally set by the component - e.g. when an input frame
+         * results in multiple output frames, this flag is set on all but the
+         * last output frame.
+         *
+         * Also, when components are chained, this flag should be propagated
+         * down the work chain. That is, if set on an earlier frame of a
+         * work-chain, it should be propagated to all later frames in that
+         * chain. Additionally, components down the chain could set this flag
+         * even if not set earlier, e.g. if multiple output frames are generated
+         * at that component for the input frame.
+         */
+        FLAG_INCOMPLETE = (1 << 3),
+        /**
          * This frame contains only codec-specific configuration data, and no
          * actual access unit.
          *
-         * \deprecated Pass codec configuration with the codec-specific
+         * @deprecated Pass codec configuration with the codec-specific
          * configuration info together with the access unit.
          */
         CODEC_CONFIG  = (1u << 31),
     };
 
     /**
-     * Frame flags.
+     * Frame flags, as described in #Flags.
      */
     bitfield<Flags> flags;
 
     /**
-     * Ordinal of the frame.
+     * @ref WorkOrdinal of the frame.
      */
     WorkOrdinal ordinal;
 
     /**
-     * Frame buffers.
+     * List of frame buffers.
      */
     vec<Buffer> buffers;
 
     /**
-     * Params determining a configuration update.
+     * List of configuration updates.
      */
     Params configUpdate;
 
     /**
-     * Info buffers.
+     * List of info buffers.
      */
     vec<InfoBuffer> infoBuffers;
 };
 
 /**
- * Struct for
+ * In/out structure containing some instructions for and results from output
+ * processing.
+ *
+ * This is a part of @ref Work. One `Worklet` corresponds to one output
+ * @ref FrameData. The client must construct an original `Worklet` object inside
+ * a @ref Work object for each expected output before calling
+ * IComponent::queue().
  */
 struct Worklet {
     /**
-     * List of Params describing tunings.
+     * Component id. (Input)
+     *
+     * This is used only when tunneling is enabled.
+     *
+     * When used, this must match the return value from IConfigurable::getId().
      */
-    vec<Params> tunings;
+    uint32_t componentId;
 
     /**
-     * List of failures.
+     * List of C2Param objects describing tunings to be applied before
+     * processing this `Worklet`. (Input)
+     */
+    Params tunings;
+
+    /**
+     * List of failures. (Output)
      */
     vec<SettingResult> failures;
 
     /**
-     * Output frame data.
+     * Output frame data. (Output)
      */
     FrameData output;
-
-    /* Note: Component id is not necessary as tunneling is not supported. */
 };
 
 /**
- * This structure holds information about a single work item. It must be passed
- * by the client to the component.
+ * A collection of input data to and output data from the component.
+ *
+ * A `Work` object holds information about a single work item. It is created by
+ * the client and passed to the component via IComponent::queue(). The component
+ * has two ways of returning a `Work` object to the client:
+ *   1. If the queued `Work` object has been successfully processed,
+ *      IComponentListener::onWorkDone() shall be called to notify the listener,
+ *      and the output shall be included in the returned `Work` object.
+ *   2. If the client calls IComponent::flush(), a `Work` object that has not
+ *      been processed shall be returned.
+ *
+ * `Work` is a part of @ref WorkBundle.
  */
 struct Work {
     /**
-     * FrameData for the input. Indices of Blocks inside #input refer to
-     * BaseBlocks in the member `blocks` of the containing `WorkBundle`.
+     * Additional work chain info not part of this work.
+     */
+    Params chainInfo;
+
+    /**
+     * @ref FrameData for the input.
      */
     FrameData input;
+
     /**
-     * Worklet. Indices of Blocks inside `worklet.output` refer to
-     * BaseBlocks in the member `blocks` of the containing `WorkBundle`.
+     * The chain of `Worklet`s.
+     *
+     * The length of #worklets is 1 when tunneling is not enabled.
+     *
+     * If #worklets has more than a single element, the tunnels between
+     * successive components of the work chain must have been successfully
+     * pre-registered at the time that the `Work` is submitted. Allocating the
+     * output buffers in the `Worklet`s is the responsibility of each component
+     * in the chain.
+     *
+     * Upon `Work` submission, #worklets must be an appropriately sized vector
+     * containing `Worklet`s with @ref Worklet.hasOutput set to `false`. After a
+     * successful processing, all but the final `Worklet` in the returned
+     * #worklets must have @ref Worklet.hasOutput set to `false`.
      */
-    Worklet worklet;
+    vec<Worklet> worklets;
+
     /**
-     * Whether the worklet was processed or not.
+     * The number of `Worklet`s successfully processed in this chain.
+     *
+     * This must be initialized to 0 by the client when the `Work` is submitted,
+     * and it must contain the number of `Worklet`s that were successfully
+     * processed when the `Work` is returned to the client.
+     *
+     * #workletsProcessed cannot exceed the length of #worklets. If
+     * #workletsProcessed is smaller than the length of #worklets, #result
+     * cannot be `OK`.
      */
-    bool workletProcessed;
+    uint32_t workletsProcessed;
+
+    /**
+     * The final outcome of the `Work` (corresponding to #workletsProcessed).
+     *
+     * The value of @ref Status.OK implies that all `Worklet`s have been
+     * successfully processed.
+     */
     Status result;
 };
 
 /**
- * This structure holds a list of Work objects and a list of BaseBlocks.
+ * List of `Work` objects.
+ *
+ * `WorkBundle` is used in IComponent::queue(), IComponent::flush() and
+ * IComponentListener::onWorkDone(). A `WorkBundle` object consists of a list of
+ * `Work` objects and a list of `BaseBlock` objects. Bundling multiple `Work`
+ * objects together provides two benefits:
+ *   1. Batching of `Work` objects can reduce the number of IPC calls.
+ *   2. If multiple `Work` objects contain `Block`s that refer to the same
+ *      `BaseBlock`, the number of `BaseBlock`s that is sent between processes
+ *      is also reduced.
+ *
+ * @note `WorkBundle` is the HIDL counterpart of the vector of `C2Work` in the
+ * Codec 2.0 standard. The presence of #baseBlocks helps with minimizing the
+ * data transferred over an IPC.
  */
 struct WorkBundle {
     /**
@@ -581,27 +780,48 @@
 };
 
 /**
- * This structure describes a query for supported values of a field. This is
- * used as input to IConfigurable::queryFieldSupportedValues().
+ * Query information for supported values of a field. This is used as input to
+ * IConfigurable::querySupportedValues().
  */
 struct FieldSupportedValuesQuery {
+    /**
+     * Identity of the field to query.
+     */
+    ParamField field;
+
     enum Type : uint32_t {
-        /** Query all possible values regardless of other settings */
+        /** Query all possible values regardless of other settings. */
         POSSIBLE,
-        /** Query currently possible values given dependent settings */
+        /** Query currently possible values given dependent settings. */
         CURRENT,
     };
-
-    ParamField field;
+    /**
+     * Type of the query. See #Type for more information.
+     */
     Type type;
 };
 
 /**
  * This structure is used to hold the result from
- * IConfigurable::queryFieldSupportedValues().
+ * IConfigurable::querySupportedValues().
  */
 struct FieldSupportedValuesQueryResult {
+    /**
+     * Result of the query. Possible values are
+     * - `OK`: The query was successful.
+     * - `BAD_STATE`: The query was requested when the `IConfigurable` instance
+     *   was in a bad state.
+     * - `BAD_INDEX`: The requested field was not recognized.
+     * - `TIMED_OUT`: The query could not be completed in a timely manner.
+     * - `BLOCKING`: The query must block, but the parameter `mayBlock` in the
+     *   call to `querySupportedValues()` was `false`.
+     * - `CORRUPTED`: Some unknown error occurred.
+     */
     Status status;
+
+    /**
+     * Supported values. This is meaningful only when #status is `OK`.
+     */
     FieldSupportedValues values;
 };
 
diff --git a/neuralnetworks/1.0/vts/functional/Android.bp b/neuralnetworks/1.0/vts/functional/Android.bp
index 2920cec..52d6328 100644
--- a/neuralnetworks/1.0/vts/functional/Android.bp
+++ b/neuralnetworks/1.0/vts/functional/Android.bp
@@ -23,6 +23,7 @@
     defaults: ["VtsHalTargetTestDefaults"],
     export_include_dirs: ["."],
     shared_libs: [
+        "libfmq",
         "libnativewindow",
     ],
     static_libs: [
@@ -51,6 +52,7 @@
         "VtsHalNeuralnetworks.cpp",
     ],
     shared_libs: [
+        "libfmq",
         "libnativewindow",
     ],
     static_libs: [
diff --git a/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.cpp b/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.cpp
index 65c425e..2e13854 100644
--- a/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.cpp
+++ b/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.cpp
@@ -14,7 +14,9 @@
  * limitations under the License.
  */
 
+#include "GeneratedTestHarness.h"
 #include "Callbacks.h"
+#include "ExecutionBurstController.h"
 #include "TestHarness.h"
 #include "Utils.h"
 
@@ -109,14 +111,24 @@
     }
     return result;
 }
-enum class Synchronously { NO, YES };
+static std::unique_ptr<::android::nn::ExecutionBurstController> CreateBurst(
+        const sp<V1_0::IPreparedModel>&) {
+    ADD_FAILURE() << "asking for burst execution at V1_0";
+    return nullptr;
+}
+static std::unique_ptr<::android::nn::ExecutionBurstController> CreateBurst(
+        const sp<V1_2::IPreparedModel>& preparedModel) {
+    return ::android::nn::createExecutionBurstController(preparedModel, /*blocking=*/true);
+}
+enum class Executor { ASYNC, SYNC, BURST };
+enum class OutputType { FULLY_SPECIFIED, UNSPECIFIED, INSUFFICIENT };
 const float kDefaultAtol = 1e-5f;
 const float kDefaultRtol = 1e-5f;
 template <typename T_IPreparedModel>
 void EvaluatePreparedModel(sp<T_IPreparedModel>& preparedModel, std::function<bool(int)> is_ignored,
                            const std::vector<MixedTypedExample>& examples,
                            bool hasRelaxedFloat32Model, float fpAtol, float fpRtol,
-                           Synchronously sync, MeasureTiming measure, bool testDynamicOutputShape) {
+                           Executor executor, MeasureTiming measure, OutputType outputType) {
     const uint32_t INPUT = 0;
     const uint32_t OUTPUT = 1;
 
@@ -164,8 +176,20 @@
 
         // Go through all outputs, initialize RequestArgument descriptors
         resize_accordingly(golden, test);
-        for_all(golden, [&outputs_info, &outputSize](int index, auto, auto s) {
+        bool sizeLargerThanOne = true;
+        for_all(golden, [&outputs_info, &outputSize, &outputType, &sizeLargerThanOne](
+                                int index, auto, auto s) {
             if (outputs_info.size() <= static_cast<size_t>(index)) outputs_info.resize(index + 1);
+            if (index == 0) {
+                // On OutputType::INSUFFICIENT, set the output operand with index 0 with
+                // buffer size one byte less than needed.
+                if (outputType == OutputType::INSUFFICIENT) {
+                    if (s > 1)
+                        s -= 1;
+                    else
+                        sizeLargerThanOne = false;
+                }
+            }
             RequestArgument arg = {
                 .location = {.poolIndex = OUTPUT, .offset = 0, .length = static_cast<uint32_t>(s)},
                 .dimensions = {},
@@ -173,6 +197,9 @@
             outputs_info[index] = arg;
             outputSize += s;
         });
+        // If output0 does not have size larger than one byte,
+        // we can not provide an insufficient buffer
+        if (!sizeLargerThanOne && outputType == OutputType::INSUFFICIENT) return;
         // Compute offset for outputs 1 and so on
         {
             size_t offset = 0;
@@ -209,46 +236,73 @@
         inputMemory->commit();
         outputMemory->commit();
 
+        const Request request = {.inputs = inputs_info, .outputs = outputs_info, .pools = pools};
+
         ErrorStatus executionStatus;
         hidl_vec<OutputShape> outputShapes;
         Timing timing;
-        if (sync == Synchronously::NO) {
-            SCOPED_TRACE("asynchronous");
+        switch (executor) {
+            case Executor::ASYNC: {
+                SCOPED_TRACE("asynchronous");
 
-            // launch execution
-            sp<ExecutionCallback> executionCallback = new ExecutionCallback();
-            ASSERT_NE(nullptr, executionCallback.get());
-            Return<ErrorStatus> executionLaunchStatus = ExecutePreparedModel(
-                    preparedModel, {.inputs = inputs_info, .outputs = outputs_info, .pools = pools},
-                    measure, executionCallback);
-            ASSERT_TRUE(executionLaunchStatus.isOk());
-            EXPECT_EQ(ErrorStatus::NONE, static_cast<ErrorStatus>(executionLaunchStatus));
+                // launch execution
+                sp<ExecutionCallback> executionCallback = new ExecutionCallback();
+                ASSERT_NE(nullptr, executionCallback.get());
+                Return<ErrorStatus> executionLaunchStatus =
+                        ExecutePreparedModel(preparedModel, request, measure, executionCallback);
+                ASSERT_TRUE(executionLaunchStatus.isOk());
+                EXPECT_EQ(ErrorStatus::NONE, static_cast<ErrorStatus>(executionLaunchStatus));
 
-            // retrieve execution status
-            executionCallback->wait();
-            executionStatus = executionCallback->getStatus();
-            outputShapes = executionCallback->getOutputShapes();
-            timing = executionCallback->getTiming();
-        } else {
-            SCOPED_TRACE("synchronous");
+                // retrieve execution status
+                executionCallback->wait();
+                executionStatus = executionCallback->getStatus();
+                outputShapes = executionCallback->getOutputShapes();
+                timing = executionCallback->getTiming();
 
-            // execute
-            Return<ErrorStatus> executionReturnStatus = ExecutePreparedModel(
-                    preparedModel, {.inputs = inputs_info, .outputs = outputs_info, .pools = pools},
-                    measure, &outputShapes, &timing);
-            ASSERT_TRUE(executionReturnStatus.isOk());
-            executionStatus = static_cast<ErrorStatus>(executionReturnStatus);
+                break;
+            }
+            case Executor::SYNC: {
+                SCOPED_TRACE("synchronous");
+
+                // execute
+                Return<ErrorStatus> executionReturnStatus = ExecutePreparedModel(
+                        preparedModel, request, measure, &outputShapes, &timing);
+                ASSERT_TRUE(executionReturnStatus.isOk());
+                executionStatus = static_cast<ErrorStatus>(executionReturnStatus);
+
+                break;
+            }
+            case Executor::BURST: {
+                SCOPED_TRACE("burst");
+
+                // create burst
+                const std::unique_ptr<::android::nn::ExecutionBurstController> controller =
+                        CreateBurst(preparedModel);
+                ASSERT_NE(nullptr, controller.get());
+
+                // create memory keys
+                std::vector<intptr_t> keys(request.pools.size());
+                for (size_t i = 0; i < keys.size(); ++i) {
+                    keys[i] = reinterpret_cast<intptr_t>(&request.pools[i]);
+                }
+
+                // execute burst
+                std::tie(executionStatus, outputShapes, timing) =
+                        controller->compute(request, measure, keys);
+
+                break;
+            }
         }
 
-        if (testDynamicOutputShape && executionStatus != ErrorStatus::NONE) {
+        if (outputType != OutputType::FULLY_SPECIFIED &&
+            executionStatus == ErrorStatus::GENERAL_FAILURE) {
             LOG(INFO) << "NN VTS: Early termination of test because vendor service cannot "
                          "execute model that it does not support.";
             std::cout << "[          ]   Early termination of test because vendor service cannot "
                          "execute model that it does not support."
                       << std::endl;
-            return;
+            GTEST_SKIP();
         }
-        ASSERT_EQ(ErrorStatus::NONE, executionStatus);
         if (measure == MeasureTiming::NO) {
             EXPECT_EQ(UINT64_MAX, timing.timeOnDevice);
             EXPECT_EQ(UINT64_MAX, timing.timeInDriver);
@@ -258,9 +312,28 @@
             }
         }
 
+        switch (outputType) {
+            case OutputType::FULLY_SPECIFIED:
+                // If the model output operands are fully specified, outputShapes must be either
+                // either empty, or have the same number of elements as the number of outputs.
+                ASSERT_EQ(ErrorStatus::NONE, executionStatus);
+                ASSERT_TRUE(outputShapes.size() == 0 ||
+                            outputShapes.size() == test.operandDimensions.size());
+                break;
+            case OutputType::UNSPECIFIED:
+                // If the model output operands are not fully specified, outputShapes must have
+                // the same number of elements as the number of outputs.
+                ASSERT_EQ(ErrorStatus::NONE, executionStatus);
+                ASSERT_EQ(outputShapes.size(), test.operandDimensions.size());
+                break;
+            case OutputType::INSUFFICIENT:
+                ASSERT_EQ(ErrorStatus::OUTPUT_INSUFFICIENT_SIZE, executionStatus);
+                ASSERT_EQ(outputShapes.size(), test.operandDimensions.size());
+                ASSERT_FALSE(outputShapes[0].isSufficient);
+                return;
+        }
         // Go through all outputs, overwrite output dimensions with returned output shapes
-        if (testDynamicOutputShape) {
-            ASSERT_NE(outputShapes.size(), 0);
+        if (outputShapes.size() > 0) {
             for_each<uint32_t>(test.operandDimensions,
                                [&outputShapes](int idx, std::vector<uint32_t>& dim) {
                                    dim = outputShapes[idx].dimensions;
@@ -286,10 +359,55 @@
 template <typename T_IPreparedModel>
 void EvaluatePreparedModel(sp<T_IPreparedModel>& preparedModel, std::function<bool(int)> is_ignored,
                            const std::vector<MixedTypedExample>& examples,
-                           bool hasRelaxedFloat32Model, Synchronously sync, MeasureTiming measure,
-                           bool testDynamicOutputShape) {
+                           bool hasRelaxedFloat32Model, Executor executor, MeasureTiming measure,
+                           OutputType outputType) {
     EvaluatePreparedModel(preparedModel, is_ignored, examples, hasRelaxedFloat32Model, kDefaultAtol,
-                          kDefaultRtol, sync, measure, testDynamicOutputShape);
+                          kDefaultRtol, executor, measure, outputType);
+}
+
+void EvaluatePreparedModel(sp<V1_2::IPreparedModel>& preparedModel,
+                           std::function<bool(int)> is_ignored,
+                           const std::vector<MixedTypedExample>& examples,
+                           bool hasRelaxedFloat32Model, bool testDynamicOutputShape) {
+    if (testDynamicOutputShape) {
+        EvaluatePreparedModel(preparedModel, is_ignored, examples, hasRelaxedFloat32Model,
+                              Executor::ASYNC, MeasureTiming::NO, OutputType::UNSPECIFIED);
+        EvaluatePreparedModel(preparedModel, is_ignored, examples, hasRelaxedFloat32Model,
+                              Executor::SYNC, MeasureTiming::NO, OutputType::UNSPECIFIED);
+        EvaluatePreparedModel(preparedModel, is_ignored, examples, hasRelaxedFloat32Model,
+                              Executor::BURST, MeasureTiming::NO, OutputType::UNSPECIFIED);
+        EvaluatePreparedModel(preparedModel, is_ignored, examples, hasRelaxedFloat32Model,
+                              Executor::ASYNC, MeasureTiming::YES, OutputType::UNSPECIFIED);
+        EvaluatePreparedModel(preparedModel, is_ignored, examples, hasRelaxedFloat32Model,
+                              Executor::SYNC, MeasureTiming::YES, OutputType::UNSPECIFIED);
+        EvaluatePreparedModel(preparedModel, is_ignored, examples, hasRelaxedFloat32Model,
+                              Executor::BURST, MeasureTiming::YES, OutputType::UNSPECIFIED);
+        EvaluatePreparedModel(preparedModel, is_ignored, examples, hasRelaxedFloat32Model,
+                              Executor::ASYNC, MeasureTiming::NO, OutputType::INSUFFICIENT);
+        EvaluatePreparedModel(preparedModel, is_ignored, examples, hasRelaxedFloat32Model,
+                              Executor::SYNC, MeasureTiming::NO, OutputType::INSUFFICIENT);
+        EvaluatePreparedModel(preparedModel, is_ignored, examples, hasRelaxedFloat32Model,
+                              Executor::BURST, MeasureTiming::NO, OutputType::INSUFFICIENT);
+        EvaluatePreparedModel(preparedModel, is_ignored, examples, hasRelaxedFloat32Model,
+                              Executor::ASYNC, MeasureTiming::YES, OutputType::INSUFFICIENT);
+        EvaluatePreparedModel(preparedModel, is_ignored, examples, hasRelaxedFloat32Model,
+                              Executor::SYNC, MeasureTiming::YES, OutputType::INSUFFICIENT);
+        EvaluatePreparedModel(preparedModel, is_ignored, examples, hasRelaxedFloat32Model,
+                              Executor::BURST, MeasureTiming::YES, OutputType::INSUFFICIENT);
+    } else {
+        EvaluatePreparedModel(preparedModel, is_ignored, examples, hasRelaxedFloat32Model,
+                              Executor::ASYNC, MeasureTiming::NO, OutputType::FULLY_SPECIFIED);
+        EvaluatePreparedModel(preparedModel, is_ignored, examples, hasRelaxedFloat32Model,
+                              Executor::SYNC, MeasureTiming::NO, OutputType::FULLY_SPECIFIED);
+        EvaluatePreparedModel(preparedModel, is_ignored, examples, hasRelaxedFloat32Model,
+                              Executor::BURST, MeasureTiming::NO, OutputType::FULLY_SPECIFIED);
+        EvaluatePreparedModel(preparedModel, is_ignored, examples, hasRelaxedFloat32Model,
+                              Executor::ASYNC, MeasureTiming::YES, OutputType::FULLY_SPECIFIED);
+        EvaluatePreparedModel(preparedModel, is_ignored, examples, hasRelaxedFloat32Model,
+                              Executor::SYNC, MeasureTiming::YES, OutputType::FULLY_SPECIFIED);
+        EvaluatePreparedModel(preparedModel, is_ignored, examples, hasRelaxedFloat32Model,
+                              Executor::BURST, MeasureTiming::YES, OutputType::FULLY_SPECIFIED);
+    }
 }
 
 static void getPreparedModel(sp<PreparedModelCallback> callback,
@@ -338,15 +456,15 @@
         std::cout << "[          ]   Early termination of test because vendor service cannot "
                      "prepare model that it does not support."
                   << std::endl;
-        return;
+        GTEST_SKIP();
     }
     EXPECT_EQ(ErrorStatus::NONE, prepareReturnStatus);
     ASSERT_NE(nullptr, preparedModel.get());
 
     float fpAtol = 1e-5f, fpRtol = 5.0f * 1.1920928955078125e-7f;
     EvaluatePreparedModel(preparedModel, is_ignored, examples,
-                          /*hasRelaxedFloat32Model=*/false, fpAtol, fpRtol, Synchronously::NO,
-                          MeasureTiming::NO, /*testDynamicOutputShape=*/false);
+                          /*hasRelaxedFloat32Model=*/false, fpAtol, fpRtol, Executor::ASYNC,
+                          MeasureTiming::NO, OutputType::FULLY_SPECIFIED);
 }
 
 void Execute(const sp<V1_1::IDevice>& device, std::function<V1_1::Model(void)> create_model,
@@ -386,22 +504,18 @@
         std::cout << "[          ]   Early termination of test because vendor service cannot "
                      "prepare model that it does not support."
                   << std::endl;
-        return;
+        GTEST_SKIP();
     }
     EXPECT_EQ(ErrorStatus::NONE, prepareReturnStatus);
     ASSERT_NE(nullptr, preparedModel.get());
 
     EvaluatePreparedModel(preparedModel, is_ignored, examples,
-                          model.relaxComputationFloat32toFloat16, 1e-5f, 1e-5f, Synchronously::NO,
-                          MeasureTiming::NO, /*testDynamicOutputShape=*/false);
+                          model.relaxComputationFloat32toFloat16, 1e-5f, 1e-5f, Executor::ASYNC,
+                          MeasureTiming::NO, OutputType::FULLY_SPECIFIED);
 }
 
-// TODO: Reduce code duplication.
-void Execute(const sp<V1_2::IDevice>& device, std::function<V1_2::Model(void)> create_model,
-             std::function<bool(int)> is_ignored, const std::vector<MixedTypedExample>& examples,
-             bool testDynamicOutputShape) {
-    V1_2::Model model = create_model();
-
+void PrepareModel(const sp<V1_2::IDevice>& device, const V1_2::Model& model,
+                  sp<V1_2::IPreparedModel>* preparedModel) {
     // see if service can handle model
     bool fullySupportsModel = false;
     Return<void> supportedCall = device->getSupportedOperations_1_2(
@@ -424,34 +538,31 @@
     // retrieve prepared model
     preparedModelCallback->wait();
     ErrorStatus prepareReturnStatus = preparedModelCallback->getStatus();
-    sp<V1_2::IPreparedModel> preparedModel;
-    getPreparedModel(preparedModelCallback, &preparedModel);
+    getPreparedModel(preparedModelCallback, preparedModel);
 
     // early termination if vendor service cannot fully prepare model
     if (!fullySupportsModel && prepareReturnStatus != ErrorStatus::NONE) {
-        ASSERT_EQ(nullptr, preparedModel.get());
+        ASSERT_EQ(nullptr, preparedModel->get());
         LOG(INFO) << "NN VTS: Early termination of test because vendor service cannot "
                      "prepare model that it does not support.";
         std::cout << "[          ]   Early termination of test because vendor service cannot "
                      "prepare model that it does not support."
                   << std::endl;
-        return;
+        GTEST_SKIP();
     }
     EXPECT_EQ(ErrorStatus::NONE, prepareReturnStatus);
-    ASSERT_NE(nullptr, preparedModel.get());
+    ASSERT_NE(nullptr, preparedModel->get());
+}
 
+// TODO: Reduce code duplication.
+void Execute(const sp<V1_2::IDevice>& device, std::function<V1_2::Model(void)> create_model,
+             std::function<bool(int)> is_ignored, const std::vector<MixedTypedExample>& examples,
+             bool testDynamicOutputShape) {
+    V1_2::Model model = create_model();
+    sp<V1_2::IPreparedModel> preparedModel = nullptr;
+    PrepareModel(device, model, &preparedModel);
     EvaluatePreparedModel(preparedModel, is_ignored, examples,
-                          model.relaxComputationFloat32toFloat16, Synchronously::NO,
-                          MeasureTiming::NO, testDynamicOutputShape);
-    EvaluatePreparedModel(preparedModel, is_ignored, examples,
-                          model.relaxComputationFloat32toFloat16, Synchronously::YES,
-                          MeasureTiming::NO, testDynamicOutputShape);
-    EvaluatePreparedModel(preparedModel, is_ignored, examples,
-                          model.relaxComputationFloat32toFloat16, Synchronously::NO,
-                          MeasureTiming::YES, testDynamicOutputShape);
-    EvaluatePreparedModel(preparedModel, is_ignored, examples,
-                          model.relaxComputationFloat32toFloat16, Synchronously::YES,
-                          MeasureTiming::YES, testDynamicOutputShape);
+                          model.relaxComputationFloat32toFloat16, testDynamicOutputShape);
 }
 
 }  // namespace generated_tests
diff --git a/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.h b/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.h
new file mode 100644
index 0000000..c7d2399
--- /dev/null
+++ b/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2019 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 VTS_HAL_NEURALNETWORKS_GENERATED_TEST_HARNESS_H
+#define VTS_HAL_NEURALNETWORKS_GENERATED_TEST_HARNESS_H
+
+#include "TestHarness.h"
+
+#include <android/hardware/neuralnetworks/1.0/IDevice.h>
+#include <android/hardware/neuralnetworks/1.1/IDevice.h>
+#include <android/hardware/neuralnetworks/1.2/IDevice.h>
+
+namespace android {
+namespace hardware {
+namespace neuralnetworks {
+
+namespace generated_tests {
+using ::test_helper::MixedTypedExample;
+
+void PrepareModel(const sp<V1_2::IDevice>& device, const V1_2::Model& model,
+                  sp<V1_2::IPreparedModel>* preparedModel);
+
+void EvaluatePreparedModel(sp<V1_2::IPreparedModel>& preparedModel,
+                           std::function<bool(int)> is_ignored,
+                           const std::vector<MixedTypedExample>& examples,
+                           bool hasRelaxedFloat32Model, bool testDynamicOutputShape);
+
+void Execute(const sp<V1_0::IDevice>& device, std::function<V1_0::Model(void)> create_model,
+             std::function<bool(int)> is_ignored, const std::vector<MixedTypedExample>& examples);
+
+void Execute(const sp<V1_1::IDevice>& device, std::function<V1_1::Model(void)> create_model,
+             std::function<bool(int)> is_ignored, const std::vector<MixedTypedExample>& examples);
+
+void Execute(const sp<V1_2::IDevice>& device, std::function<V1_2::Model(void)> create_model,
+             std::function<bool(int)> is_ignored, const std::vector<MixedTypedExample>& examples,
+             bool testDynamicOutputShape = false);
+
+}  // namespace generated_tests
+
+}  // namespace neuralnetworks
+}  // namespace hardware
+}  // namespace android
+
+#endif  // VTS_HAL_NEURALNETWORKS_GENERATED_TEST_HARNESS_H
diff --git a/neuralnetworks/1.0/vts/functional/GeneratedTests.cpp b/neuralnetworks/1.0/vts/functional/GeneratedTests.cpp
index 55e5861..d1c7de3 100644
--- a/neuralnetworks/1.0/vts/functional/GeneratedTests.cpp
+++ b/neuralnetworks/1.0/vts/functional/GeneratedTests.cpp
@@ -19,6 +19,7 @@
 #include "VtsHalNeuralnetworks.h"
 
 #include "Callbacks.h"
+#include "GeneratedTestHarness.h"
 #include "TestHarness.h"
 #include "Utils.h"
 
@@ -29,13 +30,6 @@
 namespace android {
 namespace hardware {
 namespace neuralnetworks {
-
-namespace generated_tests {
-using ::test_helper::MixedTypedExample;
-extern void Execute(const sp<V1_0::IDevice>&, std::function<V1_0::Model(void)>,
-                    std::function<bool(int)>, const std::vector<MixedTypedExample>&);
-}  // namespace generated_tests
-
 namespace V1_0 {
 namespace vts {
 namespace functional {
diff --git a/neuralnetworks/1.1/vts/functional/GeneratedTests.cpp b/neuralnetworks/1.1/vts/functional/GeneratedTests.cpp
index d98ea04..4db1276 100644
--- a/neuralnetworks/1.1/vts/functional/GeneratedTests.cpp
+++ b/neuralnetworks/1.1/vts/functional/GeneratedTests.cpp
@@ -19,6 +19,7 @@
 #include "VtsHalNeuralnetworks.h"
 
 #include "Callbacks.h"
+#include "GeneratedTestHarness.h"
 #include "TestHarness.h"
 #include "Utils.h"
 
@@ -29,13 +30,6 @@
 namespace android {
 namespace hardware {
 namespace neuralnetworks {
-
-namespace generated_tests {
-using ::test_helper::MixedTypedExample;
-extern void Execute(const sp<V1_1::IDevice>&, std::function<V1_1::Model(void)>,
-                    std::function<bool(int)>, const std::vector<MixedTypedExample>&);
-}  // namespace generated_tests
-
 namespace V1_1 {
 namespace vts {
 namespace functional {
diff --git a/neuralnetworks/1.1/vts/functional/GeneratedTestsV1_0.cpp b/neuralnetworks/1.1/vts/functional/GeneratedTestsV1_0.cpp
index 1df3218..e67ef8e 100644
--- a/neuralnetworks/1.1/vts/functional/GeneratedTestsV1_0.cpp
+++ b/neuralnetworks/1.1/vts/functional/GeneratedTestsV1_0.cpp
@@ -19,6 +19,7 @@
 #include "VtsHalNeuralnetworks.h"
 
 #include "Callbacks.h"
+#include "GeneratedTestHarness.h"
 #include "TestHarness.h"
 #include "Utils.h"
 
@@ -29,13 +30,6 @@
 namespace android {
 namespace hardware {
 namespace neuralnetworks {
-
-namespace generated_tests {
-using ::test_helper::MixedTypedExample;
-extern void Execute(const sp<V1_1::IDevice>&, std::function<V1_1::Model(void)>,
-                    std::function<bool(int)>, const std::vector<MixedTypedExample>&);
-}  // namespace generated_tests
-
 namespace V1_1 {
 namespace vts {
 namespace functional {
diff --git a/neuralnetworks/1.2/IDevice.hal b/neuralnetworks/1.2/IDevice.hal
index 6c3b483..b9fa388 100644
--- a/neuralnetworks/1.2/IDevice.hal
+++ b/neuralnetworks/1.2/IDevice.hal
@@ -76,6 +76,21 @@
     getType() generates (ErrorStatus status, DeviceType type);
 
     /**
+     * Gets information about extensions supported by the driver implementation.
+     *
+     * All extension operations and operands must be fully supported for the
+     * extension to appear in the list of supported extensions.
+     *
+     * @return status Error status of the call, must be:
+     *     - NONE if successful
+     *     - DEVICE_UNAVAILABLE if driver is offline or busy
+     *     - GENERAL_FAILURE if there is an unspecified error
+     * @return extensions A list of supported extensions.
+     */
+    getSupportedExtensions()
+        generates (ErrorStatus status, vec<Extension> extensions);
+
+    /**
      * Gets the supported operations in a model.
      *
      * getSupportedOperations indicates which operations of a model are fully
@@ -98,6 +113,25 @@
             generates (ErrorStatus status, vec<bool> supportedOperations);
 
     /**
+     * Gets whether the driver supports compilation caching.
+     *
+     * isCachingSupported indicates whether the driver supports compilation caching.
+     * Even if so, the driver may still choose not to cache certain compiled models.
+     *
+     * If the device reports the caching is not supported, the user may avoid calling
+     * IDevice::prepareModelFromCache and IPreparedModel::saveToCache.
+     *
+     * @return status Error status of the call, must be:
+     *     - NONE if successful
+     *     - DEVICE_UNAVAILABLE if driver is offline or busy
+     *     - GENERAL_FAILURE if there is an unspecified error
+     * @return supported A boolean indicating whether the driver supports compilation
+     *                   caching. Even on returning true, the driver may still choose
+     *                   not to cache certain compiled models.
+     */
+    isCachingSupported() generates (ErrorStatus status, bool supported);
+
+    /**
      * Creates a prepared model for execution.
      *
      * prepareModel is used to make any necessary transformations or alternative
@@ -153,4 +187,84 @@
     prepareModel_1_2(Model model, ExecutionPreference preference,
                      IPreparedModelCallback callback)
           generates (ErrorStatus status);
+
+    /**
+     * Creates a prepared model from cache files for execution.
+     *
+     * prepareModelFromCache is used to retrieve a prepared model directly from
+     * cache files to avoid slow model compilation time. There are exactly two
+     * cache file descriptors provided to the driver: modelCache and dataCache.
+     *
+     * The dataCache is for caching constant data, possibly including preprocessed
+     * and transformed tensor buffers. Any modification to the dataCache should
+     * have no worse effect than generating bad output values at execution time.
+     *
+     * The modelCache is for caching security-sensitive data such as compiled
+     * executable machine code in the device's native binary format. A modification
+     * to the modelCache may affect the driver's execution behavior, and a malicious
+     * client could make use of this to execute beyond the granted permission. Thus,
+     * the driver must always check whether the modelCache is corrupted before preparing
+     * the model from cache.
+     *
+     * The two file descriptors may be closed by the client once the asynchronous
+     * preparation has finished. The driver has to copy all the data it needs.
+     *
+     * The model is prepared asynchronously with respect to the caller. The
+     * prepareModelFromCache function must verify the inputs to the
+     * prepareModelFromCache function are correct, and that the security-sensitive
+     * cache has not been modified since it was last written by the driver.
+     * If there is an error, or if compilation caching is not supported, or if the
+     * security-sensitive cache has been modified, prepareModelFromCache must
+     * immediately invoke the callback with the appropriate ErrorStatus value and
+     * nullptr for the IPreparedModel, then return with the same ErrorStatus. If
+     * the inputs to the prepareModelFromCache function are valid, the security-sensitive
+     * cache is not modified, and there is no error, prepareModelFromCache must launch an
+     * asynchronous task to prepare the model in the background, and immediately return
+     * from prepareModelFromCache with ErrorStatus::NONE. If the asynchronous task
+     * fails to launch, prepareModelFromCache must immediately invoke the callback
+     * with ErrorStatus::GENERAL_FAILURE and nullptr for the IPreparedModel, then
+     * return with ErrorStatus::GENERAL_FAILURE.
+     *
+     * When the asynchronous task has finished preparing the model, it must
+     * immediately invoke the callback function provided as an input to
+     * prepareModelFromCache. If the model was prepared successfully, the
+     * callback object must be invoked with an error status of ErrorStatus::NONE
+     * and the produced IPreparedModel object. If an error occurred preparing
+     * the model, the callback object must be invoked with the appropriate
+     * ErrorStatus value and nullptr for the IPreparedModel.
+     *
+     * The only information that may be unknown to the model at this stage is
+     * the shape of the tensors, which may only be known at execution time. As
+     * such, some driver services may return partially prepared models, where
+     * the prepared model may only be finished when it is paired with a set of
+     * inputs to the model. Note that the same prepared model object may be
+     * used with different shapes of inputs on different (possibly concurrent)
+     * executions.
+     *
+     * @param modelCache A handle holding exactly one cache file descriptor for the
+     *     security-sensitive cache.
+     * @param dataCache A handle holding exactly one cache file descriptor for the
+     *     constants' cache.
+     * @param token A caching token of length Constant::BYTE_SIZE_OF_CACHE_TOKEN
+     *     identifying the prepared model. It is the same token provided when saving
+     *     the cache files with IPreparedModel::saveToCache. Tokens should be chosen
+     *     to have a low rate of collision for a particular application. The driver
+     *     cannot detect a collision; a collision will result in a failed execution
+     *     or in a successful execution that produces incorrect output values.
+     * @param callback A callback object used to return the error status of
+     *     preparing the model for execution and the prepared model if
+     *     successful, nullptr otherwise. The callback object's notify function
+     *     must be called exactly once, even if the model could not be prepared.
+     * @return status Error status of launching a task which prepares the model
+     *     in the background; must be:
+     *     - NONE if preparation task is successfully launched
+     *     - DEVICE_UNAVAILABLE if driver is offline or busy
+     *     - GENERAL_FAILURE if caching is not supported or if there is an
+     *       unspecified error
+     *     - INVALID_ARGUMENT if one of the input arguments is invalid
+     */
+    prepareModelFromCache(handle modelCache, handle dataCache,
+                          uint8_t[Constant:BYTE_SIZE_OF_CACHE_TOKEN] token,
+                          IPreparedModelCallback callback)
+            generates (ErrorStatus status);
 };
diff --git a/neuralnetworks/1.2/IPreparedModel.hal b/neuralnetworks/1.2/IPreparedModel.hal
index 5d2d80f..757d5f1 100644
--- a/neuralnetworks/1.2/IPreparedModel.hal
+++ b/neuralnetworks/1.2/IPreparedModel.hal
@@ -157,4 +157,62 @@
                             fmq_sync<FmqRequestDatum> requestChannel,
                             fmq_sync<FmqResultDatum> resultChannel)
                  generates (ErrorStatus status, IBurstContext context);
+
+    /*
+     * Saves the prepared model to cache files.
+     *
+     * saveToCache is used to save a prepared model to cache files for faster
+     * model compilation time when the same model preparation is requested in
+     * the future. There are exactly two cache file descriptors provided to the
+     * driver: modelCache and dataCache.
+     *
+     * The dataCache is for caching constant data, possibly including preprocessed
+     * and transformed tensor buffers. Any modification to the dataCache should
+     * have no worse effect than generating bad output values at execution time.
+     *
+     * The modelCache is for caching security-sensitive data such as compiled
+     * executable machine code in the device's native binary format. A modification
+     * to the modelCache may affect the driver's execution behavior, and a malicious
+     * client could make use of this to execute beyond the granted permission. Thus,
+     * the driver must always check whether the modelCache is corrupted before preparing
+     * the model from cache.
+     *
+     * The two file descriptors must point to two zero-length files with offset
+     * positioned at the beginning of the file. The file descriptors may be closed
+     * by the client once the method has returned.
+     *
+     * If the driver decides not to save the prepared model without looking at the
+     * input arguments to the saveToCache function, saveToCache must return with
+     * ErrorStatus::GENERAL_FAILURE. Otherwise, the saveToCache function must verify
+     * the input arguments to the saveToCache function are valid, and return with
+     * ErrorStatus::INVALID_ARGUMENT if not. If the inputs are valid but the driver
+     * could not save the prepared model, saveToCache must return with the appropriate
+     * ErrorStatus. Otherwise, it must write the cache files and return
+     * ErrorStatus::NONE. Unless saveToCache returns ErrorStatus::NONE, the contents
+     * of the cache files are undefined.
+     *
+     * @param modelCache A handle holding exactly one cache file descriptor for the
+     *                   security-sensitive cache.
+     * @param dataCache A handle holding exactly one cache file descriptor for the
+     *                  constants' cache.
+     * @param token A caching token of length Constant::BYTE_SIZE_OF_CACHE_TOKEN
+     *              identifying the prepared model. The same token will be provided
+     *              when retrieving the prepared model from cache files with
+     *              IDevice::prepareModelFromCache. Tokens should be chosen to have
+     *              a low rate of collision for a particular application. The driver
+     *              cannot detect a collision; a collision will result in a failed
+     *              execution or in a successful execution that produces incorrect
+     *              output values.
+     * @return status Error status of saveToCache, must be:
+     *                - NONE if saveToCache is performed successfully
+     *                - DEVICE_UNAVAILABLE if driver is offline or busy
+     *                - GENERAL_FAILURE if the driver could not save the
+     *                  prepared model or if there is an unspecified error
+     *                - INVALID_ARGUMENT if one of the input arguments is invalid,
+     *                  unless the driver decides not to save the prepared model
+     *                  without looking at the input arguments
+     */
+    saveToCache(handle modelCache, handle dataCache,
+                uint8_t[Constant:BYTE_SIZE_OF_CACHE_TOKEN] token)
+        generates (ErrorStatus status);
 };
diff --git a/neuralnetworks/1.2/types.hal b/neuralnetworks/1.2/types.hal
index bd8354f..2e48ba0 100644
--- a/neuralnetworks/1.2/types.hal
+++ b/neuralnetworks/1.2/types.hal
@@ -25,6 +25,13 @@
 
 import android.hidl.safe_union@1.0::Monostate;
 
+enum Constant : uint32_t {
+    /**
+     * The byte size of the cache token.
+     */
+    BYTE_SIZE_OF_CACHE_TOKEN = 32,
+};
+
 enum OperandType : @1.0::OperandType {
     /**
      * An 8 bit boolean scalar value.
@@ -40,7 +47,7 @@
      * used to convert the 16 bit number to a real value in the following way:
      * realValue = integerValue * scale.
      *
-     * scale is a 32 bit floating point with value greater then zero.
+     * scale is a 32 bit floating point with value greater than zero.
      */
     TENSOR_QUANT16_SYMM = 7,
     /** A tensor of IEEE 754 16 bit floating point values. */
@@ -66,10 +73,11 @@
      * These fields are located inside Operand's extraParams union, inside the
      * SymmPerChannelQuantParams struct.
      *
-     * An Operand of this type must use 'channelQuant' field of its extraParams
-     * union.
+     * An Operand of this type must use the 'channelQuant' variant of its
+     * extraParams field.
      *
-     * The channel dimension of this tensor must not be unknown (dimensions[channelDim] != 0).
+     * The channel dimension of this tensor must be known, i.e.
+     * dimensions[channelDim] must be non-zero.
      *
      * The formula for real values:
      * realValue[..., C, ...] =
@@ -89,11 +97,21 @@
      * real_value = (integer_value - zeroPoint) * scale.
      */
     TENSOR_QUANT16_ASYMM = 12,
+    /**
+     * A tensor of 8 bit signed integers that represent real numbers.
+     *
+     * Attached to this tensor is a number representing real value scale that is
+     * used to convert the 8 bit number to a real value in the following way:
+     * realValue = integerValue * scale.
+     *
+     * scale is a 32 bit floating point with value greater than zero.
+     */
+    TENSOR_QUANT8_SYMM = 13,
     /* ADDING A NEW FUNDAMENTAL TYPE REQUIRES UPDATING THE VALUE OF
-     * OperandTypeRange::OPERAND_FUNDAMENTAL_MAX.
+     * OperandTypeRange::FUNDAMENTAL_MAX.
      */
     /* ADDING A NEW OEM TYPE REQUIRES UPDATING THE VALUE OF
-     * OperandTypeRange::OPERAND_OEM_MAX.
+     * OperandTypeRange::OEM_MAX.
      */
 };
 
@@ -101,10 +119,12 @@
  * The range of operand values in the OperandType enum.
  */
 enum OperandTypeRange : uint32_t {
-    OPERAND_FUNDAMENTAL_MIN = 0,
-    OPERAND_FUNDAMENTAL_MAX = 12,
-    OPERAND_OEM_MIN     = 10000,
-    OPERAND_OEM_MAX     = 10001,
+    BASE_MIN        = 0,
+    FUNDAMENTAL_MIN = 0,
+    FUNDAMENTAL_MAX = 13,
+    OEM_MIN         = 10000,
+    OEM_MAX         = 10001,
+    BASE_MAX        = 0xFFFF,
 };
 
 /**
@@ -171,10 +191,10 @@
     UNIDIRECTIONAL_SEQUENCE_LSTM = 92,
     UNIDIRECTIONAL_SEQUENCE_RNN = 93,
     /* ADDING A NEW FUNDAMENTAL OPERATION REQUIRES UPDATING THE VALUE OF
-     * OperationTypeRange::OPERATION_FUNDAMENTAL_MAX.
+     * OperationTypeRange::FUNDAMENTAL_MAX.
      */
     /* ADDING A NEW OEM OPERATION REQUIRES UPDATING THE VALUE OF
-     * OperationTypeRange::OPERATION_OEM_MAX.
+     * OperationTypeRange::OEM_MAX.
      */
 };
 
@@ -182,10 +202,12 @@
  * The range of values in the OperationType enum.
  */
 enum OperationTypeRange : uint32_t {
-    OPERATION_FUNDAMENTAL_MIN = 0,
-    OPERATION_FUNDAMENTAL_MAX = 93,
-    OPERATION_OEM_MIN = 10000,
-    OPERATION_OEM_MAX = 10000,
+    BASE_MIN        = 0,
+    FUNDAMENTAL_MIN = 0,
+    FUNDAMENTAL_MAX = 93,
+    OEM_MIN         = 10000,
+    OEM_MAX         = 10000,
+    BASE_MAX        = 0xFFFF,
 };
 
 /**
@@ -214,6 +236,10 @@
 struct Operation {
     /**
      * The operation type.
+     *
+     * Besides the values listed in {@link OperationType}, any value above
+     * {@link OperationTypeRange::BASE_MAX} is possible and should be interpreted
+     * as an extension type according to {@link Model::extensionNameToPrefix}.
      */
     OperationType type;
 
@@ -240,21 +266,16 @@
     uint32_t channelDim;
 };
 
-// TODO(slavash): Operand Extension support
-// /**
-//  * Parameters for an unknown (as of 1.2) operand extension. This is
-//  * a vendor-specific extension or a platform extension (backport of
-//  * functionality from newer NNAPI interface).
-//  */
-// struct OperandParamsUnknown {
-// };
-
 /**
  * Describes one operand of the model's graph.
  */
 struct Operand {
     /**
-     * Data type of the operand.
+     * The data type.
+     *
+     * Besides the values listed in {@link OperandType}, any value above
+     * {@link OperandTypeRange::BASE_MAX} is possible and should be interpreted
+     * as an extension type according to {@link Model::extensionNameToPrefix}.
      */
     OperandType type;
 
@@ -344,25 +365,28 @@
     DataLocation location;
 
     /**
-     * Union of extra parameters, used by some types of Operands that need additional
-     * information for the complete definition of an Operand.
+     * Additional parameters specific to a particular operand type.
      */
     safe_union ExtraParams {
        /**
-        * Placeholder for operand with no extra parameters.
+        * No additional parameters.
         */
        Monostate none;
 
        /**
-        * Used with TENSOR_QUANT8_SYMM_PER_CHANNEL operand type.
+        * Symmetric per-channel quantization parameters.
+        *
+        * Only applicable to operands of type TENSOR_QUANT8_SYMM_PER_CHANNEL.
         */
        SymmPerChannelQuantParams channelQuant;
 
-       // TODO(slavash): Operand Extension support
-       // /**
-       //  * Used with Extension operand type.
-       //  */
-       // OperandParamsUnknown unknown;
+       /**
+        * Extension operand parameters.
+        *
+        * The framework treats this as an opaque data blob.
+        * The format is up to individual extensions.
+        */
+       vec<uint8_t> extension;
     } extraParams;
 };
 
@@ -425,6 +449,63 @@
      * range and precision of the IEEE 754 32-bit floating-point format.
      */
     bool relaxComputationFloat32toFloat16;
+
+    /**
+     * The mapping between extension names and prefixes of operand and
+     * operation type values.
+     *
+     * An operand or operation whose numeric type value is above
+     * {@link OperandTypeRange::BASE_MAX} or
+     * {@link OperationTypeRange::BASE_MAX} respectively should be interpreted
+     * as an extension operand. The low
+     * {@link Model::ExtensionTypeEncoding::LOW_BITS_TYPE} bits of the value
+     * correspond to the value within the extension and the high
+     * {@link Model::ExtensionTypeEncoding::HIGH_BITS_PREFIX} bits encode
+     * the "prefix", which maps uniquely to the extension name.
+     *
+     * For example, if a model contains an operation whose value is
+     * 0xAAAABBBB and extensionNameToPrefix contains an entry with
+     * prefix=0xAAAA and name="vendor.test.test_extension", then
+     * the operation should be interpreted as the operation 0xBBBB
+     * of the extension named vendor.test.test_extension.
+     *
+     * This is a one-to-one correspondence. That is, there must be at most one
+     * prefix corresponding to each extension name and at most one extension
+     * name corresponding to each prefix.
+     */
+    vec<ExtensionNameAndPrefix> extensionNameToPrefix;
+
+    /**
+     * A correspondence between an extension name and a prefix of operand and
+     * operation type values.
+     */
+    struct ExtensionNameAndPrefix {
+        /**
+         * The extension name.
+         *
+         * See {@link Extension::name}.
+         */
+        string name;
+
+        /**
+         * The unique extension identifier within the model.
+         *
+         * See {@link Model::extensionNameToPrefix}.
+         */
+        uint16_t prefix;
+    };
+
+    /**
+     * Numeric values of extension operand and operation types have the
+     * following structure:
+     * - 16 high bits represent the "prefix", which corresponds uniquely to the
+     *   extension name.
+     * - 16 low bits represent the type ID within the extension.
+     */
+    enum ExtensionTypeEncoding : uint8_t {
+        HIGH_BITS_PREFIX = 16,
+        LOW_BITS_TYPE = 16,
+    };
 };
 
 /**
@@ -678,3 +759,43 @@
      */
     Timing executionTiming;
 };
+
+/**
+ * Information about an extension.
+ */
+struct Extension {
+    /**
+     * The extension name.
+     *
+     * The name must start with the reverse domain name of the vendor.
+     * Example: com.google.test_extension
+     */
+    string name;
+
+    /**
+     * Information about an extension operand type.
+     */
+    struct OperandTypeInformation {
+        /**
+         * The extension operand type.
+         */
+        uint16_t type;
+
+        /**
+         * Indicates whether the extension operand type represents a tensor or
+         * a scalar.
+         */
+        bool isTensor;
+
+        /**
+         * The byte size of the operand (if scalar) or of a single element (if
+         * tensor).
+         */
+        uint32_t byteSize;
+    };
+
+    /**
+     * Information about operand types defined by the extension.
+     */
+    vec<OperandTypeInformation> operandTypes;
+};
diff --git a/neuralnetworks/1.2/vts/functional/Android.bp b/neuralnetworks/1.2/vts/functional/Android.bp
index 0cb9e16..510a0d5 100644
--- a/neuralnetworks/1.2/vts/functional/Android.bp
+++ b/neuralnetworks/1.2/vts/functional/Android.bp
@@ -46,6 +46,7 @@
     defaults: ["VtsHalNeuralNetworksTargetTestDefaults"],
     srcs: [
         "BasicTests.cpp",
+        "CompilationCachingTests.cpp",
         "GeneratedTests.cpp",
     ],
     cflags: [
diff --git a/neuralnetworks/1.2/vts/functional/BasicTests.cpp b/neuralnetworks/1.2/vts/functional/BasicTests.cpp
index 8c3ad15..2b88edd 100644
--- a/neuralnetworks/1.2/vts/functional/BasicTests.cpp
+++ b/neuralnetworks/1.2/vts/functional/BasicTests.cpp
@@ -55,6 +55,29 @@
     });
     EXPECT_TRUE(ret.isOk());
 }
+
+// device supported extensions test
+TEST_F(NeuralnetworksHidlTest, GetDeviceSupportedExtensionsTest) {
+    Return<void> ret = device->getSupportedExtensions(
+            [](ErrorStatus status, const hidl_vec<Extension>& extensions) {
+                EXPECT_EQ(ErrorStatus::NONE, status);
+                for (auto& extension : extensions) {
+                    std::string extensionName = extension.name;
+                    EXPECT_FALSE(extensionName.empty());
+                    EXPECT_NE(extensionName.find("."), std::string::npos)
+                            << "Extension name must start with the reverse domain name of the "
+                               "vendor";
+                }
+            });
+    EXPECT_TRUE(ret.isOk());
+}
+
+// isCachingSupported test
+TEST_F(NeuralnetworksHidlTest, IsCachingSupported) {
+    Return<void> ret = device->isCachingSupported(
+            [](ErrorStatus status, bool) { EXPECT_EQ(ErrorStatus::NONE, status); });
+    EXPECT_TRUE(ret.isOk());
+}
 }  // namespace functional
 }  // namespace vts
 }  // namespace V1_2
diff --git a/neuralnetworks/1.2/vts/functional/CompilationCachingTests.cpp b/neuralnetworks/1.2/vts/functional/CompilationCachingTests.cpp
new file mode 100644
index 0000000..454aa1f
--- /dev/null
+++ b/neuralnetworks/1.2/vts/functional/CompilationCachingTests.cpp
@@ -0,0 +1,652 @@
+/*
+ * Copyright (C) 2019 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 "neuralnetworks_hidl_hal_test"
+
+#include "VtsHalNeuralnetworks.h"
+
+#include "Callbacks.h"
+#include "GeneratedTestHarness.h"
+#include "TestHarness.h"
+#include "Utils.h"
+
+#include <android-base/logging.h>
+#include <android/hidl/memory/1.0/IMemory.h>
+#include <hidlmemory/mapping.h>
+#include <cstdio>
+#include <cstdlib>
+#include <random>
+
+#include <gtest/gtest.h>
+
+namespace android {
+namespace hardware {
+namespace neuralnetworks {
+namespace V1_2 {
+namespace vts {
+namespace functional {
+
+using ::android::hardware::neuralnetworks::V1_2::implementation::ExecutionCallback;
+using ::android::hardware::neuralnetworks::V1_2::implementation::PreparedModelCallback;
+using ::android::nn::allocateSharedMemory;
+using ::test_helper::MixedTypedExample;
+
+namespace {
+
+// In frameworks/ml/nn/runtime/tests/generated/, creates a hidl model of mobilenet.
+#include "examples/mobilenet_224_gender_basic_fixed.example.cpp"
+#include "vts_models/mobilenet_224_gender_basic_fixed.model.cpp"
+
+// Prevent the compiler from complaining about an otherwise unused function.
+[[maybe_unused]] auto dummy_createTestModel = createTestModel_dynamic_output_shape;
+[[maybe_unused]] auto dummy_get_examples = get_examples_dynamic_output_shape;
+
+enum class AccessMode { READ_ONLY, WRITE_ONLY };
+
+void createCacheHandle(const std::vector<std::string>& files, AccessMode mode,
+                       hidl_handle* handle) {
+    std::vector<int> fds;
+    for (const auto& file : files) {
+        int fd;
+        if (mode == AccessMode::READ_ONLY) {
+            fd = open(file.c_str(), O_RDONLY);
+        } else if (mode == AccessMode::WRITE_ONLY) {
+            fd = open(file.c_str(), O_WRONLY | O_TRUNC | O_CREAT, S_IRUSR | S_IWUSR);
+        } else {
+            FAIL();
+        }
+        ASSERT_GE(fd, 0);
+        fds.push_back(fd);
+    }
+    native_handle_t* cacheNativeHandle = native_handle_create(fds.size(), 0);
+    ASSERT_NE(cacheNativeHandle, nullptr);
+    for (uint32_t i = 0; i < fds.size(); i++) {
+        cacheNativeHandle->data[i] = fds[i];
+    }
+    handle->setTo(cacheNativeHandle, /*shouldOwn=*/true);
+}
+
+}  // namespace
+
+// Tag for the compilation caching tests.
+class CompilationCachingTest : public NeuralnetworksHidlTest {
+  protected:
+    void SetUp() override {
+        NeuralnetworksHidlTest::SetUp();
+
+        // Create cache directory.
+        char cacheDirTemp[] = "/data/local/tmp/TestCompilationCachingXXXXXX";
+        char* cacheDir = mkdtemp(cacheDirTemp);
+        ASSERT_NE(cacheDir, nullptr);
+        mCache1 = cacheDir + mCache1;
+        mCache2 = cacheDir + mCache2;
+        mCache3 = cacheDir + mCache3;
+
+        // Check if caching is supported.
+        bool isCachingSupported;
+        Return<void> ret = device->isCachingSupported(
+                [&isCachingSupported](ErrorStatus status, bool supported) {
+                    EXPECT_EQ(ErrorStatus::NONE, status);
+                    isCachingSupported = supported;
+                });
+        EXPECT_TRUE(ret.isOk());
+        if (isCachingSupported) {
+            mIsCachingSupported = true;
+        } else {
+            LOG(INFO) << "NN VTS: Early termination of test because vendor service does not "
+                         "support compilation caching.";
+            std::cout << "[          ]   Early termination of test because vendor service does not "
+                         "support compilation caching."
+                      << std::endl;
+            mIsCachingSupported = false;
+        }
+
+        // Create empty cache files.
+        hidl_handle handle;
+        createCacheHandle({mCache1, mCache2, mCache3}, AccessMode::WRITE_ONLY, &handle);
+    }
+
+    void saveModelToCache(sp<IPreparedModel> preparedModel, const hidl_handle& cache1,
+                          const hidl_handle& cache2, ErrorStatus* status) {
+        // Save IPreparedModel to cache.
+        hidl_array<uint8_t, sizeof(mToken)> cacheToken(mToken);
+        Return<ErrorStatus> saveToCacheStatus =
+                preparedModel->saveToCache(cache1, cache2, cacheToken);
+        ASSERT_TRUE(saveToCacheStatus.isOk());
+        *status = static_cast<ErrorStatus>(saveToCacheStatus);
+    }
+
+    bool checkEarlyTermination(ErrorStatus status) {
+        if (status == ErrorStatus::GENERAL_FAILURE) {
+            LOG(INFO) << "NN VTS: Early termination of test because vendor service cannot "
+                         "save the prepared model that it does not support.";
+            std::cout << "[          ]   Early termination of test because vendor service cannot "
+                         "save the prepared model that it does not support."
+                      << std::endl;
+            return true;
+        }
+        return false;
+    }
+
+    void prepareModelFromCache(const hidl_handle& cache1, const hidl_handle& cache2,
+                               sp<IPreparedModel>* preparedModel, ErrorStatus* status) {
+        // Launch prepare model from cache.
+        sp<PreparedModelCallback> preparedModelCallback = new PreparedModelCallback();
+        ASSERT_NE(nullptr, preparedModelCallback.get());
+        hidl_array<uint8_t, sizeof(mToken)> cacheToken(mToken);
+        Return<ErrorStatus> prepareLaunchStatus =
+                device->prepareModelFromCache(cache1, cache2, cacheToken, preparedModelCallback);
+        ASSERT_TRUE(prepareLaunchStatus.isOk());
+        if (static_cast<ErrorStatus>(prepareLaunchStatus) != ErrorStatus::NONE) {
+            *preparedModel = nullptr;
+            *status = static_cast<ErrorStatus>(prepareLaunchStatus);
+            return;
+        }
+
+        // Retrieve prepared model.
+        preparedModelCallback->wait();
+        *status = preparedModelCallback->getStatus();
+        *preparedModel = V1_2::IPreparedModel::castFrom(preparedModelCallback->getPreparedModel())
+                                 .withDefault(nullptr);
+    }
+
+    std::string mCache1 = "/cache1";
+    std::string mCache2 = "/cache2";
+    std::string mCache3 = "/cache3";
+    uint8_t mToken[static_cast<uint32_t>(Constant::BYTE_SIZE_OF_CACHE_TOKEN)] = {};
+    bool mIsCachingSupported;
+};
+
+TEST_F(CompilationCachingTest, CacheSavingAndRetrieval) {
+    // Create test HIDL model and compile.
+    Model testModel = createTestModel();
+    sp<IPreparedModel> preparedModel = nullptr;
+    generated_tests::PrepareModel(device, testModel, &preparedModel);
+    // Terminate early if the driver cannot prepare the model.
+    if (preparedModel == nullptr) return;
+
+    // Save the compilation to cache.
+    {
+        ErrorStatus status;
+        hidl_handle cache1, cache2;
+        createCacheHandle({mCache1}, AccessMode::WRITE_ONLY, &cache1);
+        createCacheHandle({mCache2}, AccessMode::WRITE_ONLY, &cache2);
+        saveModelToCache(preparedModel, cache1, cache2, &status);
+        if (!mIsCachingSupported) {
+            EXPECT_EQ(status, ErrorStatus::GENERAL_FAILURE);
+        } else {
+            if (checkEarlyTermination(status)) return;
+            ASSERT_EQ(status, ErrorStatus::NONE);
+        }
+    }
+
+    // Retrieve preparedModel from cache.
+    {
+        preparedModel = nullptr;
+        ErrorStatus status;
+        hidl_handle cache1, cache2;
+        createCacheHandle({mCache1}, AccessMode::READ_ONLY, &cache1);
+        createCacheHandle({mCache2}, AccessMode::READ_ONLY, &cache2);
+        prepareModelFromCache(cache1, cache2, &preparedModel, &status);
+        if (!mIsCachingSupported) {
+            ASSERT_EQ(status, ErrorStatus::GENERAL_FAILURE);
+            ASSERT_EQ(preparedModel, nullptr);
+            return;
+        } else {
+            ASSERT_EQ(status, ErrorStatus::NONE);
+            ASSERT_NE(preparedModel, nullptr);
+        }
+    }
+
+    // Execute and verify results.
+    generated_tests::EvaluatePreparedModel(preparedModel, [](int) { return false; }, get_examples(),
+                                           testModel.relaxComputationFloat32toFloat16,
+                                           /*testDynamicOutputShape=*/false);
+}
+
+TEST_F(CompilationCachingTest, CacheSavingAndRetrievalNonZeroOffset) {
+    // Create test HIDL model and compile.
+    Model testModel = createTestModel();
+    sp<IPreparedModel> preparedModel = nullptr;
+    generated_tests::PrepareModel(device, testModel, &preparedModel);
+    // Terminate early if the driver cannot prepare the model.
+    if (preparedModel == nullptr) return;
+
+    // Save the compilation to cache.
+    {
+        ErrorStatus status;
+        hidl_handle cache1, cache2;
+        createCacheHandle({mCache1}, AccessMode::WRITE_ONLY, &cache1);
+        createCacheHandle({mCache2}, AccessMode::WRITE_ONLY, &cache2);
+        saveModelToCache(preparedModel, cache1, cache2, &status);
+        if (!mIsCachingSupported) {
+            EXPECT_EQ(status, ErrorStatus::GENERAL_FAILURE);
+        } else {
+            if (checkEarlyTermination(status)) return;
+            ASSERT_EQ(status, ErrorStatus::NONE);
+        }
+    }
+
+    // Retrieve preparedModel from cache.
+    {
+        preparedModel = nullptr;
+        ErrorStatus status;
+        hidl_handle cache1, cache2;
+        createCacheHandle({mCache1}, AccessMode::READ_ONLY, &cache1);
+        createCacheHandle({mCache2}, AccessMode::READ_ONLY, &cache2);
+        uint8_t dummyByte = 0;
+        // Advance offset by one byte.
+        ASSERT_GE(read(cache1.getNativeHandle()->data[0], &dummyByte, 1), 0);
+        ASSERT_GE(read(cache2.getNativeHandle()->data[0], &dummyByte, 1), 0);
+        prepareModelFromCache(cache1, cache2, &preparedModel, &status);
+        if (!mIsCachingSupported) {
+            ASSERT_EQ(status, ErrorStatus::GENERAL_FAILURE);
+            ASSERT_EQ(preparedModel, nullptr);
+            return;
+        } else {
+            ASSERT_EQ(status, ErrorStatus::NONE);
+            ASSERT_NE(preparedModel, nullptr);
+        }
+    }
+
+    // Execute and verify results.
+    generated_tests::EvaluatePreparedModel(preparedModel, [](int) { return false; }, get_examples(),
+                                           testModel.relaxComputationFloat32toFloat16,
+                                           /*testDynamicOutputShape=*/false);
+}
+
+TEST_F(CompilationCachingTest, SaveToCacheInvalidNumFd) {
+    // Create test HIDL model and compile.
+    Model testModel = createTestModel();
+    sp<IPreparedModel> preparedModel = nullptr;
+    generated_tests::PrepareModel(device, testModel, &preparedModel);
+    // Terminate early if the driver cannot prepare the model.
+    if (preparedModel == nullptr) return;
+
+    // cache1 with invalid NumFd.
+    {
+        ErrorStatus status;
+        hidl_handle cache1, cache2;
+        createCacheHandle({mCache1, mCache3}, AccessMode::WRITE_ONLY, &cache1);
+        createCacheHandle({mCache2}, AccessMode::WRITE_ONLY, &cache2);
+        saveModelToCache(preparedModel, cache1, cache2, &status);
+        if (status != ErrorStatus::GENERAL_FAILURE) {
+            ASSERT_EQ(status, ErrorStatus::INVALID_ARGUMENT);
+        }
+    }
+
+    // cache2 with invalid NumFd.
+    {
+        ErrorStatus status;
+        hidl_handle cache1, cache2;
+        createCacheHandle({mCache1}, AccessMode::WRITE_ONLY, &cache1);
+        createCacheHandle({mCache2, mCache3}, AccessMode::WRITE_ONLY, &cache2);
+        saveModelToCache(preparedModel, cache1, cache2, &status);
+        if (status != ErrorStatus::GENERAL_FAILURE) {
+            ASSERT_EQ(status, ErrorStatus::INVALID_ARGUMENT);
+        }
+    }
+}
+
+TEST_F(CompilationCachingTest, PrepareModelFromCacheInvalidNumFd) {
+    // Create test HIDL model and compile.
+    Model testModel = createTestModel();
+    sp<IPreparedModel> preparedModel = nullptr;
+    generated_tests::PrepareModel(device, testModel, &preparedModel);
+    // Terminate early if the driver cannot prepare the model.
+    if (preparedModel == nullptr) return;
+
+    // Save the compilation to cache.
+    {
+        ErrorStatus status;
+        hidl_handle cache1, cache2;
+        createCacheHandle({mCache1}, AccessMode::WRITE_ONLY, &cache1);
+        createCacheHandle({mCache2}, AccessMode::WRITE_ONLY, &cache2);
+        saveModelToCache(preparedModel, cache1, cache2, &status);
+        if (status != ErrorStatus::GENERAL_FAILURE) {
+            ASSERT_EQ(status, ErrorStatus::NONE);
+        }
+    }
+
+    // cache1 with invalid NumFd.
+    {
+        preparedModel = nullptr;
+        ErrorStatus status;
+        hidl_handle cache1, cache2;
+        createCacheHandle({mCache1, mCache3}, AccessMode::READ_ONLY, &cache1);
+        createCacheHandle({mCache2}, AccessMode::READ_ONLY, &cache2);
+        prepareModelFromCache(cache1, cache2, &preparedModel, &status);
+        if (status != ErrorStatus::GENERAL_FAILURE) {
+            ASSERT_EQ(status, ErrorStatus::INVALID_ARGUMENT);
+            ASSERT_EQ(preparedModel, nullptr);
+        }
+    }
+
+    // cache2 with invalid NumFd.
+    {
+        preparedModel = nullptr;
+        ErrorStatus status;
+        hidl_handle cache1, cache2;
+        createCacheHandle({mCache1}, AccessMode::READ_ONLY, &cache1);
+        createCacheHandle({mCache2, mCache3}, AccessMode::READ_ONLY, &cache2);
+        prepareModelFromCache(cache1, cache2, &preparedModel, &status);
+        if (status != ErrorStatus::GENERAL_FAILURE) {
+            ASSERT_EQ(status, ErrorStatus::INVALID_ARGUMENT);
+            ASSERT_EQ(preparedModel, nullptr);
+        }
+    }
+}
+
+TEST_F(CompilationCachingTest, SaveToCacheInvalidAccessMode) {
+    // Create test HIDL model and compile.
+    Model testModel = createTestModel();
+    sp<IPreparedModel> preparedModel = nullptr;
+    generated_tests::PrepareModel(device, testModel, &preparedModel);
+    // Terminate early if the driver cannot prepare the model.
+    if (preparedModel == nullptr) return;
+
+    // cache1 with invalid access mode.
+    {
+        ErrorStatus status;
+        hidl_handle cache1, cache2;
+        createCacheHandle({mCache1}, AccessMode::READ_ONLY, &cache1);
+        createCacheHandle({mCache2}, AccessMode::WRITE_ONLY, &cache2);
+        saveModelToCache(preparedModel, cache1, cache2, &status);
+        ASSERT_EQ(status, ErrorStatus::GENERAL_FAILURE);
+    }
+
+    // cache2 with invalid access mode.
+    {
+        ErrorStatus status;
+        hidl_handle cache1, cache2;
+        createCacheHandle({mCache1}, AccessMode::WRITE_ONLY, &cache1);
+        createCacheHandle({mCache2}, AccessMode::READ_ONLY, &cache2);
+        saveModelToCache(preparedModel, cache1, cache2, &status);
+        ASSERT_EQ(status, ErrorStatus::GENERAL_FAILURE);
+    }
+}
+
+TEST_F(CompilationCachingTest, PrepareModelFromCacheInvalidAccessMode) {
+    // Create test HIDL model and compile.
+    Model testModel = createTestModel();
+    sp<IPreparedModel> preparedModel = nullptr;
+    generated_tests::PrepareModel(device, testModel, &preparedModel);
+    // Terminate early if the driver cannot prepare the model.
+    if (preparedModel == nullptr) return;
+
+    // Save the compilation to cache.
+    {
+        ErrorStatus status;
+        hidl_handle cache1, cache2;
+        createCacheHandle({mCache1}, AccessMode::WRITE_ONLY, &cache1);
+        createCacheHandle({mCache2}, AccessMode::WRITE_ONLY, &cache2);
+        saveModelToCache(preparedModel, cache1, cache2, &status);
+        if (status != ErrorStatus::GENERAL_FAILURE) {
+            ASSERT_EQ(status, ErrorStatus::NONE);
+        }
+    }
+
+    // cache1 with invalid access mode.
+    {
+        preparedModel = nullptr;
+        ErrorStatus status;
+        hidl_handle cache1, cache2;
+        createCacheHandle({mCache1}, AccessMode::WRITE_ONLY, &cache1);
+        createCacheHandle({mCache2}, AccessMode::READ_ONLY, &cache2);
+        prepareModelFromCache(cache1, cache2, &preparedModel, &status);
+        ASSERT_EQ(status, ErrorStatus::GENERAL_FAILURE);
+        ASSERT_EQ(preparedModel, nullptr);
+    }
+
+    // cache2 with invalid access mode.
+    {
+        preparedModel = nullptr;
+        ErrorStatus status;
+        hidl_handle cache1, cache2;
+        createCacheHandle({mCache1}, AccessMode::READ_ONLY, &cache1);
+        createCacheHandle({mCache2}, AccessMode::WRITE_ONLY, &cache2);
+        prepareModelFromCache(cache1, cache2, &preparedModel, &status);
+        ASSERT_EQ(status, ErrorStatus::GENERAL_FAILURE);
+        ASSERT_EQ(preparedModel, nullptr);
+    }
+}
+
+TEST_F(CompilationCachingTest, SaveToCacheInvalidOffset) {
+    // Create test HIDL model and compile.
+    Model testModel = createTestModel();
+    sp<IPreparedModel> preparedModel = nullptr;
+    generated_tests::PrepareModel(device, testModel, &preparedModel);
+    // Terminate early if the driver cannot prepare the model.
+    if (preparedModel == nullptr) return;
+
+    // cache1 with invalid file descriptor offset.
+    {
+        ErrorStatus status;
+        hidl_handle cache1, cache2;
+        createCacheHandle({mCache1}, AccessMode::WRITE_ONLY, &cache1);
+        createCacheHandle({mCache2}, AccessMode::WRITE_ONLY, &cache2);
+        uint8_t dummyByte = 0;
+        // Advance offset by one byte.
+        ASSERT_EQ(write(cache1.getNativeHandle()->data[0], &dummyByte, 1), 1);
+        saveModelToCache(preparedModel, cache1, cache2, &status);
+        ASSERT_EQ(status, ErrorStatus::GENERAL_FAILURE);
+    }
+
+    // cache2 with invalid file descriptor offset.
+    {
+        ErrorStatus status;
+        hidl_handle cache1, cache2;
+        createCacheHandle({mCache1}, AccessMode::WRITE_ONLY, &cache1);
+        createCacheHandle({mCache2}, AccessMode::WRITE_ONLY, &cache2);
+        uint8_t dummyByte = 0;
+        // Advance offset by one byte.
+        ASSERT_EQ(write(cache2.getNativeHandle()->data[0], &dummyByte, 1), 1);
+        saveModelToCache(preparedModel, cache1, cache2, &status);
+        ASSERT_EQ(status, ErrorStatus::GENERAL_FAILURE);
+    }
+}
+
+TEST_F(CompilationCachingTest, SaveToCacheInvalidFileSize) {
+    // Create test HIDL model and compile.
+    Model testModel = createTestModel();
+    sp<IPreparedModel> preparedModel = nullptr;
+    generated_tests::PrepareModel(device, testModel, &preparedModel);
+    // Terminate early if the driver cannot prepare the model.
+    if (preparedModel == nullptr) return;
+
+    // cache1 with invalid file size.
+    {
+        ErrorStatus status;
+        hidl_handle cache1, cache2;
+        createCacheHandle({mCache1}, AccessMode::WRITE_ONLY, &cache1);
+        createCacheHandle({mCache2}, AccessMode::WRITE_ONLY, &cache2);
+        uint8_t dummyByte = 0;
+        // Write one byte and seek back to the beginning.
+        ASSERT_EQ(write(cache1.getNativeHandle()->data[0], &dummyByte, 1), 1);
+        ASSERT_EQ(lseek(cache1.getNativeHandle()->data[0], 0, SEEK_SET), 0);
+        saveModelToCache(preparedModel, cache1, cache2, &status);
+        ASSERT_EQ(status, ErrorStatus::GENERAL_FAILURE);
+    }
+
+    // cache2 with invalid file size.
+    {
+        ErrorStatus status;
+        hidl_handle cache1, cache2;
+        createCacheHandle({mCache1}, AccessMode::WRITE_ONLY, &cache1);
+        createCacheHandle({mCache2}, AccessMode::WRITE_ONLY, &cache2);
+        uint8_t dummyByte = 0;
+        // Write one byte and seek back to the beginning.
+        ASSERT_EQ(write(cache2.getNativeHandle()->data[0], &dummyByte, 1), 1);
+        ASSERT_EQ(lseek(cache2.getNativeHandle()->data[0], 0, SEEK_SET), 0);
+        saveModelToCache(preparedModel, cache1, cache2, &status);
+        ASSERT_EQ(status, ErrorStatus::GENERAL_FAILURE);
+    }
+}
+
+class CompilationCachingSecurityTest : public CompilationCachingTest,
+                                       public ::testing::WithParamInterface<uint32_t> {
+  protected:
+    void SetUp() {
+        CompilationCachingTest::SetUp();
+        generator.seed(kSeed);
+    }
+
+    // Get a random integer within a closed range [lower, upper].
+    template <typename T>
+    T getRandomInt(T lower, T upper) {
+        std::uniform_int_distribution<T> dis(lower, upper);
+        return dis(generator);
+    }
+
+    const uint32_t kSeed = GetParam();
+    std::mt19937 generator;
+};
+
+TEST_P(CompilationCachingSecurityTest, CorruptedSecuritySensitiveCache) {
+    if (!mIsCachingSupported) return;
+
+    // Create test HIDL model and compile.
+    Model testModel = createTestModel();
+    sp<IPreparedModel> preparedModel = nullptr;
+    generated_tests::PrepareModel(device, testModel, &preparedModel);
+    // Terminate early if the driver cannot prepare the model.
+    if (preparedModel == nullptr) return;
+
+    // Save the compilation to cache.
+    {
+        ErrorStatus status;
+        hidl_handle cache1, cache2;
+        createCacheHandle({mCache1}, AccessMode::WRITE_ONLY, &cache1);
+        createCacheHandle({mCache2}, AccessMode::WRITE_ONLY, &cache2);
+        saveModelToCache(preparedModel, cache1, cache2, &status);
+        if (checkEarlyTermination(status)) return;
+        ASSERT_EQ(status, ErrorStatus::NONE);
+    }
+
+    // Randomly flip one single bit of the cache entry.
+    FILE* pFile = fopen(mCache1.c_str(), "r+");
+    ASSERT_EQ(fseek(pFile, 0, SEEK_END), 0);
+    long int fileSize = ftell(pFile);
+    ASSERT_GT(fileSize, 0);
+    ASSERT_EQ(fseek(pFile, getRandomInt(0l, fileSize - 1), SEEK_SET), 0);
+    int readByte = fgetc(pFile);
+    ASSERT_NE(readByte, EOF);
+    ASSERT_EQ(fseek(pFile, -1, SEEK_CUR), 0);
+    ASSERT_NE(fputc(static_cast<uint8_t>(readByte) ^ (1U << getRandomInt(0, 7)), pFile), EOF);
+    fclose(pFile);
+
+    // Retrieve preparedModel from cache, expect failure.
+    {
+        preparedModel = nullptr;
+        ErrorStatus status;
+        hidl_handle cache1, cache2;
+        createCacheHandle({mCache1}, AccessMode::READ_ONLY, &cache1);
+        createCacheHandle({mCache2}, AccessMode::READ_ONLY, &cache2);
+        prepareModelFromCache(cache1, cache2, &preparedModel, &status);
+        ASSERT_EQ(status, ErrorStatus::GENERAL_FAILURE);
+        ASSERT_EQ(preparedModel, nullptr);
+    }
+}
+
+TEST_P(CompilationCachingSecurityTest, WrongLengthSecuritySensitiveCache) {
+    if (!mIsCachingSupported) return;
+
+    // Create test HIDL model and compile.
+    Model testModel = createTestModel();
+    sp<IPreparedModel> preparedModel = nullptr;
+    generated_tests::PrepareModel(device, testModel, &preparedModel);
+    // Terminate early if the driver cannot prepare the model.
+    if (preparedModel == nullptr) return;
+
+    // Save the compilation to cache.
+    {
+        ErrorStatus status;
+        hidl_handle cache1, cache2;
+        createCacheHandle({mCache1}, AccessMode::WRITE_ONLY, &cache1);
+        createCacheHandle({mCache2}, AccessMode::WRITE_ONLY, &cache2);
+        saveModelToCache(preparedModel, cache1, cache2, &status);
+        if (checkEarlyTermination(status)) return;
+        ASSERT_EQ(status, ErrorStatus::NONE);
+    }
+
+    // Randomly append bytes to the cache entry.
+    FILE* pFile = fopen(mCache1.c_str(), "a");
+    uint32_t appendLength = getRandomInt(1, 256);
+    for (uint32_t i = 0; i < appendLength; i++) {
+        ASSERT_NE(fputc(getRandomInt<uint8_t>(0, 255), pFile), EOF);
+    }
+    fclose(pFile);
+
+    // Retrieve preparedModel from cache, expect failure.
+    {
+        preparedModel = nullptr;
+        ErrorStatus status;
+        hidl_handle cache1, cache2;
+        createCacheHandle({mCache1}, AccessMode::READ_ONLY, &cache1);
+        createCacheHandle({mCache2}, AccessMode::READ_ONLY, &cache2);
+        prepareModelFromCache(cache1, cache2, &preparedModel, &status);
+        ASSERT_EQ(status, ErrorStatus::GENERAL_FAILURE);
+        ASSERT_EQ(preparedModel, nullptr);
+    }
+}
+
+TEST_P(CompilationCachingSecurityTest, WrongToken) {
+    if (!mIsCachingSupported) return;
+
+    // Create test HIDL model and compile.
+    Model testModel = createTestModel();
+    sp<IPreparedModel> preparedModel = nullptr;
+    generated_tests::PrepareModel(device, testModel, &preparedModel);
+    // Terminate early if the driver cannot prepare the model.
+    if (preparedModel == nullptr) return;
+
+    // Save the compilation to cache.
+    {
+        ErrorStatus status;
+        hidl_handle cache1, cache2;
+        createCacheHandle({mCache1}, AccessMode::WRITE_ONLY, &cache1);
+        createCacheHandle({mCache2}, AccessMode::WRITE_ONLY, &cache2);
+        saveModelToCache(preparedModel, cache1, cache2, &status);
+        if (checkEarlyTermination(status)) return;
+        ASSERT_EQ(status, ErrorStatus::NONE);
+    }
+
+    // Randomly flip one single bit in mToken.
+    uint32_t ind = getRandomInt(0u, static_cast<uint32_t>(Constant::BYTE_SIZE_OF_CACHE_TOKEN) - 1);
+    mToken[ind] ^= (1U << getRandomInt(0, 7));
+
+    // Retrieve the preparedModel from cache, expect failure.
+    {
+        preparedModel = nullptr;
+        ErrorStatus status;
+        hidl_handle cache1, cache2;
+        createCacheHandle({mCache1}, AccessMode::READ_ONLY, &cache1);
+        createCacheHandle({mCache2}, AccessMode::READ_ONLY, &cache2);
+        prepareModelFromCache(cache1, cache2, &preparedModel, &status);
+        ASSERT_EQ(status, ErrorStatus::GENERAL_FAILURE);
+        ASSERT_EQ(preparedModel, nullptr);
+    }
+}
+
+INSTANTIATE_TEST_CASE_P(TestCompilationCaching, CompilationCachingSecurityTest,
+                        ::testing::Range(0U, 10U));
+
+}  // namespace functional
+}  // namespace vts
+}  // namespace V1_2
+}  // namespace neuralnetworks
+}  // namespace hardware
+}  // namespace android
diff --git a/neuralnetworks/1.2/vts/functional/GeneratedTests.cpp b/neuralnetworks/1.2/vts/functional/GeneratedTests.cpp
index 4bc891f..2c3287a 100644
--- a/neuralnetworks/1.2/vts/functional/GeneratedTests.cpp
+++ b/neuralnetworks/1.2/vts/functional/GeneratedTests.cpp
@@ -19,6 +19,7 @@
 #include "VtsHalNeuralnetworks.h"
 
 #include "Callbacks.h"
+#include "GeneratedTestHarness.h"
 #include "TestHarness.h"
 #include "Utils.h"
 
@@ -29,14 +30,6 @@
 namespace android {
 namespace hardware {
 namespace neuralnetworks {
-
-namespace generated_tests {
-using ::test_helper::MixedTypedExample;
-extern void Execute(const sp<V1_2::IDevice>&, std::function<V1_2::Model(void)>,
-                    std::function<bool(int)>, const std::vector<MixedTypedExample>&,
-                    bool testDynamicOutputShape = false);
-}  // namespace generated_tests
-
 namespace V1_2 {
 namespace vts {
 namespace functional {
diff --git a/neuralnetworks/1.2/vts/functional/GeneratedTestsV1_0.cpp b/neuralnetworks/1.2/vts/functional/GeneratedTestsV1_0.cpp
index 956926a..990cab9 100644
--- a/neuralnetworks/1.2/vts/functional/GeneratedTestsV1_0.cpp
+++ b/neuralnetworks/1.2/vts/functional/GeneratedTestsV1_0.cpp
@@ -19,6 +19,7 @@
 #include "VtsHalNeuralnetworks.h"
 
 #include "Callbacks.h"
+#include "GeneratedTestHarness.h"
 #include "TestHarness.h"
 #include "Utils.h"
 
@@ -29,14 +30,6 @@
 namespace android {
 namespace hardware {
 namespace neuralnetworks {
-
-namespace generated_tests {
-using ::test_helper::MixedTypedExample;
-extern void Execute(const sp<V1_2::IDevice>&, std::function<V1_2::Model(void)>,
-                    std::function<bool(int)>, const std::vector<MixedTypedExample>&,
-                    bool testDynamicOutputShape = false);
-}  // namespace generated_tests
-
 namespace V1_2 {
 namespace vts {
 namespace functional {
diff --git a/neuralnetworks/1.2/vts/functional/GeneratedTestsV1_1.cpp b/neuralnetworks/1.2/vts/functional/GeneratedTestsV1_1.cpp
index 425690f..fa6d54d 100644
--- a/neuralnetworks/1.2/vts/functional/GeneratedTestsV1_1.cpp
+++ b/neuralnetworks/1.2/vts/functional/GeneratedTestsV1_1.cpp
@@ -19,6 +19,7 @@
 #include "VtsHalNeuralnetworks.h"
 
 #include "Callbacks.h"
+#include "GeneratedTestHarness.h"
 #include "TestHarness.h"
 #include "Utils.h"
 
@@ -29,14 +30,6 @@
 namespace android {
 namespace hardware {
 namespace neuralnetworks {
-
-namespace generated_tests {
-using ::test_helper::MixedTypedExample;
-extern void Execute(const sp<V1_2::IDevice>&, std::function<V1_2::Model(void)>,
-                    std::function<bool(int)>, const std::vector<MixedTypedExample>&,
-                    bool testDynamicOutputShape = false);
-}  // namespace generated_tests
-
 namespace V1_2 {
 namespace vts {
 namespace functional {
diff --git a/neuralnetworks/1.2/vts/functional/ValidateModel.cpp b/neuralnetworks/1.2/vts/functional/ValidateModel.cpp
index f3e528e..a0f11eb 100644
--- a/neuralnetworks/1.2/vts/functional/ValidateModel.cpp
+++ b/neuralnetworks/1.2/vts/functional/ValidateModel.cpp
@@ -128,10 +128,10 @@
 ///////////////////////// VALIDATE MODEL OPERAND TYPE /////////////////////////
 
 static const uint32_t invalidOperandTypes[] = {
-    static_cast<uint32_t>(OperandTypeRange::OPERAND_FUNDAMENTAL_MIN) - 1,
-    static_cast<uint32_t>(OperandTypeRange::OPERAND_FUNDAMENTAL_MAX) + 1,
-    static_cast<uint32_t>(OperandTypeRange::OPERAND_OEM_MIN) - 1,
-    static_cast<uint32_t>(OperandTypeRange::OPERAND_OEM_MAX) + 1,
+        static_cast<uint32_t>(OperandTypeRange::FUNDAMENTAL_MIN) - 1,
+        static_cast<uint32_t>(OperandTypeRange::FUNDAMENTAL_MAX) + 1,
+        static_cast<uint32_t>(OperandTypeRange::OEM_MIN) - 1,
+        static_cast<uint32_t>(OperandTypeRange::OEM_MAX) + 1,
 };
 
 static void mutateOperandTypeTest(const sp<IDevice>& device, const Model& model) {
@@ -161,6 +161,7 @@
         case OperandType::TENSOR_FLOAT32:
         case OperandType::TENSOR_INT32:
         case OperandType::TENSOR_QUANT8_ASYMM:
+        case OperandType::TENSOR_QUANT8_SYMM:
         case OperandType::TENSOR_QUANT16_ASYMM:
         case OperandType::TENSOR_QUANT16_SYMM:
         case OperandType::TENSOR_QUANT8_SYMM_PER_CHANNEL:
@@ -199,6 +200,7 @@
             return 1.0f;
         case OperandType::TENSOR_INT32:
             return -1.0f;
+        case OperandType::TENSOR_QUANT8_SYMM:
         case OperandType::TENSOR_QUANT8_ASYMM:
         case OperandType::TENSOR_QUANT16_ASYMM:
         case OperandType::TENSOR_QUANT16_SYMM:
@@ -235,6 +237,8 @@
             return {1};
         case OperandType::TENSOR_QUANT8_ASYMM:
             return {-1, 256};
+        case OperandType::TENSOR_QUANT8_SYMM:
+          return {-129, -1, 1, 128};
         case OperandType::TENSOR_QUANT16_ASYMM:
             return {-1, 65536};
         case OperandType::TENSOR_QUANT16_SYMM:
@@ -292,6 +296,7 @@
             newOperand.zeroPoint = 0;
             break;
         case OperandType::TENSOR_QUANT8_ASYMM:
+        case OperandType::TENSOR_QUANT8_SYMM:
         case OperandType::TENSOR_QUANT16_ASYMM:
         case OperandType::TENSOR_QUANT16_SYMM:
             newOperand.dimensions =
@@ -392,10 +397,10 @@
 ///////////////////////// VALIDATE MODEL OPERATION TYPE /////////////////////////
 
 static const uint32_t invalidOperationTypes[] = {
-    static_cast<uint32_t>(OperationTypeRange::OPERATION_FUNDAMENTAL_MIN) - 1,
-    static_cast<uint32_t>(OperationTypeRange::OPERATION_FUNDAMENTAL_MAX) + 1,
-    static_cast<uint32_t>(OperationTypeRange::OPERATION_OEM_MIN) - 1,
-    static_cast<uint32_t>(OperationTypeRange::OPERATION_OEM_MAX) + 1,
+        static_cast<uint32_t>(OperationTypeRange::FUNDAMENTAL_MIN) - 1,
+        static_cast<uint32_t>(OperationTypeRange::FUNDAMENTAL_MAX) + 1,
+        static_cast<uint32_t>(OperationTypeRange::OEM_MIN) - 1,
+        static_cast<uint32_t>(OperationTypeRange::OEM_MAX) + 1,
 };
 
 static void mutateOperationTypeTest(const sp<IDevice>& device, const Model& model) {
diff --git a/neuralnetworks/1.2/vts/functional/ValidateRequest.cpp b/neuralnetworks/1.2/vts/functional/ValidateRequest.cpp
index 00a7c3e..d411da4 100644
--- a/neuralnetworks/1.2/vts/functional/ValidateRequest.cpp
+++ b/neuralnetworks/1.2/vts/functional/ValidateRequest.cpp
@@ -19,6 +19,7 @@
 #include "VtsHalNeuralnetworks.h"
 
 #include "Callbacks.h"
+#include "ExecutionBurstController.h"
 #include "TestHarness.h"
 #include "Utils.h"
 
@@ -112,6 +113,7 @@
     };
     MeasureTiming measure = (hash & 1) ? MeasureTiming::YES : MeasureTiming::NO;
 
+    // asynchronous
     {
         SCOPED_TRACE(message + " [execute_1_2]");
 
@@ -131,6 +133,7 @@
         ASSERT_TRUE(badTiming(timing));
     }
 
+    // synchronous
     {
         SCOPED_TRACE(message + " [executeSynchronously]");
 
@@ -144,6 +147,43 @@
                 });
         ASSERT_TRUE(executeStatus.isOk());
     }
+
+    // burst
+    {
+        SCOPED_TRACE(message + " [burst]");
+
+        // create burst
+        std::unique_ptr<::android::nn::ExecutionBurstController> burst =
+                ::android::nn::createExecutionBurstController(preparedModel, /*blocking=*/true);
+        ASSERT_NE(nullptr, burst.get());
+
+        // create memory keys
+        std::vector<intptr_t> keys(request.pools.size());
+        for (size_t i = 0; i < keys.size(); ++i) {
+            keys[i] = reinterpret_cast<intptr_t>(&request.pools[i]);
+        }
+
+        // execute and verify
+        ErrorStatus error;
+        std::vector<OutputShape> outputShapes;
+        Timing timing;
+        std::tie(error, outputShapes, timing) = burst->compute(request, measure, keys);
+        EXPECT_EQ(ErrorStatus::INVALID_ARGUMENT, error);
+        EXPECT_EQ(outputShapes.size(), 0);
+        EXPECT_TRUE(badTiming(timing));
+
+        // additional burst testing
+        if (request.pools.size() > 0) {
+            // valid free
+            burst->freeMemory(keys.front());
+
+            // negative test: invalid free of unknown (blank) memory
+            burst->freeMemory(intptr_t{});
+
+            // negative test: double free of memory
+            burst->freeMemory(keys.front());
+        }
+    }
 }
 
 // Delete element from hidl_vec. hidl_vec doesn't support a "remove" operation,
diff --git a/power/stats/1.0/default/Android.bp b/power/stats/1.0/default/Android.bp
index b57466d..7a09639 100644
--- a/power/stats/1.0/default/Android.bp
+++ b/power/stats/1.0/default/Android.bp
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 
 cc_binary {
-    name: "android.hardware.power.stats@1.0-service",
+    name: "android.hardware.power.stats@1.0-service.mock",
     relative_install_path: "hw",
     init_rc: ["android.hardware.power.stats@1.0-service.rc"],
     srcs: ["service.cpp", "PowerStats.cpp"],
@@ -31,4 +31,5 @@
         "android.hardware.power.stats@1.0",
     ],
     vendor: true,
+    vintf_fragments: ["android.hardware.power.stats@1.0-service-mock.xml"],
 }
diff --git a/power/stats/1.0/default/PowerStats.cpp b/power/stats/1.0/default/PowerStats.cpp
index 350aa62..78766f2 100644
--- a/power/stats/1.0/default/PowerStats.cpp
+++ b/power/stats/1.0/default/PowerStats.cpp
@@ -14,6 +14,8 @@
  * limitations under the License.
  */
 
+#define LOG_TAG "android.hardware.power.stats@1.0-service-mock"
+
 #include "PowerStats.h"
 #include <android-base/file.h>
 #include <android-base/logging.h>
diff --git a/power/stats/1.0/default/android.hardware.power.stats@1.0-service-mock.xml b/power/stats/1.0/default/android.hardware.power.stats@1.0-service-mock.xml
new file mode 100644
index 0000000..dc52f66
--- /dev/null
+++ b/power/stats/1.0/default/android.hardware.power.stats@1.0-service-mock.xml
@@ -0,0 +1,11 @@
+<manifest version="1.0" type="device">
+    <hal format="hidl">
+        <name>android.hardware.power.stats</name>
+        <transport>hwbinder</transport>
+        <version>1.0</version>
+        <interface>
+            <name>IPowerStats</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+</manifest>
\ No newline at end of file
diff --git a/power/stats/1.0/default/android.hardware.power.stats@1.0-service.rc b/power/stats/1.0/default/android.hardware.power.stats@1.0-service.rc
index d7e546b..9377fc2 100644
--- a/power/stats/1.0/default/android.hardware.power.stats@1.0-service.rc
+++ b/power/stats/1.0/default/android.hardware.power.stats@1.0-service.rc
@@ -1,4 +1,5 @@
-service vendor.power.stats-hal-1-0 /vendor/bin/hw/android.hardware.power.stats@1.0-service
+service vendor.power.stats-hal-1-0-mock /vendor/bin/hw/android.hardware.power.stats@1.0-service.mock
+    interface android.hardware.power.stats@1.0::IPowerStats default
     class hal
     user system
     group system
diff --git a/power/stats/1.0/default/service.cpp b/power/stats/1.0/default/service.cpp
index a516536..8eb53e8 100644
--- a/power/stats/1.0/default/service.cpp
+++ b/power/stats/1.0/default/service.cpp
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-#define LOG_TAG "android.hardware.power.stats@1.0-service"
+#define LOG_TAG "android.hardware.power.stats@1.0-service-mock"
 
 #include <android/log.h>
 #include <hidl/HidlTransportSupport.h>
@@ -82,7 +82,7 @@
 };
 
 int main(int /* argc */, char** /* argv */) {
-    ALOGI("power.stats service 1.0 is starting.");
+    ALOGI("power.stats service 1.0 mock is starting.");
 
     PowerStats* service = new PowerStats();
     if (service == nullptr) {
diff --git a/radio/1.0/types.hal b/radio/1.0/types.hal
index 17718e0..8393cf5 100644
--- a/radio/1.0/types.hal
+++ b/radio/1.0/types.hal
@@ -1230,85 +1230,108 @@
 
 struct GsmSignalStrength {
     uint32_t signalStrength;              // Valid values are (0-61, 99) as defined in
-                                          // TS 27.007 8.69
-    uint32_t bitErrorRate;                // bit error rate (0-7, 99) as defined in TS 27.007 8.5
+                                          // TS 27.007 8.69; INT_MAX means invalid/unreported.
+    uint32_t bitErrorRate;                // bit error rate (0-7, 99) as defined in TS 27.007 8.5;
+                                          // INT_MAX means invalid/unreported.
     int32_t timingAdvance;                // Timing Advance in bit periods. 1 bit period = 48/13 us.
-                                          // INT_MAX denotes invalid value
+                                          // INT_MAX means invalid/unreported.
 };
 
 struct WcdmaSignalStrength{
     int32_t signalStrength;               // Valid values are (0-31, 99) as defined in
-                                          // TS 27.007 8.5
-    int32_t bitErrorRate;                 // bit error rate (0-7, 99) as defined in TS 27.007 8.5
+                                          // TS 27.007 8.5; INT_MAX means unreported.
+    int32_t bitErrorRate;                 // bit error rate (0-7, 99) as defined in TS 27.007 8.5;
+                                          // INT_MAX means invalid/unreported.
 };
 
 struct CdmaSignalStrength {
     uint32_t dbm;                         // This value is the actual RSSI
                                           // value multiplied by -1. Example: If the
                                           // actual RSSI is -75, then this response value will
-                                          // be 75.
+                                          // be 75. INT_MAX means invalid/unreported.
     uint32_t ecio;                        // This value is the actual
                                           // Ec/Io multiplied by -10. Example: If the
                                           // actual Ec/Io is -12.5 dB, then this response value
-                                          // will be 125.
+                                          // will be 125. INT_MAX means invalid/unreported.
 };
 
 struct EvdoSignalStrength {
     uint32_t dbm;                         // This value is the actual
                                           // RSSI value multiplied by -1.
                                           // Example: If the actual RSSI is -75,
-                                          // then this response value will be 75.
+                                          // then this response value will be 75; INT_MAX means
+                                          // invalid/unreported.
     uint32_t ecio;                        // This value is the actual
                                           // Ec/Io multiplied by -10. Example: If the
                                           // actual Ec/Io is -12.5 dB, then this response value
-                                          // will be 125.
+                                          // will be 125; INT_MAX means invalid/unreported.
     uint32_t signalNoiseRatio;            // Valid values are 0-8. 8 is the highest signal to
-                                          // noise ratio.
+                                          // noise ratio; INT_MAX means invalid/unreported.
 };
 
 struct LteSignalStrength {
     uint32_t signalStrength;              // Valid values are (0-31, 99) as defined in
-                                          // TS 27.007 8.5
+                                          // TS 27.007 8.5; INT_MAX means invalid/unreported.
     uint32_t rsrp;                        // The current Reference Signal Receive Power in dBm
                                           // multipled by -1.
-                                          // Range: 44 to 140 dBm
-                                          // INT_MAX: 0x7FFFFFFF denotes invalid value.
+                                          // Range: 44 to 140 dBm;
+                                          // INT_MAX: 0x7FFFFFFF denotes invalid/unreported value.
                                           // Reference: 3GPP TS 36.133 9.1.4
     uint32_t rsrq;                        // The current Reference Signal Receive Quality in dB
                                           // multiplied by -1.
-                                          // Range: 20 to 3 dB.
-                                          // INT_MAX: 0x7FFFFFFF denotes invalid value.
+                                          // Range: 20 to 3 dB;
+                                          // INT_MAX: 0x7FFFFFFF denotes invalid/unreported value.
                                           // Reference: 3GPP TS 36.133 9.1.7
     int32_t rssnr;                        // The current reference signal signal-to-noise ratio in
                                           // 0.1 dB units.
                                           // Range: -200 to +300 (-200 = -20.0 dB, +300 = 30dB).
-                                          // INT_MAX : 0x7FFFFFFF denotes invalid value.
+                                          // INT_MAX: 0x7FFFFFFF denotes invalid/unreported value.
                                           // Reference: 3GPP TS 36.101 8.1.1
     uint32_t cqi;                         // The current Channel Quality Indicator.
                                           // Range: 0 to 15.
-                                          // INT_MAX : 0x7FFFFFFF denotes invalid value.
+                                          // INT_MAX: 0x7FFFFFFF denotes invalid/unreported value.
                                           // Reference: 3GPP TS 36.101 9.2, 9.3, A.4
     uint32_t timingAdvance;               // timing advance in micro seconds for a one way trip
                                           // from cell to device.
                                           // Approximate distance is calculated using
                                           // 300m/us * timingAdvance.
                                           // Range: 0 to 1282 inclusive.
-                                          // INT_MAX : 0x7FFFFFFF denotes unknown value.
+                                          // INT_MAX: 0x7FFFFFFF denotes invalid/unreported value.
                                           // Reference: 3GPP 36.213 section 4.2.3
 };
 
 struct TdScdmaSignalStrength {
     uint32_t rscp;                        // The Received Signal Code Power in dBm multiplied by -1.
                                           // Range : 25 to 120
-                                          // INT_MAX: 0x7FFFFFFF denotes invalid value.
+                                          // INT_MAX: 0x7FFFFFFF denotes invalid/unreported value.
                                           // Reference: 3GPP TS 25.123, section 9.1.1.1
 };
 
 struct SignalStrength {
+    /**
+     * If GSM measurements are provided, this structure must contain valid measurements; otherwise
+     * all fields should be set to INT_MAX to mark them as invalid.
+     */
     GsmSignalStrength gw;
+    /**
+     * If CDMA measurements are provided, this structure must contain valid measurements; otherwise
+     * all fields should be set to INT_MAX to mark them as invalid.
+     */
     CdmaSignalStrength cdma;
+    /**
+     * If EvDO measurements are provided, this structure must contain valid measurements; otherwise
+     * all fields should be set to INT_MAX to mark them as invalid.
+     */
     EvdoSignalStrength evdo;
+    /**
+     * If LTE measurements are provided, this structure must contain valid measurements; otherwise
+     * all fields should be set to INT_MAX to mark them as invalid.
+     */
     LteSignalStrength lte;
+    /**
+     * If TD-SCDMA measurements are provided, this structure must contain valid measurements;
+     * otherwise all fields should be set to INT_MAX to mark them as invalid.
+     */
     TdScdmaSignalStrength tdScdma;
 };
 
diff --git a/radio/1.2/types.hal b/radio/1.2/types.hal
index 4715fac..2dceeb1 100644
--- a/radio/1.2/types.hal
+++ b/radio/1.2/types.hal
@@ -427,11 +427,13 @@
     /**
      * CPICH RSCP as defined in TS 25.215 5.1.1
      * Valid values are (0-96, 255) as defined in TS 27.007 8.69
+     * INT_MAX denotes that the value is invalid/unreported.
      */
     uint32_t rscp;
     /**
      * Ec/No value as defined in TS 25.215 5.1.5
      * Valid values are (0-49, 255) as defined in TS 27.007 8.69
+     * INT_MAX denotes that the value is invalid/unreported.
      */
     uint32_t ecno;
 
@@ -441,26 +443,53 @@
     /**
      * UTRA carrier RSSI as defined in TS 25.225 5.1.4
      * Valid values are (0-31, 99) as defined in TS 27.007 8.5
+     * INT_MAX denotes that the value is invalid/unreported.
      */
     uint32_t signalStrength;
     /**
      * Transport Channel BER as defined in TS 25.225 5.2.5
      * Valid values are (0-7, 99) as defined in TS 27.007 8.5
+     * INT_MAX denotes that the value is invalid/unreported.
      */
     uint32_t bitErrorRate;
     /**
      * P-CCPCH RSCP as defined in TS 25.225 5.1.1
      * Valid values are (0-96, 255) as defined in TS 27.007 8.69
+     * INT_MAX denotes that the value is invalid/unreported.
      */
     uint32_t rscp;
 };
 
 struct SignalStrength {
+    /**
+     * If GSM measurements are provided, this structure must contain valid measurements; otherwise
+     * all fields should be set to INT_MAX to mark them as invalid.
+     */
     GsmSignalStrength gsm;
+    /**
+     * If CDMA measurements are provided, this structure must contain valid measurements; otherwise
+     * all fields should be set to INT_MAX to mark them as invalid.
+     */
     CdmaSignalStrength cdma;
+    /**
+     * If EvDO measurements are provided, this structure must contain valid measurements; otherwise
+     * all fields should be set to INT_MAX to mark them as invalid.
+     */
     EvdoSignalStrength evdo;
+    /**
+     * If LTE measurements are provided, this structure must contain valid measurements; otherwise
+     * all fields should be set to INT_MAX to mark them as invalid.
+     */
     LteSignalStrength lte;
+    /**
+     * If TD-SCDMA measurements are provided, this structure must contain valid measurements;
+     * otherwise all fields should be set to INT_MAX to mark them as invalid.
+     */
     TdScdmaSignalStrength tdScdma;
+    /**
+     * If WCDMA measurements are provided, this structure must contain valid measurements; otherwise
+     * all fields should be set to INT_MAX to mark them as invalid.
+     */
     WcdmaSignalStrength wcdma;
 };
 
diff --git a/radio/1.4/vts/OWNERS b/radio/1.4/vts/OWNERS
new file mode 100644
index 0000000..fd69f36
--- /dev/null
+++ b/radio/1.4/vts/OWNERS
@@ -0,0 +1,8 @@
+# Telephony team
+amitmahajan@google.com
+shuoq@google.com
+sasindran@google.com
+
+# VTS team
+yuexima@google.com
+yim@google.com
\ No newline at end of file
diff --git a/radio/1.4/vts/functional/Android.bp b/radio/1.4/vts/functional/Android.bp
new file mode 100644
index 0000000..2d0e089
--- /dev/null
+++ b/radio/1.4/vts/functional/Android.bp
@@ -0,0 +1,37 @@
+//
+// Copyright (C) 2018 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+cc_test {
+    name: "VtsHalRadioV1_4TargetTest",
+    defaults: ["VtsHalTargetTestDefaults"],
+    srcs: [
+        "radio_hidl_hal_api.cpp",
+        "radio_hidl_hal_test.cpp",
+        "radio_response.cpp",
+        "radio_indication.cpp",
+        "VtsHalRadioV1_4TargetTest.cpp",
+    ],
+    static_libs: [
+        "RadioVtsTestUtilBase",
+        "android.hardware.radio@1.4",
+        "android.hardware.radio@1.3",
+        "android.hardware.radio@1.2",
+        "android.hardware.radio@1.1",
+        "android.hardware.radio@1.0",
+    ],
+    header_libs: ["radio.util.header@1.0"],
+    test_suites: ["general-tests"]
+}
\ No newline at end of file
diff --git a/radio/1.4/vts/functional/VtsHalRadioV1_4TargetTest.cpp b/radio/1.4/vts/functional/VtsHalRadioV1_4TargetTest.cpp
new file mode 100644
index 0000000..d6330e6
--- /dev/null
+++ b/radio/1.4/vts/functional/VtsHalRadioV1_4TargetTest.cpp
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <radio_hidl_hal_utils_v1_4.h>
+
+int main(int argc, char** argv) {
+    ::testing::AddGlobalTestEnvironment(RadioHidlEnvironment::Instance());
+    ::testing::InitGoogleTest(&argc, argv);
+    RadioHidlEnvironment::Instance()->init(&argc, argv);
+    int status = RUN_ALL_TESTS();
+    LOG(INFO) << "Test result = " << status;
+    return status;
+}
\ No newline at end of file
diff --git a/radio/1.4/vts/functional/radio_hidl_hal_api.cpp b/radio/1.4/vts/functional/radio_hidl_hal_api.cpp
new file mode 100644
index 0000000..6b1f85e
--- /dev/null
+++ b/radio/1.4/vts/functional/radio_hidl_hal_api.cpp
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <radio_hidl_hal_utils_v1_4.h>
+
+#define ASSERT_OK(ret) ASSERT_TRUE(ret.isOk())
\ No newline at end of file
diff --git a/radio/1.4/vts/functional/radio_hidl_hal_test.cpp b/radio/1.4/vts/functional/radio_hidl_hal_test.cpp
new file mode 100644
index 0000000..4d80696
--- /dev/null
+++ b/radio/1.4/vts/functional/radio_hidl_hal_test.cpp
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <radio_hidl_hal_utils_v1_4.h>
+
+void RadioHidlTest_v1_4::SetUp() {
+    radio_v1_4 = ::testing::VtsHalHidlTargetTestBase::getService<
+            ::android::hardware::radio::V1_4::IRadio>(
+            RadioHidlEnvironment::Instance()
+                    ->getServiceName<::android::hardware::radio::V1_4::IRadio>(
+                            hidl_string(RADIO_SERVICE_NAME)));
+    if (radio_v1_4 == NULL) {
+        sleep(60);
+        radio_v1_4 = ::testing::VtsHalHidlTargetTestBase::getService<
+                ::android::hardware::radio::V1_4::IRadio>(
+                RadioHidlEnvironment::Instance()
+                        ->getServiceName<::android::hardware::radio::V1_4::IRadio>(
+                                hidl_string(RADIO_SERVICE_NAME)));
+    }
+    ASSERT_NE(nullptr, radio_v1_4.get());
+
+    radioRsp_v1_4 = new (std::nothrow) RadioResponse_v1_4(*this);
+    ASSERT_NE(nullptr, radioRsp_v1_4.get());
+
+    count_ = 0;
+
+    radioInd_v1_4 = new (std::nothrow) RadioIndication_v1_4(*this);
+    ASSERT_NE(nullptr, radioInd_v1_4.get());
+
+    radio_v1_4->setResponseFunctions(radioRsp_v1_4, radioInd_v1_4);
+
+    updateSimCardStatus();
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_4->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_v1_4->rspInfo.serial);
+    EXPECT_EQ(RadioError::NONE, radioRsp_v1_4->rspInfo.error);
+
+    /* Enforce Vts Testing with Sim Status Present only. */
+    EXPECT_EQ(CardState::PRESENT, cardStatus.base.base.cardState);
+}
+
+/*
+ * Notify that the response message is received.
+ */
+void RadioHidlTest_v1_4::notify(int receivedSerial) {
+    std::unique_lock<std::mutex> lock(mtx_);
+    if (serial == receivedSerial) {
+        count_++;
+        cv_.notify_one();
+    }
+}
+
+/*
+ * Wait till the response message is notified or till TIMEOUT_PERIOD.
+ */
+std::cv_status RadioHidlTest_v1_4::wait() {
+    std::unique_lock<std::mutex> lock(mtx_);
+
+    std::cv_status status = std::cv_status::no_timeout;
+    auto now = std::chrono::system_clock::now();
+    while (count_ == 0) {
+        status = cv_.wait_until(lock, now + std::chrono::seconds(TIMEOUT_PERIOD));
+        if (status == std::cv_status::timeout) {
+            return status;
+        }
+    }
+    count_--;
+    return status;
+}
+
+void RadioHidlTest_v1_4::updateSimCardStatus() {
+    serial = GetRandomSerialNumber();
+    radio_v1_4->getIccCardStatus(serial);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+}
\ No newline at end of file
diff --git a/radio/1.4/vts/functional/radio_hidl_hal_utils_v1_4.h b/radio/1.4/vts/functional/radio_hidl_hal_utils_v1_4.h
new file mode 100644
index 0000000..f290d5d
--- /dev/null
+++ b/radio/1.4/vts/functional/radio_hidl_hal_utils_v1_4.h
@@ -0,0 +1,733 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <android-base/logging.h>
+
+#include <VtsHalHidlTargetTestBase.h>
+#include <VtsHalHidlTargetTestEnvBase.h>
+#include <chrono>
+#include <condition_variable>
+#include <mutex>
+
+#include <android/hardware/radio/1.4/IRadio.h>
+#include <android/hardware/radio/1.4/IRadioIndication.h>
+#include <android/hardware/radio/1.4/IRadioResponse.h>
+#include <android/hardware/radio/1.4/types.h>
+
+#include "vts_test_util.h"
+
+using namespace ::android::hardware::radio::V1_4;
+using namespace ::android::hardware::radio::V1_3;
+using namespace ::android::hardware::radio::V1_2;
+using namespace ::android::hardware::radio::V1_1;
+using namespace ::android::hardware::radio::V1_0;
+
+using ::android::sp;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+
+#define TIMEOUT_PERIOD 75
+#define RADIO_SERVICE_NAME "slot1"
+
+class RadioHidlTest_v1_4;
+extern ::android::hardware::radio::V1_4::CardStatus cardStatus;
+
+/* Callback class for radio respons v1_4 */
+class RadioResponse_v1_4 : public ::android::hardware::radio::V1_4::IRadioResponse {
+   protected:
+    RadioHidlTest_v1_4& parent_v1_4;
+
+   public:
+    hidl_vec<RadioBandMode> radioBandModes;
+
+    RadioResponseInfo rspInfo;
+
+    // Modem
+    bool isModemEnabled;
+    bool enableModemResponseToggle;
+
+    // Data
+    ::android::hardware::radio::V1_4::DataRegStateResult dataRegResp;
+
+    RadioResponse_v1_4(RadioHidlTest_v1_4& parent_v1_4);
+    virtual ~RadioResponse_v1_4() = default;
+
+    Return<void> getIccCardStatusResponse(
+            const RadioResponseInfo& info,
+            const ::android::hardware::radio::V1_0::CardStatus& cardStatus);
+
+    Return<void> supplyIccPinForAppResponse(const RadioResponseInfo& info,
+                                            int32_t remainingRetries);
+
+    Return<void> supplyIccPukForAppResponse(const RadioResponseInfo& info,
+                                            int32_t remainingRetries);
+
+    Return<void> supplyIccPin2ForAppResponse(const RadioResponseInfo& info,
+                                             int32_t remainingRetries);
+
+    Return<void> supplyIccPuk2ForAppResponse(const RadioResponseInfo& info,
+                                             int32_t remainingRetries);
+
+    Return<void> changeIccPinForAppResponse(const RadioResponseInfo& info,
+                                            int32_t remainingRetries);
+
+    Return<void> changeIccPin2ForAppResponse(const RadioResponseInfo& info,
+                                             int32_t remainingRetries);
+
+    Return<void> supplyNetworkDepersonalizationResponse(const RadioResponseInfo& info,
+                                                        int32_t remainingRetries);
+
+    Return<void> getCurrentCallsResponse(
+            const RadioResponseInfo& info,
+            const ::android::hardware::hidl_vec<::android::hardware::radio::V1_0::Call>& calls);
+
+    Return<void> dialResponse(const RadioResponseInfo& info);
+
+    Return<void> getIMSIForAppResponse(const RadioResponseInfo& info,
+                                       const ::android::hardware::hidl_string& imsi);
+
+    Return<void> hangupConnectionResponse(const RadioResponseInfo& info);
+
+    Return<void> hangupWaitingOrBackgroundResponse(const RadioResponseInfo& info);
+
+    Return<void> hangupForegroundResumeBackgroundResponse(const RadioResponseInfo& info);
+
+    Return<void> switchWaitingOrHoldingAndActiveResponse(const RadioResponseInfo& info);
+
+    Return<void> conferenceResponse(const RadioResponseInfo& info);
+
+    Return<void> rejectCallResponse(const RadioResponseInfo& info);
+
+    Return<void> getLastCallFailCauseResponse(const RadioResponseInfo& info,
+                                              const LastCallFailCauseInfo& failCauseInfo);
+
+    Return<void> getSignalStrengthResponse(
+            const RadioResponseInfo& info,
+            const ::android::hardware::radio::V1_0::SignalStrength& sigStrength);
+
+    Return<void> getVoiceRegistrationStateResponse(
+            const RadioResponseInfo& info,
+            const ::android::hardware::radio::V1_0::VoiceRegStateResult& voiceRegResponse);
+
+    Return<void> getDataRegistrationStateResponse(
+            const RadioResponseInfo& info,
+            const ::android::hardware::radio::V1_0::DataRegStateResult& dataRegResponse);
+
+    Return<void> getOperatorResponse(const RadioResponseInfo& info,
+                                     const ::android::hardware::hidl_string& longName,
+                                     const ::android::hardware::hidl_string& shortName,
+                                     const ::android::hardware::hidl_string& numeric);
+
+    Return<void> setRadioPowerResponse(const RadioResponseInfo& info);
+
+    Return<void> sendDtmfResponse(const RadioResponseInfo& info);
+
+    Return<void> sendSmsResponse(const RadioResponseInfo& info, const SendSmsResult& sms);
+
+    Return<void> sendSMSExpectMoreResponse(const RadioResponseInfo& info, const SendSmsResult& sms);
+
+    Return<void> setupDataCallResponse(
+            const RadioResponseInfo& info,
+            const android::hardware::radio::V1_0::SetupDataCallResult& dcResponse);
+
+    Return<void> iccIOForAppResponse(const RadioResponseInfo& info, const IccIoResult& iccIo);
+
+    Return<void> sendUssdResponse(const RadioResponseInfo& info);
+
+    Return<void> cancelPendingUssdResponse(const RadioResponseInfo& info);
+
+    Return<void> getClirResponse(const RadioResponseInfo& info, int32_t n, int32_t m);
+
+    Return<void> setClirResponse(const RadioResponseInfo& info);
+
+    Return<void> getCallForwardStatusResponse(
+            const RadioResponseInfo& info,
+            const ::android::hardware::hidl_vec<CallForwardInfo>& call_forwardInfos);
+
+    Return<void> setCallForwardResponse(const RadioResponseInfo& info);
+
+    Return<void> getCallWaitingResponse(const RadioResponseInfo& info, bool enable,
+                                        int32_t serviceClass);
+
+    Return<void> setCallWaitingResponse(const RadioResponseInfo& info);
+
+    Return<void> acknowledgeLastIncomingGsmSmsResponse(const RadioResponseInfo& info);
+
+    Return<void> acceptCallResponse(const RadioResponseInfo& info);
+
+    Return<void> deactivateDataCallResponse(const RadioResponseInfo& info);
+
+    Return<void> getFacilityLockForAppResponse(const RadioResponseInfo& info, int32_t response);
+
+    Return<void> setFacilityLockForAppResponse(const RadioResponseInfo& info, int32_t retry);
+
+    Return<void> setBarringPasswordResponse(const RadioResponseInfo& info);
+
+    Return<void> getNetworkSelectionModeResponse(const RadioResponseInfo& info, bool manual);
+
+    Return<void> setNetworkSelectionModeAutomaticResponse(const RadioResponseInfo& info);
+
+    Return<void> setNetworkSelectionModeManualResponse(const RadioResponseInfo& info);
+
+    Return<void> getAvailableNetworksResponse(
+            const RadioResponseInfo& info,
+            const ::android::hardware::hidl_vec<OperatorInfo>& networkInfos);
+
+    Return<void> startDtmfResponse(const RadioResponseInfo& info);
+
+    Return<void> stopDtmfResponse(const RadioResponseInfo& info);
+
+    Return<void> getBasebandVersionResponse(const RadioResponseInfo& info,
+                                            const ::android::hardware::hidl_string& version);
+
+    Return<void> separateConnectionResponse(const RadioResponseInfo& info);
+
+    Return<void> setMuteResponse(const RadioResponseInfo& info);
+
+    Return<void> getMuteResponse(const RadioResponseInfo& info, bool enable);
+
+    Return<void> getClipResponse(const RadioResponseInfo& info, ClipStatus status);
+
+    Return<void> getDataCallListResponse(
+            const RadioResponseInfo& info,
+            const ::android::hardware::hidl_vec<
+                    android::hardware::radio::V1_0::SetupDataCallResult>& dcResponse);
+
+    Return<void> sendOemRilRequestRawResponse(const RadioResponseInfo& info,
+                                              const ::android::hardware::hidl_vec<uint8_t>& data);
+
+    Return<void> sendOemRilRequestStringsResponse(
+            const RadioResponseInfo& info,
+            const ::android::hardware::hidl_vec<::android::hardware::hidl_string>& data);
+
+    Return<void> setSuppServiceNotificationsResponse(const RadioResponseInfo& info);
+
+    Return<void> writeSmsToSimResponse(const RadioResponseInfo& info, int32_t index);
+
+    Return<void> deleteSmsOnSimResponse(const RadioResponseInfo& info);
+
+    Return<void> setBandModeResponse(const RadioResponseInfo& info);
+
+    Return<void> getAvailableBandModesResponse(
+            const RadioResponseInfo& info,
+            const ::android::hardware::hidl_vec<RadioBandMode>& bandModes);
+
+    Return<void> sendEnvelopeResponse(const RadioResponseInfo& info,
+                                      const ::android::hardware::hidl_string& commandResponse);
+
+    Return<void> sendTerminalResponseToSimResponse(const RadioResponseInfo& info);
+
+    Return<void> handleStkCallSetupRequestFromSimResponse(const RadioResponseInfo& info);
+
+    Return<void> explicitCallTransferResponse(const RadioResponseInfo& info);
+
+    Return<void> setPreferredNetworkTypeResponse(const RadioResponseInfo& info);
+
+    Return<void> getPreferredNetworkTypeResponse(const RadioResponseInfo& info,
+                                                 PreferredNetworkType nwType);
+
+    Return<void> getNeighboringCidsResponse(
+            const RadioResponseInfo& info,
+            const ::android::hardware::hidl_vec<NeighboringCell>& cells);
+
+    Return<void> setLocationUpdatesResponse(const RadioResponseInfo& info);
+
+    Return<void> setCdmaSubscriptionSourceResponse(const RadioResponseInfo& info);
+
+    Return<void> setCdmaRoamingPreferenceResponse(const RadioResponseInfo& info);
+
+    Return<void> getCdmaRoamingPreferenceResponse(const RadioResponseInfo& info,
+                                                  CdmaRoamingType type);
+
+    Return<void> setTTYModeResponse(const RadioResponseInfo& info);
+
+    Return<void> getTTYModeResponse(const RadioResponseInfo& info, TtyMode mode);
+
+    Return<void> setPreferredVoicePrivacyResponse(const RadioResponseInfo& info);
+
+    Return<void> getPreferredVoicePrivacyResponse(const RadioResponseInfo& info, bool enable);
+
+    Return<void> sendCDMAFeatureCodeResponse(const RadioResponseInfo& info);
+
+    Return<void> sendBurstDtmfResponse(const RadioResponseInfo& info);
+
+    Return<void> sendCdmaSmsResponse(const RadioResponseInfo& info, const SendSmsResult& sms);
+
+    Return<void> acknowledgeLastIncomingCdmaSmsResponse(const RadioResponseInfo& info);
+
+    Return<void> getGsmBroadcastConfigResponse(
+            const RadioResponseInfo& info,
+            const ::android::hardware::hidl_vec<GsmBroadcastSmsConfigInfo>& configs);
+
+    Return<void> setGsmBroadcastConfigResponse(const RadioResponseInfo& info);
+
+    Return<void> setGsmBroadcastActivationResponse(const RadioResponseInfo& info);
+
+    Return<void> getCdmaBroadcastConfigResponse(
+            const RadioResponseInfo& info,
+            const ::android::hardware::hidl_vec<CdmaBroadcastSmsConfigInfo>& configs);
+
+    Return<void> setCdmaBroadcastConfigResponse(const RadioResponseInfo& info);
+
+    Return<void> setCdmaBroadcastActivationResponse(const RadioResponseInfo& info);
+
+    Return<void> getCDMASubscriptionResponse(const RadioResponseInfo& info,
+                                             const ::android::hardware::hidl_string& mdn,
+                                             const ::android::hardware::hidl_string& hSid,
+                                             const ::android::hardware::hidl_string& hNid,
+                                             const ::android::hardware::hidl_string& min,
+                                             const ::android::hardware::hidl_string& prl);
+
+    Return<void> writeSmsToRuimResponse(const RadioResponseInfo& info, uint32_t index);
+
+    Return<void> deleteSmsOnRuimResponse(const RadioResponseInfo& info);
+
+    Return<void> getDeviceIdentityResponse(const RadioResponseInfo& info,
+                                           const ::android::hardware::hidl_string& imei,
+                                           const ::android::hardware::hidl_string& imeisv,
+                                           const ::android::hardware::hidl_string& esn,
+                                           const ::android::hardware::hidl_string& meid);
+
+    Return<void> exitEmergencyCallbackModeResponse(const RadioResponseInfo& info);
+
+    Return<void> getSmscAddressResponse(const RadioResponseInfo& info,
+                                        const ::android::hardware::hidl_string& smsc);
+
+    Return<void> setSmscAddressResponse(const RadioResponseInfo& info);
+
+    Return<void> reportSmsMemoryStatusResponse(const RadioResponseInfo& info);
+
+    Return<void> reportStkServiceIsRunningResponse(const RadioResponseInfo& info);
+
+    Return<void> getCdmaSubscriptionSourceResponse(const RadioResponseInfo& info,
+                                                   CdmaSubscriptionSource source);
+
+    Return<void> requestIsimAuthenticationResponse(
+            const RadioResponseInfo& info, const ::android::hardware::hidl_string& response);
+
+    Return<void> acknowledgeIncomingGsmSmsWithPduResponse(const RadioResponseInfo& info);
+
+    Return<void> sendEnvelopeWithStatusResponse(const RadioResponseInfo& info,
+                                                const IccIoResult& iccIo);
+
+    Return<void> getVoiceRadioTechnologyResponse(
+            const RadioResponseInfo& info, ::android::hardware::radio::V1_0::RadioTechnology rat);
+
+    Return<void> getCellInfoListResponse(
+            const RadioResponseInfo& info,
+            const ::android::hardware::hidl_vec<::android::hardware::radio::V1_0::CellInfo>&
+                    cellInfo);
+
+    Return<void> setCellInfoListRateResponse(const RadioResponseInfo& info);
+
+    Return<void> setInitialAttachApnResponse(const RadioResponseInfo& info);
+
+    Return<void> getImsRegistrationStateResponse(const RadioResponseInfo& info, bool isRegistered,
+                                                 RadioTechnologyFamily ratFamily);
+
+    Return<void> sendImsSmsResponse(const RadioResponseInfo& info, const SendSmsResult& sms);
+
+    Return<void> iccTransmitApduBasicChannelResponse(const RadioResponseInfo& info,
+                                                     const IccIoResult& result);
+
+    Return<void> iccOpenLogicalChannelResponse(
+            const RadioResponseInfo& info, int32_t channelId,
+            const ::android::hardware::hidl_vec<int8_t>& selectResponse);
+
+    Return<void> iccCloseLogicalChannelResponse(const RadioResponseInfo& info);
+
+    Return<void> iccTransmitApduLogicalChannelResponse(const RadioResponseInfo& info,
+                                                       const IccIoResult& result);
+
+    Return<void> nvReadItemResponse(const RadioResponseInfo& info,
+                                    const ::android::hardware::hidl_string& result);
+
+    Return<void> nvWriteItemResponse(const RadioResponseInfo& info);
+
+    Return<void> nvWriteCdmaPrlResponse(const RadioResponseInfo& info);
+
+    Return<void> nvResetConfigResponse(const RadioResponseInfo& info);
+
+    Return<void> setUiccSubscriptionResponse(const RadioResponseInfo& info);
+
+    Return<void> setDataAllowedResponse(const RadioResponseInfo& info);
+
+    Return<void> getHardwareConfigResponse(
+            const RadioResponseInfo& info,
+            const ::android::hardware::hidl_vec<HardwareConfig>& config);
+
+    Return<void> requestIccSimAuthenticationResponse(const RadioResponseInfo& info,
+                                                     const IccIoResult& result);
+
+    Return<void> setDataProfileResponse(const RadioResponseInfo& info);
+
+    Return<void> requestShutdownResponse(const RadioResponseInfo& info);
+
+    Return<void> getRadioCapabilityResponse(
+            const RadioResponseInfo& info,
+            const android::hardware::radio::V1_0::RadioCapability& rc);
+
+    Return<void> setRadioCapabilityResponse(
+            const RadioResponseInfo& info,
+            const android::hardware::radio::V1_0::RadioCapability& rc);
+
+    Return<void> startLceServiceResponse(const RadioResponseInfo& info,
+                                         const LceStatusInfo& statusInfo);
+
+    Return<void> stopLceServiceResponse(const RadioResponseInfo& info,
+                                        const LceStatusInfo& statusInfo);
+
+    Return<void> pullLceDataResponse(const RadioResponseInfo& info, const LceDataInfo& lceInfo);
+
+    Return<void> getModemActivityInfoResponse(const RadioResponseInfo& info,
+                                              const ActivityStatsInfo& activityInfo);
+
+    Return<void> setAllowedCarriersResponse(const RadioResponseInfo& info, int32_t numAllowed);
+
+    Return<void> getAllowedCarriersResponse(const RadioResponseInfo& info, bool allAllowed,
+                                            const CarrierRestrictions& carriers);
+
+    Return<void> sendDeviceStateResponse(const RadioResponseInfo& info);
+
+    Return<void> setIndicationFilterResponse(const RadioResponseInfo& info);
+
+    Return<void> setSimCardPowerResponse(const RadioResponseInfo& info);
+
+    Return<void> acknowledgeRequest(int32_t serial);
+
+    /* 1.1 Api */
+    Return<void> setCarrierInfoForImsiEncryptionResponse(const RadioResponseInfo& info);
+
+    Return<void> setSimCardPowerResponse_1_1(const RadioResponseInfo& info);
+
+    Return<void> startNetworkScanResponse(const RadioResponseInfo& info);
+
+    Return<void> stopNetworkScanResponse(const RadioResponseInfo& info);
+
+    Return<void> startKeepaliveResponse(const RadioResponseInfo& info,
+                                        const KeepaliveStatus& status);
+
+    Return<void> stopKeepaliveResponse(const RadioResponseInfo& info);
+
+    /* 1.2 Api */
+    Return<void> setSignalStrengthReportingCriteriaResponse(const RadioResponseInfo& info);
+
+    Return<void> setLinkCapacityReportingCriteriaResponse(const RadioResponseInfo& info);
+
+    Return<void> getIccCardStatusResponse_1_2(
+            const RadioResponseInfo& info,
+            const ::android::hardware::radio::V1_2::CardStatus& card_status);
+
+    Return<void> getCurrentCallsResponse_1_2(
+            const RadioResponseInfo& info,
+            const ::android::hardware::hidl_vec<::android::hardware::radio::V1_2::Call>& calls);
+
+    Return<void> getSignalStrengthResponse_1_2(
+            const RadioResponseInfo& info,
+            const ::android::hardware::radio::V1_2::SignalStrength& sig_strength);
+
+    Return<void> getCellInfoListResponse_1_2(
+            const RadioResponseInfo& info,
+            const ::android::hardware::hidl_vec<::android::hardware::radio::V1_2::CellInfo>&
+                    cellInfo);
+
+    Return<void> getVoiceRegistrationStateResponse_1_2(
+            const RadioResponseInfo& info,
+            const ::android::hardware::radio::V1_2::VoiceRegStateResult& voiceRegResponse);
+
+    Return<void> getDataRegistrationStateResponse_1_2(
+            const RadioResponseInfo& info,
+            const ::android::hardware::radio::V1_2::DataRegStateResult& dataRegResponse);
+
+    /* 1.3 Api */
+    Return<void> setSystemSelectionChannelsResponse(const RadioResponseInfo& info);
+
+    Return<void> enableModemResponse(const RadioResponseInfo& info);
+
+    Return<void> getModemStackStatusResponse(const RadioResponseInfo& info, const bool enabled);
+
+    /* 1.4 Api */
+    Return<void> emergencyDialResponse(const RadioResponseInfo& info);
+
+    Return<void> startNetworkScanResponse_1_4(const RadioResponseInfo& info);
+
+    Return<void> getCellInfoListResponse_1_4(
+            const RadioResponseInfo& info,
+            const ::android::hardware::hidl_vec<::android::hardware::radio::V1_4::CellInfo>&
+                    cellInfo);
+
+    Return<void> getDataRegistrationStateResponse_1_4(
+            const RadioResponseInfo& info,
+            const ::android::hardware::radio::V1_4::DataRegStateResult& dataRegResponse);
+
+    Return<void> getIccCardStatusResponse_1_4(
+            const RadioResponseInfo& info,
+            const ::android::hardware::radio::V1_4::CardStatus& card_status);
+
+    Return<void> getPreferredNetworkTypeBitmapResponse(
+            const RadioResponseInfo& info,
+            const ::android::hardware::hidl_bitfield<
+                    ::android::hardware::radio::V1_4::RadioAccessFamily>
+                    networkTypeBitmap);
+
+    Return<void> setPreferredNetworkTypeBitmapResponse(const RadioResponseInfo& info);
+
+    Return<void> getDataCallListResponse_1_4(
+            const RadioResponseInfo& info,
+            const ::android::hardware::hidl_vec<
+                    ::android::hardware::radio::V1_4::SetupDataCallResult>& dcResponse);
+
+    Return<void> setupDataCallResponse_1_4(
+            const RadioResponseInfo& info,
+            const android::hardware::radio::V1_4::SetupDataCallResult& dcResponse);
+
+    Return<void> setAllowedCarriersResponse_1_4(const RadioResponseInfo& info);
+
+    Return<void> getAllowedCarriersResponse_1_4(const RadioResponseInfo& info,
+                                                const CarrierRestrictionsWithPriority& carriers,
+                                                SimLockMultiSimPolicy multiSimPolicy);
+};
+
+/* Callback class for radio indication */
+class RadioIndication_v1_4 : public ::android::hardware::radio::V1_4::IRadioIndication {
+   protected:
+    RadioHidlTest_v1_4& parent_v1_4;
+
+   public:
+    RadioIndication_v1_4(RadioHidlTest_v1_4& parent_v1_4);
+    virtual ~RadioIndication_v1_4() = default;
+
+    /* 1.4 Api */
+    Return<void> currentEmergencyNumberList(
+            RadioIndicationType type,
+            const ::android::hardware::hidl_vec<EmergencyNumber>& emergencyNumberList);
+
+    Return<void> cellInfoList_1_4(
+            RadioIndicationType type,
+            const ::android::hardware::hidl_vec<::android::hardware::radio::V1_4::CellInfo>&
+                    records);
+
+    Return<void> networkScanResult_1_4(
+            RadioIndicationType type,
+            const ::android::hardware::radio::V1_4::NetworkScanResult& result);
+
+    Return<void> currentPhysicalChannelConfigs_1_4(
+            RadioIndicationType type,
+            const ::android::hardware::hidl_vec<
+                    ::android::hardware::radio::V1_4::PhysicalChannelConfig>& configs);
+
+    Return<void> dataCallListChanged_1_4(
+            RadioIndicationType type,
+            const ::android::hardware::hidl_vec<
+                    android::hardware::radio::V1_4::SetupDataCallResult>& dcList);
+
+    /* 1.2 Api */
+    Return<void> networkScanResult_1_2(
+            RadioIndicationType type,
+            const ::android::hardware::radio::V1_2::NetworkScanResult& result);
+
+    Return<void> cellInfoList_1_2(
+            RadioIndicationType type,
+            const ::android::hardware::hidl_vec<::android::hardware::radio::V1_2::CellInfo>&
+                    records);
+
+    Return<void> currentLinkCapacityEstimate(
+            RadioIndicationType type,
+            const ::android::hardware::radio::V1_2::LinkCapacityEstimate& lce);
+
+    Return<void> currentPhysicalChannelConfigs(
+            RadioIndicationType type,
+            const ::android::hardware::hidl_vec<
+                    ::android::hardware::radio::V1_2::PhysicalChannelConfig>& configs);
+
+    Return<void> currentSignalStrength_1_2(
+            RadioIndicationType type,
+            const ::android::hardware::radio::V1_2::SignalStrength& signalStrength);
+
+    /* 1.1 Api */
+    Return<void> carrierInfoForImsiEncryption(RadioIndicationType info);
+
+    Return<void> networkScanResult(
+            RadioIndicationType type,
+            const ::android::hardware::radio::V1_1::NetworkScanResult& result);
+
+    Return<void> keepaliveStatus(RadioIndicationType type, const KeepaliveStatus& status);
+
+    /* 1.0 Api */
+    Return<void> radioStateChanged(RadioIndicationType type, RadioState radioState);
+
+    Return<void> callStateChanged(RadioIndicationType type);
+
+    Return<void> networkStateChanged(RadioIndicationType type);
+
+    Return<void> newSms(RadioIndicationType type,
+                        const ::android::hardware::hidl_vec<uint8_t>& pdu);
+
+    Return<void> newSmsStatusReport(RadioIndicationType type,
+                                    const ::android::hardware::hidl_vec<uint8_t>& pdu);
+
+    Return<void> newSmsOnSim(RadioIndicationType type, int32_t recordNumber);
+
+    Return<void> onUssd(RadioIndicationType type, UssdModeType modeType,
+                        const ::android::hardware::hidl_string& msg);
+
+    Return<void> nitzTimeReceived(RadioIndicationType type,
+                                  const ::android::hardware::hidl_string& nitzTime,
+                                  uint64_t receivedTime);
+
+    Return<void> currentSignalStrength(
+            RadioIndicationType type,
+            const ::android::hardware::radio::V1_0::SignalStrength& signalStrength);
+
+    Return<void> dataCallListChanged(
+            RadioIndicationType type,
+            const ::android::hardware::hidl_vec<
+                    android::hardware::radio::V1_0::SetupDataCallResult>& dcList);
+
+    Return<void> suppSvcNotify(RadioIndicationType type, const SuppSvcNotification& suppSvc);
+
+    Return<void> stkSessionEnd(RadioIndicationType type);
+
+    Return<void> stkProactiveCommand(RadioIndicationType type,
+                                     const ::android::hardware::hidl_string& cmd);
+
+    Return<void> stkEventNotify(RadioIndicationType type,
+                                const ::android::hardware::hidl_string& cmd);
+
+    Return<void> stkCallSetup(RadioIndicationType type, int64_t timeout);
+
+    Return<void> simSmsStorageFull(RadioIndicationType type);
+
+    Return<void> simRefresh(RadioIndicationType type, const SimRefreshResult& refreshResult);
+
+    Return<void> callRing(RadioIndicationType type, bool isGsm, const CdmaSignalInfoRecord& record);
+
+    Return<void> simStatusChanged(RadioIndicationType type);
+
+    Return<void> cdmaNewSms(RadioIndicationType type, const CdmaSmsMessage& msg);
+
+    Return<void> newBroadcastSms(RadioIndicationType type,
+                                 const ::android::hardware::hidl_vec<uint8_t>& data);
+
+    Return<void> cdmaRuimSmsStorageFull(RadioIndicationType type);
+
+    Return<void> restrictedStateChanged(RadioIndicationType type, PhoneRestrictedState state);
+
+    Return<void> enterEmergencyCallbackMode(RadioIndicationType type);
+
+    Return<void> cdmaCallWaiting(RadioIndicationType type,
+                                 const CdmaCallWaiting& callWaitingRecord);
+
+    Return<void> cdmaOtaProvisionStatus(RadioIndicationType type, CdmaOtaProvisionStatus status);
+
+    Return<void> cdmaInfoRec(RadioIndicationType type, const CdmaInformationRecords& records);
+
+    Return<void> indicateRingbackTone(RadioIndicationType type, bool start);
+
+    Return<void> resendIncallMute(RadioIndicationType type);
+
+    Return<void> cdmaSubscriptionSourceChanged(RadioIndicationType type,
+                                               CdmaSubscriptionSource cdmaSource);
+
+    Return<void> cdmaPrlChanged(RadioIndicationType type, int32_t version);
+
+    Return<void> exitEmergencyCallbackMode(RadioIndicationType type);
+
+    Return<void> rilConnected(RadioIndicationType type);
+
+    Return<void> voiceRadioTechChanged(RadioIndicationType type,
+                                       ::android::hardware::radio::V1_0::RadioTechnology rat);
+
+    Return<void> cellInfoList(
+            RadioIndicationType type,
+            const ::android::hardware::hidl_vec<::android::hardware::radio::V1_0::CellInfo>&
+                    records);
+
+    Return<void> imsNetworkStateChanged(RadioIndicationType type);
+
+    Return<void> subscriptionStatusChanged(RadioIndicationType type, bool activate);
+
+    Return<void> srvccStateNotify(RadioIndicationType type, SrvccState state);
+
+    Return<void> hardwareConfigChanged(
+            RadioIndicationType type, const ::android::hardware::hidl_vec<HardwareConfig>& configs);
+
+    Return<void> radioCapabilityIndication(
+            RadioIndicationType type, const android::hardware::radio::V1_0::RadioCapability& rc);
+
+    Return<void> onSupplementaryServiceIndication(RadioIndicationType type,
+                                                  const StkCcUnsolSsResult& ss);
+
+    Return<void> stkCallControlAlphaNotify(RadioIndicationType type,
+                                           const ::android::hardware::hidl_string& alpha);
+
+    Return<void> lceData(RadioIndicationType type, const LceDataInfo& lce);
+
+    Return<void> pcoData(RadioIndicationType type, const PcoDataInfo& pco);
+
+    Return<void> modemReset(RadioIndicationType type,
+                            const ::android::hardware::hidl_string& reason);
+};
+
+// Test environment for Radio HIDL HAL.
+class RadioHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase {
+   public:
+    // get the test environment singleton
+    static RadioHidlEnvironment* Instance() {
+        static RadioHidlEnvironment* instance = new RadioHidlEnvironment;
+        return instance;
+    }
+    virtual void registerTestServices() override {
+        registerTestService<::android::hardware::radio::V1_4::IRadio>();
+    }
+
+   private:
+    RadioHidlEnvironment() {}
+};
+
+// The main test class for Radio HIDL.
+class RadioHidlTest_v1_4 : public ::testing::VtsHalHidlTargetTestBase {
+   protected:
+    std::mutex mtx_;
+    std::condition_variable cv_;
+    int count_;
+
+    /* Serial number for radio request */
+    int serial;
+
+    /* Update Sim Card Status */
+    void updateSimCardStatus();
+
+   public:
+    virtual void SetUp() override;
+
+    /* Used as a mechanism to inform the test about data/event callback */
+    void notify(int receivedSerial);
+
+    /* Test code calls this function to wait for response */
+    std::cv_status wait();
+
+    /* radio service handle */
+    sp<::android::hardware::radio::V1_4::IRadio> radio_v1_4;
+
+    /* radio response handle */
+    sp<RadioResponse_v1_4> radioRsp_v1_4;
+
+    /* radio indication handle */
+    sp<RadioIndication_v1_4> radioInd_v1_4;
+};
\ No newline at end of file
diff --git a/radio/1.4/vts/functional/radio_indication.cpp b/radio/1.4/vts/functional/radio_indication.cpp
new file mode 100644
index 0000000..f08b361
--- /dev/null
+++ b/radio/1.4/vts/functional/radio_indication.cpp
@@ -0,0 +1,324 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <radio_hidl_hal_utils_v1_4.h>
+
+RadioIndication_v1_4::RadioIndication_v1_4(RadioHidlTest_v1_4& parent) : parent_v1_4(parent) {}
+
+/* 1.4 Apis */
+Return<void> RadioIndication_v1_4::currentPhysicalChannelConfigs_1_4(
+        RadioIndicationType /*type*/,
+        const ::android::hardware::hidl_vec<
+                ::android::hardware::radio::V1_4::PhysicalChannelConfig>& /*configs*/) {
+    return Void();
+}
+
+Return<void> RadioIndication_v1_4::networkScanResult_1_4(
+        RadioIndicationType /*type*/,
+        const ::android::hardware::radio::V1_4::NetworkScanResult& /*result*/) {
+    return Void();
+}
+
+Return<void> RadioIndication_v1_4::cellInfoList_1_4(
+        RadioIndicationType /*type*/,
+        const ::android::hardware::hidl_vec<
+                ::android::hardware::radio::V1_4::CellInfo>& /*records*/) {
+    return Void();
+}
+
+Return<void> RadioIndication_v1_4::currentEmergencyNumberList(
+        RadioIndicationType /*type*/,
+        const ::android::hardware::hidl_vec<EmergencyNumber>& /*emergencyNumberList*/) {
+    return Void();
+}
+
+Return<void> RadioIndication_v1_4::dataCallListChanged_1_4(
+        RadioIndicationType /*type*/,
+        const ::android::hardware::hidl_vec<android::hardware::radio::V1_4::SetupDataCallResult>&
+        /*dcList*/) {
+    return Void();
+}
+
+/* 1.2 Apis */
+Return<void> RadioIndication_v1_4::networkScanResult_1_2(
+        RadioIndicationType /*type*/,
+        const ::android::hardware::radio::V1_2::NetworkScanResult& /*result*/) {
+    return Void();
+}
+
+Return<void> RadioIndication_v1_4::cellInfoList_1_2(
+        RadioIndicationType /*type*/,
+        const ::android::hardware::hidl_vec<
+                ::android::hardware::radio::V1_2::CellInfo>& /*records*/) {
+    return Void();
+}
+
+Return<void> RadioIndication_v1_4::currentLinkCapacityEstimate(
+        RadioIndicationType /*type*/,
+        const ::android::hardware::radio::V1_2::LinkCapacityEstimate& /*lce*/) {
+    return Void();
+}
+
+Return<void> RadioIndication_v1_4::currentPhysicalChannelConfigs(
+        RadioIndicationType /*type*/,
+        const ::android::hardware::hidl_vec<
+                ::android::hardware::radio::V1_2::PhysicalChannelConfig>& /*configs*/) {
+    return Void();
+}
+
+Return<void> RadioIndication_v1_4::currentSignalStrength_1_2(
+        RadioIndicationType /*type*/,
+        const ::android::hardware::radio::V1_2::SignalStrength& /*signalStrength*/) {
+    return Void();
+}
+
+/* 1.1 Apis */
+Return<void> RadioIndication_v1_4::carrierInfoForImsiEncryption(RadioIndicationType /*info*/) {
+    return Void();
+}
+
+Return<void> RadioIndication_v1_4::networkScanResult(
+        RadioIndicationType /*type*/,
+        const ::android::hardware::radio::V1_1::NetworkScanResult& /*result*/) {
+    return Void();
+}
+
+Return<void> RadioIndication_v1_4::keepaliveStatus(RadioIndicationType /*type*/,
+                                                   const KeepaliveStatus& /*status*/) {
+    return Void();
+}
+
+/* 1.0 Apis */
+Return<void> RadioIndication_v1_4::radioStateChanged(RadioIndicationType /*type*/,
+                                                     RadioState /*radioState*/) {
+    return Void();
+}
+
+Return<void> RadioIndication_v1_4::callStateChanged(RadioIndicationType /*type*/) {
+    return Void();
+}
+
+Return<void> RadioIndication_v1_4::networkStateChanged(RadioIndicationType /*type*/) {
+    return Void();
+}
+
+Return<void> RadioIndication_v1_4::newSms(RadioIndicationType /*type*/,
+                                          const ::android::hardware::hidl_vec<uint8_t>& /*pdu*/) {
+    return Void();
+}
+
+Return<void> RadioIndication_v1_4::newSmsStatusReport(
+        RadioIndicationType /*type*/, const ::android::hardware::hidl_vec<uint8_t>& /*pdu*/) {
+    return Void();
+}
+
+Return<void> RadioIndication_v1_4::newSmsOnSim(RadioIndicationType /*type*/,
+                                               int32_t /*recordNumber*/) {
+    return Void();
+}
+
+Return<void> RadioIndication_v1_4::onUssd(RadioIndicationType /*type*/, UssdModeType /*modeType*/,
+                                          const ::android::hardware::hidl_string& /*msg*/) {
+    return Void();
+}
+
+Return<void> RadioIndication_v1_4::nitzTimeReceived(
+        RadioIndicationType /*type*/, const ::android::hardware::hidl_string& /*nitzTime*/,
+        uint64_t /*receivedTime*/) {
+    return Void();
+}
+
+Return<void> RadioIndication_v1_4::currentSignalStrength(
+        RadioIndicationType /*type*/,
+        const ::android::hardware::radio::V1_0::SignalStrength& /*signalStrength*/) {
+    return Void();
+}
+
+Return<void> RadioIndication_v1_4::dataCallListChanged(
+        RadioIndicationType /*type*/,
+        const ::android::hardware::hidl_vec<android::hardware::radio::V1_0::SetupDataCallResult>&
+        /*dcList*/) {
+    return Void();
+}
+
+Return<void> RadioIndication_v1_4::suppSvcNotify(RadioIndicationType /*type*/,
+                                                 const SuppSvcNotification& /*suppSvc*/) {
+    return Void();
+}
+
+Return<void> RadioIndication_v1_4::stkSessionEnd(RadioIndicationType /*type*/) {
+    return Void();
+}
+
+Return<void> RadioIndication_v1_4::stkProactiveCommand(
+        RadioIndicationType /*type*/, const ::android::hardware::hidl_string& /*cmd*/) {
+    return Void();
+}
+
+Return<void> RadioIndication_v1_4::stkEventNotify(RadioIndicationType /*type*/,
+                                                  const ::android::hardware::hidl_string& /*cmd*/) {
+    return Void();
+}
+
+Return<void> RadioIndication_v1_4::stkCallSetup(RadioIndicationType /*type*/, int64_t /*timeout*/) {
+    return Void();
+}
+
+Return<void> RadioIndication_v1_4::simSmsStorageFull(RadioIndicationType /*type*/) {
+    return Void();
+}
+
+Return<void> RadioIndication_v1_4::simRefresh(RadioIndicationType /*type*/,
+                                              const SimRefreshResult& /*refreshResult*/) {
+    return Void();
+}
+
+Return<void> RadioIndication_v1_4::callRing(RadioIndicationType /*type*/, bool /*isGsm*/,
+                                            const CdmaSignalInfoRecord& /*record*/) {
+    return Void();
+}
+
+Return<void> RadioIndication_v1_4::simStatusChanged(RadioIndicationType /*type*/) {
+    return Void();
+}
+
+Return<void> RadioIndication_v1_4::cdmaNewSms(RadioIndicationType /*type*/,
+                                              const CdmaSmsMessage& /*msg*/) {
+    return Void();
+}
+
+Return<void> RadioIndication_v1_4::newBroadcastSms(
+        RadioIndicationType /*type*/, const ::android::hardware::hidl_vec<uint8_t>& /*data*/) {
+    return Void();
+}
+
+Return<void> RadioIndication_v1_4::cdmaRuimSmsStorageFull(RadioIndicationType /*type*/) {
+    return Void();
+}
+
+Return<void> RadioIndication_v1_4::restrictedStateChanged(RadioIndicationType /*type*/,
+                                                          PhoneRestrictedState /*state*/) {
+    return Void();
+}
+
+Return<void> RadioIndication_v1_4::enterEmergencyCallbackMode(RadioIndicationType /*type*/) {
+    return Void();
+}
+
+Return<void> RadioIndication_v1_4::cdmaCallWaiting(RadioIndicationType /*type*/,
+                                                   const CdmaCallWaiting& /*callWaitingRecord*/) {
+    return Void();
+}
+
+Return<void> RadioIndication_v1_4::cdmaOtaProvisionStatus(RadioIndicationType /*type*/,
+                                                          CdmaOtaProvisionStatus /*status*/) {
+    return Void();
+}
+
+Return<void> RadioIndication_v1_4::cdmaInfoRec(RadioIndicationType /*type*/,
+                                               const CdmaInformationRecords& /*records*/) {
+    return Void();
+}
+
+Return<void> RadioIndication_v1_4::indicateRingbackTone(RadioIndicationType /*type*/,
+                                                        bool /*start*/) {
+    return Void();
+}
+
+Return<void> RadioIndication_v1_4::resendIncallMute(RadioIndicationType /*type*/) {
+    return Void();
+}
+
+Return<void> RadioIndication_v1_4::cdmaSubscriptionSourceChanged(
+        RadioIndicationType /*type*/, CdmaSubscriptionSource /*cdmaSource*/) {
+    return Void();
+}
+
+Return<void> RadioIndication_v1_4::cdmaPrlChanged(RadioIndicationType /*type*/,
+                                                  int32_t /*version*/) {
+    return Void();
+}
+
+Return<void> RadioIndication_v1_4::exitEmergencyCallbackMode(RadioIndicationType /*type*/) {
+    return Void();
+}
+
+Return<void> RadioIndication_v1_4::rilConnected(RadioIndicationType /*type*/) {
+    return Void();
+}
+
+Return<void> RadioIndication_v1_4::voiceRadioTechChanged(
+        RadioIndicationType /*type*/, ::android::hardware::radio::V1_0::RadioTechnology /*rat*/) {
+    return Void();
+}
+
+Return<void> RadioIndication_v1_4::cellInfoList(
+        RadioIndicationType /*type*/,
+        const ::android::hardware::hidl_vec<
+                ::android::hardware::radio::V1_0::CellInfo>& /*records*/) {
+    return Void();
+}
+
+Return<void> RadioIndication_v1_4::imsNetworkStateChanged(RadioIndicationType /*type*/) {
+    return Void();
+}
+
+Return<void> RadioIndication_v1_4::subscriptionStatusChanged(RadioIndicationType /*type*/,
+                                                             bool /*activate*/) {
+    return Void();
+}
+
+Return<void> RadioIndication_v1_4::srvccStateNotify(RadioIndicationType /*type*/,
+                                                    SrvccState /*state*/) {
+    return Void();
+}
+
+Return<void> RadioIndication_v1_4::hardwareConfigChanged(
+        RadioIndicationType /*type*/,
+        const ::android::hardware::hidl_vec<HardwareConfig>& /*configs*/) {
+    return Void();
+}
+
+Return<void> RadioIndication_v1_4::radioCapabilityIndication(
+        RadioIndicationType /*type*/,
+        const android::hardware::radio::V1_0::RadioCapability& /*rc*/) {
+    return Void();
+}
+
+Return<void> RadioIndication_v1_4::onSupplementaryServiceIndication(
+        RadioIndicationType /*type*/, const StkCcUnsolSsResult& /*ss*/) {
+    return Void();
+}
+
+Return<void> RadioIndication_v1_4::stkCallControlAlphaNotify(
+        RadioIndicationType /*type*/, const ::android::hardware::hidl_string& /*alpha*/) {
+    return Void();
+}
+
+Return<void> RadioIndication_v1_4::lceData(RadioIndicationType /*type*/,
+                                           const LceDataInfo& /*lce*/) {
+    return Void();
+}
+
+Return<void> RadioIndication_v1_4::pcoData(RadioIndicationType /*type*/,
+                                           const PcoDataInfo& /*pco*/) {
+    return Void();
+}
+
+Return<void> RadioIndication_v1_4::modemReset(RadioIndicationType /*type*/,
+                                              const ::android::hardware::hidl_string& /*reason*/) {
+    return Void();
+}
\ No newline at end of file
diff --git a/radio/1.4/vts/functional/radio_response.cpp b/radio/1.4/vts/functional/radio_response.cpp
new file mode 100644
index 0000000..2ae5f7c
--- /dev/null
+++ b/radio/1.4/vts/functional/radio_response.cpp
@@ -0,0 +1,867 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <radio_hidl_hal_utils_v1_4.h>
+
+::android::hardware::radio::V1_4::CardStatus cardStatus;
+
+RadioResponse_v1_4::RadioResponse_v1_4(RadioHidlTest_v1_4& parent) : parent_v1_4(parent) {}
+
+/* 1.0 Apis */
+Return<void> RadioResponse_v1_4::getIccCardStatusResponse(
+        const RadioResponseInfo& /*info*/,
+        const ::android::hardware::radio::V1_0::CardStatus& /*card_status*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::supplyIccPinForAppResponse(const RadioResponseInfo& /*info*/,
+                                                            int32_t /*remainingRetries*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::supplyIccPukForAppResponse(const RadioResponseInfo& /*info*/,
+                                                            int32_t /*remainingRetries*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::supplyIccPin2ForAppResponse(const RadioResponseInfo& /*info*/,
+                                                             int32_t /*remainingRetries*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::supplyIccPuk2ForAppResponse(const RadioResponseInfo& /*info*/,
+                                                             int32_t /*remainingRetries*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::changeIccPinForAppResponse(const RadioResponseInfo& /*info*/,
+                                                            int32_t /*remainingRetries*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::changeIccPin2ForAppResponse(const RadioResponseInfo& /*info*/,
+                                                             int32_t /*remainingRetries*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::supplyNetworkDepersonalizationResponse(
+        const RadioResponseInfo& /*info*/, int32_t /*remainingRetries*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::getCurrentCallsResponse(
+        const RadioResponseInfo& /*info*/,
+        const ::android::hardware::hidl_vec<::android::hardware::radio::V1_0::Call>& /*calls*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::dialResponse(const RadioResponseInfo& /*info*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::getIMSIForAppResponse(
+        const RadioResponseInfo& /*info*/, const ::android::hardware::hidl_string& /*imsi*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::hangupConnectionResponse(const RadioResponseInfo& /*info*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::hangupWaitingOrBackgroundResponse(
+        const RadioResponseInfo& /*info*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::hangupForegroundResumeBackgroundResponse(
+        const RadioResponseInfo& /*info*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::switchWaitingOrHoldingAndActiveResponse(
+        const RadioResponseInfo& /*info*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::conferenceResponse(const RadioResponseInfo& /*info*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::rejectCallResponse(const RadioResponseInfo& /*info*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::getLastCallFailCauseResponse(
+        const RadioResponseInfo& /*info*/, const LastCallFailCauseInfo& /*failCauseInfo*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::getSignalStrengthResponse(
+        const RadioResponseInfo& /*info*/,
+        const ::android::hardware::radio::V1_0::SignalStrength& /*sig_strength*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::getVoiceRegistrationStateResponse(
+        const RadioResponseInfo& /*info*/,
+        const ::android::hardware::radio::V1_0::VoiceRegStateResult& /*voiceRegResponse*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::getDataRegistrationStateResponse(
+        const RadioResponseInfo& /*info*/,
+        const ::android::hardware::radio::V1_0::DataRegStateResult& /*dataRegResponse*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::getOperatorResponse(
+        const RadioResponseInfo& /*info*/, const ::android::hardware::hidl_string& /*longName*/,
+        const ::android::hardware::hidl_string& /*shortName*/,
+        const ::android::hardware::hidl_string& /*numeric*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::setRadioPowerResponse(const RadioResponseInfo& /*info*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::sendDtmfResponse(const RadioResponseInfo& /*info*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::sendSmsResponse(const RadioResponseInfo& /*info*/,
+                                                 const SendSmsResult& /*sms*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::sendSMSExpectMoreResponse(const RadioResponseInfo& /*info*/,
+                                                           const SendSmsResult& /*sms*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::setupDataCallResponse(
+        const RadioResponseInfo& /*info*/,
+        const android::hardware::radio::V1_0::SetupDataCallResult& /*dcResponse*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::iccIOForAppResponse(const RadioResponseInfo& /*info*/,
+                                                     const IccIoResult& /*iccIo*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::sendUssdResponse(const RadioResponseInfo& /*info*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::cancelPendingUssdResponse(const RadioResponseInfo& /*info*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::getClirResponse(const RadioResponseInfo& /*info*/, int32_t /*n*/,
+                                                 int32_t /*m*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::setClirResponse(const RadioResponseInfo& /*info*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::getCallForwardStatusResponse(
+        const RadioResponseInfo& /*info*/, const ::android::hardware::hidl_vec<CallForwardInfo>&
+        /*callForwardInfos*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::setCallForwardResponse(const RadioResponseInfo& /*info*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::getCallWaitingResponse(const RadioResponseInfo& /*info*/,
+                                                        bool /*enable*/, int32_t /*serviceClass*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::setCallWaitingResponse(const RadioResponseInfo& /*info*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::acknowledgeLastIncomingGsmSmsResponse(
+        const RadioResponseInfo& /*info*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::acceptCallResponse(const RadioResponseInfo& /*info*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::deactivateDataCallResponse(const RadioResponseInfo& info) {
+    rspInfo = info;
+    parent_v1_4.notify(info.serial);
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::getFacilityLockForAppResponse(const RadioResponseInfo& /*info*/,
+                                                               int32_t /*response*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::setFacilityLockForAppResponse(const RadioResponseInfo& /*info*/,
+                                                               int32_t /*retry*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::setBarringPasswordResponse(const RadioResponseInfo& /*info*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::getNetworkSelectionModeResponse(const RadioResponseInfo& /*info*/,
+                                                                 bool /*manual*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::setNetworkSelectionModeAutomaticResponse(
+        const RadioResponseInfo& /*info*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::setNetworkSelectionModeManualResponse(
+        const RadioResponseInfo& /*info*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::getAvailableNetworksResponse(
+        const RadioResponseInfo& /*info*/,
+        const ::android::hardware::hidl_vec<OperatorInfo>& /*networkInfos*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::startDtmfResponse(const RadioResponseInfo& /*info*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::stopDtmfResponse(const RadioResponseInfo& /*info*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::getBasebandVersionResponse(
+        const RadioResponseInfo& /*info*/, const ::android::hardware::hidl_string& /*version*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::separateConnectionResponse(const RadioResponseInfo& /*info*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::setMuteResponse(const RadioResponseInfo& /*info*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::getMuteResponse(const RadioResponseInfo& /*info*/,
+                                                 bool /*enable*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::getClipResponse(const RadioResponseInfo& /*info*/,
+                                                 ClipStatus /*status*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::getDataCallListResponse(
+        const RadioResponseInfo& /*info*/,
+        const ::android::hardware::hidl_vec<android::hardware::radio::V1_0::SetupDataCallResult>&
+        /*dcResponse*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::sendOemRilRequestRawResponse(
+        const RadioResponseInfo& /*info*/, const ::android::hardware::hidl_vec<uint8_t>& /*data*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::sendOemRilRequestStringsResponse(
+        const RadioResponseInfo& /*info*/,
+        const ::android::hardware::hidl_vec<::android::hardware::hidl_string>& /*data*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::setSuppServiceNotificationsResponse(
+        const RadioResponseInfo& /*info*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::writeSmsToSimResponse(const RadioResponseInfo& /*info*/,
+                                                       int32_t /*index*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::deleteSmsOnSimResponse(const RadioResponseInfo& /*info*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::setBandModeResponse(const RadioResponseInfo& /*info*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::getAvailableBandModesResponse(
+        const RadioResponseInfo& info,
+        const ::android::hardware::hidl_vec<RadioBandMode>& bandModes) {
+    rspInfo = info;
+    radioBandModes = bandModes;
+    parent_v1_4.notify(info.serial);
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::sendEnvelopeResponse(
+        const RadioResponseInfo& /*info*/,
+        const ::android::hardware::hidl_string& /*commandResponse*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::sendTerminalResponseToSimResponse(
+        const RadioResponseInfo& /*info*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::handleStkCallSetupRequestFromSimResponse(
+        const RadioResponseInfo& /*info*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::explicitCallTransferResponse(const RadioResponseInfo& /*info*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::setPreferredNetworkTypeResponse(
+        const RadioResponseInfo& /*info*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::getPreferredNetworkTypeResponse(const RadioResponseInfo& /*info*/,
+                                                                 PreferredNetworkType /*nw_type*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::getNeighboringCidsResponse(
+        const RadioResponseInfo& /*info*/,
+        const ::android::hardware::hidl_vec<NeighboringCell>& /*cells*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::setLocationUpdatesResponse(const RadioResponseInfo& /*info*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::setCdmaSubscriptionSourceResponse(
+        const RadioResponseInfo& /*info*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::setCdmaRoamingPreferenceResponse(
+        const RadioResponseInfo& /*info*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::getCdmaRoamingPreferenceResponse(const RadioResponseInfo& /*info*/,
+                                                                  CdmaRoamingType /*type*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::setTTYModeResponse(const RadioResponseInfo& /*info*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::getTTYModeResponse(const RadioResponseInfo& /*info*/,
+                                                    TtyMode /*mode*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::setPreferredVoicePrivacyResponse(
+        const RadioResponseInfo& /*info*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::getPreferredVoicePrivacyResponse(const RadioResponseInfo& /*info*/,
+                                                                  bool /*enable*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::sendCDMAFeatureCodeResponse(const RadioResponseInfo& /*info*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::sendBurstDtmfResponse(const RadioResponseInfo& /*info*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::sendCdmaSmsResponse(const RadioResponseInfo& /*info*/,
+                                                     const SendSmsResult& /*sms*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::acknowledgeLastIncomingCdmaSmsResponse(
+        const RadioResponseInfo& /*info*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::getGsmBroadcastConfigResponse(
+        const RadioResponseInfo& /*info*/,
+        const ::android::hardware::hidl_vec<GsmBroadcastSmsConfigInfo>& /*configs*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::setGsmBroadcastConfigResponse(const RadioResponseInfo& /*info*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::setGsmBroadcastActivationResponse(
+        const RadioResponseInfo& /*info*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::getCdmaBroadcastConfigResponse(
+        const RadioResponseInfo& /*info*/,
+        const ::android::hardware::hidl_vec<CdmaBroadcastSmsConfigInfo>& /*configs*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::setCdmaBroadcastConfigResponse(const RadioResponseInfo& /*info*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::setCdmaBroadcastActivationResponse(
+        const RadioResponseInfo& /*info*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::getCDMASubscriptionResponse(
+        const RadioResponseInfo& /*info*/, const ::android::hardware::hidl_string& /*mdn*/,
+        const ::android::hardware::hidl_string& /*hSid*/,
+        const ::android::hardware::hidl_string& /*hNid*/,
+        const ::android::hardware::hidl_string& /*min*/,
+        const ::android::hardware::hidl_string& /*prl*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::writeSmsToRuimResponse(const RadioResponseInfo& /*info*/,
+                                                        uint32_t /*index*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::deleteSmsOnRuimResponse(const RadioResponseInfo& /*info*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::getDeviceIdentityResponse(
+        const RadioResponseInfo& /*info*/, const ::android::hardware::hidl_string& /*imei*/,
+        const ::android::hardware::hidl_string& /*imeisv*/,
+        const ::android::hardware::hidl_string& /*esn*/,
+        const ::android::hardware::hidl_string& /*meid*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::exitEmergencyCallbackModeResponse(
+        const RadioResponseInfo& /*info*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::getSmscAddressResponse(
+        const RadioResponseInfo& /*info*/, const ::android::hardware::hidl_string& /*smsc*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::setSmscAddressResponse(const RadioResponseInfo& /*info*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::reportSmsMemoryStatusResponse(const RadioResponseInfo& /*info*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::reportStkServiceIsRunningResponse(
+        const RadioResponseInfo& /*info*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::getCdmaSubscriptionSourceResponse(
+        const RadioResponseInfo& /*info*/, CdmaSubscriptionSource /*source*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::requestIsimAuthenticationResponse(
+        const RadioResponseInfo& /*info*/, const ::android::hardware::hidl_string& /*response*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::acknowledgeIncomingGsmSmsWithPduResponse(
+        const RadioResponseInfo& /*info*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::sendEnvelopeWithStatusResponse(const RadioResponseInfo& /*info*/,
+                                                                const IccIoResult& /*iccIo*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::getVoiceRadioTechnologyResponse(
+        const RadioResponseInfo& /*info*/,
+        ::android::hardware::radio::V1_0::RadioTechnology /*rat*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::getCellInfoListResponse(
+        const RadioResponseInfo& /*info*/,
+        const ::android::hardware::hidl_vec<
+                ::android::hardware::radio::V1_0::CellInfo>& /*cellInfo*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::setCellInfoListRateResponse(const RadioResponseInfo& /*info*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::setInitialAttachApnResponse(const RadioResponseInfo& /*info*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::getImsRegistrationStateResponse(
+        const RadioResponseInfo& /*info*/, bool /*isRegistered*/,
+        RadioTechnologyFamily /*ratFamily*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::sendImsSmsResponse(const RadioResponseInfo& /*info*/,
+                                                    const SendSmsResult& /*sms*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::iccTransmitApduBasicChannelResponse(
+        const RadioResponseInfo& /*info*/, const IccIoResult& /*result*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::iccOpenLogicalChannelResponse(
+        const RadioResponseInfo& /*info*/, int32_t /*channelId*/,
+        const ::android::hardware::hidl_vec<int8_t>& /*selectResponse*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::iccCloseLogicalChannelResponse(const RadioResponseInfo& /*info*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::iccTransmitApduLogicalChannelResponse(
+        const RadioResponseInfo& /*info*/, const IccIoResult& /*result*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::nvReadItemResponse(
+        const RadioResponseInfo& /*info*/, const ::android::hardware::hidl_string& /*result*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::nvWriteItemResponse(const RadioResponseInfo& /*info*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::nvWriteCdmaPrlResponse(const RadioResponseInfo& /*info*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::nvResetConfigResponse(const RadioResponseInfo& /*info*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::setUiccSubscriptionResponse(const RadioResponseInfo& /*info*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::setDataAllowedResponse(const RadioResponseInfo& /*info*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::getHardwareConfigResponse(
+        const RadioResponseInfo& /*info*/,
+        const ::android::hardware::hidl_vec<HardwareConfig>& /*config*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::requestIccSimAuthenticationResponse(
+        const RadioResponseInfo& /*info*/, const IccIoResult& /*result*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::setDataProfileResponse(const RadioResponseInfo& /*info*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::requestShutdownResponse(const RadioResponseInfo& /*info*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::getRadioCapabilityResponse(
+        const RadioResponseInfo& /*info*/,
+        const android::hardware::radio::V1_0::RadioCapability& /*rc*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::setRadioCapabilityResponse(
+        const RadioResponseInfo& /*info*/,
+        const android::hardware::radio::V1_0::RadioCapability& /*rc*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::startLceServiceResponse(const RadioResponseInfo& /*info*/,
+                                                         const LceStatusInfo& /*statusInfo*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::stopLceServiceResponse(const RadioResponseInfo& /*info*/,
+                                                        const LceStatusInfo& /*statusInfo*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::pullLceDataResponse(const RadioResponseInfo& /*info*/,
+                                                     const LceDataInfo& /*lceInfo*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::getModemActivityInfoResponse(
+        const RadioResponseInfo& /*info*/, const ActivityStatsInfo& /*activityInfo*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::setAllowedCarriersResponse(const RadioResponseInfo& /*info*/,
+                                                            int32_t /*numAllowed*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::getAllowedCarriersResponse(
+        const RadioResponseInfo& /*info*/, bool /*allAllowed*/,
+        const CarrierRestrictions& /*carriers*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::sendDeviceStateResponse(const RadioResponseInfo& /*info*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::setIndicationFilterResponse(const RadioResponseInfo& info) {
+    rspInfo = info;
+    parent_v1_4.notify(info.serial);
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::setSimCardPowerResponse(const RadioResponseInfo& /*info*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::acknowledgeRequest(int32_t /*serial*/) {
+    return Void();
+}
+
+/* 1.1 Apis */
+Return<void> RadioResponse_v1_4::setCarrierInfoForImsiEncryptionResponse(
+        const RadioResponseInfo& /*info*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::setSimCardPowerResponse_1_1(const RadioResponseInfo& /*info*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::startNetworkScanResponse(const RadioResponseInfo& /*info*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::stopNetworkScanResponse(const RadioResponseInfo& info) {
+    rspInfo = info;
+    parent_v1_4.notify(info.serial);
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::startKeepaliveResponse(const RadioResponseInfo& /*info*/,
+                                                        const KeepaliveStatus& /*status*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::stopKeepaliveResponse(const RadioResponseInfo& /*info*/) {
+    return Void();
+}
+
+/* 1.2 Apis */
+Return<void> RadioResponse_v1_4::setSignalStrengthReportingCriteriaResponse(
+        const RadioResponseInfo& info) {
+    rspInfo = info;
+    parent_v1_4.notify(info.serial);
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::setLinkCapacityReportingCriteriaResponse(
+        const RadioResponseInfo& info) {
+    rspInfo = info;
+    parent_v1_4.notify(info.serial);
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::getIccCardStatusResponse_1_2(
+        const RadioResponseInfo& /*info*/,
+        const ::android::hardware::radio::V1_2::CardStatus& /*card_status*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::getCurrentCallsResponse_1_2(
+        const RadioResponseInfo& info,
+        const ::android::hardware::hidl_vec<::android::hardware::radio::V1_2::Call>& /*calls*/) {
+    rspInfo = info;
+    parent_v1_4.notify(info.serial);
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::getSignalStrengthResponse_1_2(
+        const RadioResponseInfo& info,
+        const ::android::hardware::radio::V1_2::SignalStrength& /*sig_strength*/) {
+    rspInfo = info;
+    parent_v1_4.notify(info.serial);
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::getCellInfoListResponse_1_2(
+        const RadioResponseInfo& /*info*/,
+        const ::android::hardware::hidl_vec<
+                ::android::hardware::radio::V1_2::CellInfo>& /*cellInfo*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::getVoiceRegistrationStateResponse_1_2(
+        const RadioResponseInfo& info,
+        const ::android::hardware::radio::V1_2::VoiceRegStateResult& /*voiceRegResponse*/) {
+    rspInfo = info;
+    parent_v1_4.notify(info.serial);
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::getDataRegistrationStateResponse_1_2(
+        const RadioResponseInfo& /*info*/,
+        const ::android::hardware::radio::V1_2::DataRegStateResult& /*dataRegResponse*/) {
+    return Void();
+}
+
+/* 1.3 Apis */
+Return<void> RadioResponse_v1_4::setSystemSelectionChannelsResponse(const RadioResponseInfo& info) {
+    rspInfo = info;
+    parent_v1_4.notify(info.serial);
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::enableModemResponse(const RadioResponseInfo& info) {
+    rspInfo = info;
+    enableModemResponseToggle = !enableModemResponseToggle;
+    parent_v1_4.notify(info.serial);
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::getModemStackStatusResponse(const RadioResponseInfo& info,
+                                                             const bool enabled) {
+    rspInfo = info;
+    isModemEnabled = enabled;
+    parent_v1_4.notify(info.serial);
+    return Void();
+}
+
+/* 1.4 Apis */
+Return<void> RadioResponse_v1_4::emergencyDialResponse(const RadioResponseInfo& info) {
+    rspInfo = info;
+    parent_v1_4.notify(info.serial);
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::startNetworkScanResponse_1_4(const RadioResponseInfo& info) {
+    rspInfo = info;
+    parent_v1_4.notify(info.serial);
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::getDataRegistrationStateResponse_1_4(
+        const RadioResponseInfo& info,
+        const ::android::hardware::radio::V1_4::DataRegStateResult& dataRegResponse) {
+    rspInfo = info;
+    dataRegResp = dataRegResponse;
+    parent_v1_4.notify(info.serial);
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::getCellInfoListResponse_1_4(
+        const RadioResponseInfo& info,
+        const ::android::hardware::hidl_vec<
+                ::android::hardware::radio::V1_4::CellInfo>& /*cellInfo*/) {
+    rspInfo = info;
+    parent_v1_4.notify(info.serial);
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::getIccCardStatusResponse_1_4(
+        const RadioResponseInfo& info,
+        const ::android::hardware::radio::V1_4::CardStatus& card_status) {
+    rspInfo = info;
+    cardStatus = card_status;
+    parent_v1_4.notify(info.serial);
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::getPreferredNetworkTypeBitmapResponse(
+        const RadioResponseInfo& info, const ::android::hardware::hidl_bitfield<
+                                               ::android::hardware::radio::V1_4::RadioAccessFamily>
+        /*networkTypeBitmap*/) {
+    rspInfo = info;
+    // TODO: may need a new member for bitfield networkTypeBitmap.
+    parent_v1_4.notify(info.serial);
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::setPreferredNetworkTypeBitmapResponse(
+        const RadioResponseInfo& info) {
+    rspInfo = info;
+    parent_v1_4.notify(info.serial);
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::getDataCallListResponse_1_4(
+        const RadioResponseInfo& info,
+        const ::android::hardware::hidl_vec<::android::hardware::radio::V1_4::SetupDataCallResult>&
+        /*dcResponse*/) {
+    rspInfo = info;
+    parent_v1_4.notify(info.serial);
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::setupDataCallResponse_1_4(
+        const RadioResponseInfo& info,
+        const android::hardware::radio::V1_4::SetupDataCallResult& /*dcResponse*/) {
+    rspInfo = info;
+    parent_v1_4.notify(info.serial);
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::setAllowedCarriersResponse_1_4(const RadioResponseInfo& /*info*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_4::getAllowedCarriersResponse_1_4(
+        const RadioResponseInfo& /*info*/, const CarrierRestrictionsWithPriority& /*carriers*/,
+        SimLockMultiSimPolicy /*multiSimPolicy*/) {
+    return Void();
+}
\ No newline at end of file
diff --git a/secure_element/1.1/Android.bp b/secure_element/1.1/Android.bp
new file mode 100644
index 0000000..e16bc3d
--- /dev/null
+++ b/secure_element/1.1/Android.bp
@@ -0,0 +1,19 @@
+// This file is autogenerated by hidl-gen -Landroidbp.
+
+hidl_interface {
+    name: "android.hardware.secure_element@1.1",
+    root: "android.hardware",
+    vndk: {
+        enabled: true,
+    },
+    srcs: [
+        "ISecureElement.hal",
+        "ISecureElementHalCallback.hal",
+    ],
+    interfaces: [
+        "android.hardware.secure_element@1.0",
+        "android.hidl.base@1.0",
+    ],
+    gen_java: true,
+}
+
diff --git a/secure_element/1.1/ISecureElement.hal b/secure_element/1.1/ISecureElement.hal
new file mode 100644
index 0000000..2f68fc7
--- /dev/null
+++ b/secure_element/1.1/ISecureElement.hal
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2019 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.secure_element@1.1;
+
+import @1.1::ISecureElementHalCallback;
+import @1.0::ISecureElement;
+
+interface ISecureElement extends @1.0::ISecureElement {
+    /**
+     * Initializes the Secure Element. This may include updating the applet
+     * and/or vendor-specific initialization.
+     *
+     * HAL service must send onStateChange() with connected equal to true
+     * after all the initialization has been successfully completed.
+     * Clients must wait for a onStateChange(true) before opening channels.
+     *
+     * @param clientCallback callback used to sent status of the SE back to the
+     *                       client
+     */
+    init_1_1(ISecureElementHalCallback clientCallback);
+};
diff --git a/secure_element/1.1/ISecureElementHalCallback.hal b/secure_element/1.1/ISecureElementHalCallback.hal
new file mode 100644
index 0000000..090db5f
--- /dev/null
+++ b/secure_element/1.1/ISecureElementHalCallback.hal
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2019 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.secure_element@1.1;
+
+import @1.0::ISecureElementHalCallback;
+
+interface ISecureElementHalCallback extends @1.0::ISecureElementHalCallback {
+    /*
+     * Used to inform the client about changes in the state of the Secure
+     * Element.
+     *
+     * @param connected indicates the current state of the SE
+     * @param reason provides additional data why there was a change in state
+     *               ex. initialization error, SE removed etc
+     *               This is used only for debugging purpose to understand
+     *               in-field issues.
+     */
+    onStateChange_1_1(bool connected, string debugReason);
+};
diff --git a/secure_element/1.1/vts/functional/Android.bp b/secure_element/1.1/vts/functional/Android.bp
new file mode 100644
index 0000000..51410bd
--- /dev/null
+++ b/secure_element/1.1/vts/functional/Android.bp
@@ -0,0 +1,26 @@
+//
+// Copyright (C) 2019 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: "VtsHalSecureElementV1_1TargetTest",
+    defaults: ["VtsHalTargetTestDefaults"],
+    srcs: ["VtsHalSecureElementV1_1TargetTest.cpp"],
+    static_libs: [
+        "android.hardware.secure_element@1.0",
+        "android.hardware.secure_element@1.1",
+    ],
+    test_suites: ["general-tests"],
+}
diff --git a/secure_element/1.1/vts/functional/VtsHalSecureElementV1_1TargetTest.cpp b/secure_element/1.1/vts/functional/VtsHalSecureElementV1_1TargetTest.cpp
new file mode 100644
index 0000000..f8765ca
--- /dev/null
+++ b/secure_element/1.1/vts/functional/VtsHalSecureElementV1_1TargetTest.cpp
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 2019 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 <string>
+
+#define LOG_TAG "secure_element_hidl_hal_test"
+#include <android-base/logging.h>
+
+#include <android/hardware/secure_element/1.0/types.h>
+#include <android/hardware/secure_element/1.1/ISecureElement.h>
+#include <android/hardware/secure_element/1.1/ISecureElementHalCallback.h>
+
+#include <VtsHalHidlTargetCallbackBase.h>
+#include <VtsHalHidlTargetTestBase.h>
+#include <VtsHalHidlTargetTestEnvBase.h>
+
+using ::android::sp;
+using ::android::hardware::hidl_string;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::secure_element::V1_1::ISecureElement;
+using ::android::hardware::secure_element::V1_1::ISecureElementHalCallback;
+using ::testing::VtsHalHidlTargetTestEnvBase;
+
+constexpr char kCallbackNameOnStateChange[] = "onStateChange";
+
+class SecureElementCallbackArgs {
+   public:
+    bool state_;
+    hidl_string reason_;
+};
+
+class SecureElementHalCallback
+    : public ::testing::VtsHalHidlTargetCallbackBase<SecureElementCallbackArgs>,
+      public ISecureElementHalCallback {
+   public:
+    virtual ~SecureElementHalCallback() = default;
+
+    Return<void> onStateChange_1_1(bool state, const hidl_string& reason) override {
+        SecureElementCallbackArgs args;
+        args.state_ = state;
+        args.reason_ = reason;
+        NotifyFromCallback(kCallbackNameOnStateChange, args);
+        return Void();
+    };
+
+    Return<void> onStateChange(__attribute__((unused)) bool state) override { return Void(); }
+};
+
+class SecureElementHidlEnvironment : public VtsHalHidlTargetTestEnvBase {
+   public:
+    // get the test environment singleton
+    static SecureElementHidlEnvironment* Instance() {
+        static SecureElementHidlEnvironment* instance = new SecureElementHidlEnvironment;
+        return instance;
+    }
+
+    virtual void registerTestServices() override { registerTestService<ISecureElement>(); }
+
+   private:
+    SecureElementHidlEnvironment() {}
+
+    GTEST_DISALLOW_COPY_AND_ASSIGN_(SecureElementHidlEnvironment);
+};
+
+class SecureElementHidlTest : public ::testing::VtsHalHidlTargetTestBase {
+   public:
+    virtual void SetUp() override {
+        std::string serviceName =
+                SecureElementHidlEnvironment::Instance()->getServiceName<ISecureElement>("eSE1");
+        LOG(INFO) << "get service with name:" << serviceName;
+        ASSERT_FALSE(serviceName.empty());
+        se_ = ::testing::VtsHalHidlTargetTestBase::getService<ISecureElement>(serviceName);
+        ASSERT_NE(se_, nullptr);
+
+        se_cb_ = new SecureElementHalCallback();
+        ASSERT_NE(se_cb_, nullptr);
+        se_->init_1_1(se_cb_);
+        auto res = se_cb_->WaitForCallback(kCallbackNameOnStateChange);
+        EXPECT_TRUE(res.no_timeout);
+        EXPECT_TRUE(res.args->state_);
+        EXPECT_NE(res.args->reason_, "");
+    }
+
+    sp<ISecureElement> se_;
+    sp<SecureElementHalCallback> se_cb_;
+};
+
+/*
+ * isCardPresent:
+ * Expects the card to be present
+ */
+TEST_F(SecureElementHidlTest, isCardPresent) {
+    EXPECT_TRUE(se_->isCardPresent());
+}
+
+int main(int argc, char** argv) {
+    ::testing::AddGlobalTestEnvironment(SecureElementHidlEnvironment::Instance());
+    ::testing::InitGoogleTest(&argc, argv);
+    SecureElementHidlEnvironment::Instance()->init(&argc, argv);
+    int status = RUN_ALL_TESTS();
+    return status;
+}
diff --git a/sensors/2.0/default/Sensor.cpp b/sensors/2.0/default/Sensor.cpp
index 168b402..c09173f 100644
--- a/sensors/2.0/default/Sensor.cpp
+++ b/sensors/2.0/default/Sensor.cpp
@@ -18,6 +18,8 @@
 
 #include <utils/SystemClock.h>
 
+#include <cmath>
+
 namespace android {
 namespace hardware {
 namespace sensors {
@@ -28,6 +30,8 @@
 using ::android::hardware::sensors::V1_0::SensorFlagBits;
 using ::android::hardware::sensors::V1_0::SensorStatus;
 
+static constexpr float kDefaultMaxDelayUs = 10 * 1000 * 1000;
+
 Sensor::Sensor(ISensorsEventCallback* callback)
     : mIsEnabled(false),
       mSamplingPeriodNs(0),
@@ -83,7 +87,7 @@
     // to the Event FMQ prior to writing the flush complete event.
     Event ev;
     ev.sensorHandle = mSensorInfo.sensorHandle;
-    ev.sensorType = SensorType::ADDITIONAL_INFO;
+    ev.sensorType = SensorType::META_DATA;
     ev.u.meta.what = MetaDataEventType::META_DATA_FLUSH_COMPLETE;
     std::vector<Event> evs{ev};
     mCallback->postEvents(evs, isWakeUpSensor());
@@ -131,9 +135,9 @@
     event.sensorHandle = mSensorInfo.sensorHandle;
     event.sensorType = mSensorInfo.type;
     event.timestamp = ::android::elapsedRealtimeNano();
-    event.u.vec3.x = 1;
-    event.u.vec3.y = 2;
-    event.u.vec3.z = 3;
+    event.u.vec3.x = 0;
+    event.u.vec3.y = 0;
+    event.u.vec3.z = 0;
     event.u.vec3.status = SensorStatus::ACCURACY_HIGH;
     events.push_back(event);
     return events;
@@ -166,6 +170,31 @@
     return result;
 }
 
+OnChangeSensor::OnChangeSensor(ISensorsEventCallback* callback)
+    : Sensor(callback), mPreviousEventSet(false) {}
+
+void OnChangeSensor::activate(bool enable) {
+    Sensor::activate(enable);
+    if (!enable) {
+        mPreviousEventSet = false;
+    }
+}
+
+std::vector<Event> OnChangeSensor::readEvents() {
+    std::vector<Event> events = Sensor::readEvents();
+    std::vector<Event> outputEvents;
+
+    for (auto iter = events.begin(); iter != events.end(); ++iter) {
+        Event ev = *iter;
+        if (ev.u.vec3 != mPreviousEvent.u.vec3 || !mPreviousEventSet) {
+            outputEvents.push_back(ev);
+            mPreviousEvent = ev;
+            mPreviousEventSet = true;
+        }
+    }
+    return outputEvents;
+}
+
 AccelSensor::AccelSensor(int32_t sensorHandle, ISensorsEventCallback* callback) : Sensor(callback) {
     mSensorInfo.sensorHandle = sensorHandle;
     mSensorInfo.name = "Accel Sensor";
@@ -177,14 +206,166 @@
     mSensorInfo.resolution = 1.52e-5;
     mSensorInfo.power = 0.001f;          // mA
     mSensorInfo.minDelay = 20 * 1000;    // microseconds
-    mSensorInfo.maxDelay = 1000 * 1000;  // microseconds
+    mSensorInfo.maxDelay = kDefaultMaxDelayUs;
+    mSensorInfo.fifoReservedEventCount = 0;
+    mSensorInfo.fifoMaxEventCount = 0;
+    mSensorInfo.requiredPermission = "";
+    mSensorInfo.flags = static_cast<uint32_t>(SensorFlagBits::DATA_INJECTION);
+};
+
+PressureSensor::PressureSensor(int32_t sensorHandle, ISensorsEventCallback* callback)
+    : Sensor(callback) {
+    mSensorInfo.sensorHandle = sensorHandle;
+    mSensorInfo.name = "Pressure Sensor";
+    mSensorInfo.vendor = "Vendor String";
+    mSensorInfo.version = 1;
+    mSensorInfo.type = SensorType::PRESSURE;
+    mSensorInfo.typeAsString = "";
+    mSensorInfo.maxRange = 1100.0f;   // hPa
+    mSensorInfo.resolution = 0.005f;  // hPa
+    mSensorInfo.power = 0.001f;       // mA
+    mSensorInfo.minDelay = 100 * 1000;  // microseconds
+    mSensorInfo.maxDelay = kDefaultMaxDelayUs;
+    mSensorInfo.fifoReservedEventCount = 0;
+    mSensorInfo.fifoMaxEventCount = 0;
+    mSensorInfo.requiredPermission = "";
+    mSensorInfo.flags = 0;
+};
+
+MagnetometerSensor::MagnetometerSensor(int32_t sensorHandle, ISensorsEventCallback* callback)
+    : Sensor(callback) {
+    mSensorInfo.sensorHandle = sensorHandle;
+    mSensorInfo.name = "Magnetic Field Sensor";
+    mSensorInfo.vendor = "Vendor String";
+    mSensorInfo.version = 1;
+    mSensorInfo.type = SensorType::MAGNETIC_FIELD;
+    mSensorInfo.typeAsString = "";
+    mSensorInfo.maxRange = 1300.0f;
+    mSensorInfo.resolution = 0.01f;
+    mSensorInfo.power = 0.001f;       // mA
+    mSensorInfo.minDelay = 20 * 1000;  // microseconds
+    mSensorInfo.maxDelay = kDefaultMaxDelayUs;
+    mSensorInfo.fifoReservedEventCount = 0;
+    mSensorInfo.fifoMaxEventCount = 0;
+    mSensorInfo.requiredPermission = "";
+    mSensorInfo.flags = 0;
+};
+
+LightSensor::LightSensor(int32_t sensorHandle, ISensorsEventCallback* callback)
+    : OnChangeSensor(callback) {
+    mSensorInfo.sensorHandle = sensorHandle;
+    mSensorInfo.name = "Light Sensor";
+    mSensorInfo.vendor = "Vendor String";
+    mSensorInfo.version = 1;
+    mSensorInfo.type = SensorType::LIGHT;
+    mSensorInfo.typeAsString = "";
+    mSensorInfo.maxRange = 43000.0f;
+    mSensorInfo.resolution = 10.0f;
+    mSensorInfo.power = 0.001f;           // mA
+    mSensorInfo.minDelay = 200 * 1000;    // microseconds
+    mSensorInfo.maxDelay = kDefaultMaxDelayUs;
+    mSensorInfo.fifoReservedEventCount = 0;
+    mSensorInfo.fifoMaxEventCount = 0;
+    mSensorInfo.requiredPermission = "";
+    mSensorInfo.flags = static_cast<uint32_t>(SensorFlagBits::ON_CHANGE_MODE);
+};
+
+ProximitySensor::ProximitySensor(int32_t sensorHandle, ISensorsEventCallback* callback)
+    : OnChangeSensor(callback) {
+    mSensorInfo.sensorHandle = sensorHandle;
+    mSensorInfo.name = "Proximity Sensor";
+    mSensorInfo.vendor = "Vendor String";
+    mSensorInfo.version = 1;
+    mSensorInfo.type = SensorType::PROXIMITY;
+    mSensorInfo.typeAsString = "";
+    mSensorInfo.maxRange = 5.0f;
+    mSensorInfo.resolution = 1.0f;
+    mSensorInfo.power = 0.012f;  // mA
+    mSensorInfo.minDelay = 200 * 1000;  // microseconds
+    mSensorInfo.maxDelay = kDefaultMaxDelayUs;
     mSensorInfo.fifoReservedEventCount = 0;
     mSensorInfo.fifoMaxEventCount = 0;
     mSensorInfo.requiredPermission = "";
     mSensorInfo.flags =
-        static_cast<uint32_t>(SensorFlagBits::WAKE_UP | SensorFlagBits::DATA_INJECTION);
+            static_cast<uint32_t>(SensorFlagBits::ON_CHANGE_MODE | SensorFlagBits::WAKE_UP);
 };
 
+GyroSensor::GyroSensor(int32_t sensorHandle, ISensorsEventCallback* callback) : Sensor(callback) {
+    mSensorInfo.sensorHandle = sensorHandle;
+    mSensorInfo.name = "Gyro Sensor";
+    mSensorInfo.vendor = "Vendor String";
+    mSensorInfo.version = 1;
+    mSensorInfo.type = SensorType::GYROSCOPE;
+    mSensorInfo.typeAsString = "";
+    mSensorInfo.maxRange = 1000.0f * M_PI / 180.0f;
+    mSensorInfo.resolution = 1000.0f * M_PI / (180.0f * 32768.0f);
+    mSensorInfo.power = 0.001f;
+    mSensorInfo.minDelay = 2.5f * 1000;  // microseconds
+    mSensorInfo.maxDelay = kDefaultMaxDelayUs;
+    mSensorInfo.fifoReservedEventCount = 0;
+    mSensorInfo.fifoMaxEventCount = 0;
+    mSensorInfo.requiredPermission = "";
+    mSensorInfo.flags = 0;
+};
+
+AmbientTempSensor::AmbientTempSensor(int32_t sensorHandle, ISensorsEventCallback* callback)
+    : OnChangeSensor(callback) {
+    mSensorInfo.sensorHandle = sensorHandle;
+    mSensorInfo.name = "Ambient Temp Sensor";
+    mSensorInfo.vendor = "Vendor String";
+    mSensorInfo.version = 1;
+    mSensorInfo.type = SensorType::AMBIENT_TEMPERATURE;
+    mSensorInfo.typeAsString = "";
+    mSensorInfo.maxRange = 80.0f;
+    mSensorInfo.resolution = 0.01f;
+    mSensorInfo.power = 0.001f;
+    mSensorInfo.minDelay = 40 * 1000;  // microseconds
+    mSensorInfo.maxDelay = kDefaultMaxDelayUs;
+    mSensorInfo.fifoReservedEventCount = 0;
+    mSensorInfo.fifoMaxEventCount = 0;
+    mSensorInfo.requiredPermission = "";
+    mSensorInfo.flags = static_cast<uint32_t>(SensorFlagBits::ON_CHANGE_MODE);
+};
+
+DeviceTempSensor::DeviceTempSensor(int32_t sensorHandle, ISensorsEventCallback* callback)
+    : OnChangeSensor(callback) {
+    mSensorInfo.sensorHandle = sensorHandle;
+    mSensorInfo.name = "Device Temp Sensor";
+    mSensorInfo.vendor = "Vendor String";
+    mSensorInfo.version = 1;
+    mSensorInfo.type = SensorType::TEMPERATURE;
+    mSensorInfo.typeAsString = "";
+    mSensorInfo.maxRange = 80.0f;
+    mSensorInfo.resolution = 0.01f;
+    mSensorInfo.power = 0.001f;
+    mSensorInfo.minDelay = 40 * 1000;  // microseconds
+    mSensorInfo.maxDelay = kDefaultMaxDelayUs;
+    mSensorInfo.fifoReservedEventCount = 0;
+    mSensorInfo.fifoMaxEventCount = 0;
+    mSensorInfo.requiredPermission = "";
+    mSensorInfo.flags = static_cast<uint32_t>(SensorFlagBits::ON_CHANGE_MODE);
+}
+
+RelativeHumiditySensor::RelativeHumiditySensor(int32_t sensorHandle,
+                                               ISensorsEventCallback* callback)
+    : OnChangeSensor(callback) {
+    mSensorInfo.sensorHandle = sensorHandle;
+    mSensorInfo.name = "Relative Humidity Sensor";
+    mSensorInfo.vendor = "Vendor String";
+    mSensorInfo.version = 1;
+    mSensorInfo.type = SensorType::RELATIVE_HUMIDITY;
+    mSensorInfo.typeAsString = "";
+    mSensorInfo.maxRange = 100.0f;
+    mSensorInfo.resolution = 0.1f;
+    mSensorInfo.power = 0.001f;
+    mSensorInfo.minDelay = 40 * 1000;  // microseconds
+    mSensorInfo.maxDelay = kDefaultMaxDelayUs;
+    mSensorInfo.fifoReservedEventCount = 0;
+    mSensorInfo.fifoMaxEventCount = 0;
+    mSensorInfo.requiredPermission = "";
+    mSensorInfo.flags = static_cast<uint32_t>(SensorFlagBits::ON_CHANGE_MODE);
+}
+
 }  // namespace implementation
 }  // namespace V2_0
 }  // namespace sensors
diff --git a/sensors/2.0/default/Sensor.h b/sensors/2.0/default/Sensor.h
index 3ab2299..61900fa 100644
--- a/sensors/2.0/default/Sensor.h
+++ b/sensors/2.0/default/Sensor.h
@@ -50,7 +50,7 @@
 
     const SensorInfo& getSensorInfo() const;
     void batch(int32_t samplingPeriodNs);
-    void activate(bool enable);
+    virtual void activate(bool enable);
     Result flush();
 
     void setOperationMode(OperationMode mode);
@@ -79,11 +79,65 @@
     OperationMode mMode;
 };
 
+class OnChangeSensor : public Sensor {
+   public:
+    OnChangeSensor(ISensorsEventCallback* callback);
+
+    virtual void activate(bool enable) override;
+
+   protected:
+    virtual std::vector<Event> readEvents() override;
+
+   protected:
+    Event mPreviousEvent;
+    bool mPreviousEventSet;
+};
+
 class AccelSensor : public Sensor {
    public:
     AccelSensor(int32_t sensorHandle, ISensorsEventCallback* callback);
 };
 
+class GyroSensor : public Sensor {
+   public:
+    GyroSensor(int32_t sensorHandle, ISensorsEventCallback* callback);
+};
+
+class AmbientTempSensor : public OnChangeSensor {
+   public:
+    AmbientTempSensor(int32_t sensorHandle, ISensorsEventCallback* callback);
+};
+
+class DeviceTempSensor : public OnChangeSensor {
+   public:
+    DeviceTempSensor(int32_t sensorHandle, ISensorsEventCallback* callback);
+};
+
+class PressureSensor : public Sensor {
+   public:
+    PressureSensor(int32_t sensorHandle, ISensorsEventCallback* callback);
+};
+
+class MagnetometerSensor : public Sensor {
+   public:
+    MagnetometerSensor(int32_t sensorHandle, ISensorsEventCallback* callback);
+};
+
+class LightSensor : public OnChangeSensor {
+   public:
+    LightSensor(int32_t sensorHandle, ISensorsEventCallback* callback);
+};
+
+class ProximitySensor : public OnChangeSensor {
+   public:
+    ProximitySensor(int32_t sensorHandle, ISensorsEventCallback* callback);
+};
+
+class RelativeHumiditySensor : public OnChangeSensor {
+   public:
+    RelativeHumiditySensor(int32_t sensorHandle, ISensorsEventCallback* callback);
+};
+
 }  // namespace implementation
 }  // namespace V2_0
 }  // namespace sensors
diff --git a/sensors/2.0/default/Sensors.cpp b/sensors/2.0/default/Sensors.cpp
index 15fe86f..23dd26b 100644
--- a/sensors/2.0/default/Sensors.cpp
+++ b/sensors/2.0/default/Sensors.cpp
@@ -37,13 +37,20 @@
 
 Sensors::Sensors()
     : mEventQueueFlag(nullptr),
+      mNextHandle(1),
       mOutstandingWakeUpEvents(0),
       mReadWakeLockQueueRun(false),
       mAutoReleaseWakeLockTime(0),
       mHasWakeLock(false) {
-    std::shared_ptr<AccelSensor> accel =
-        std::make_shared<AccelSensor>(1 /* sensorHandle */, this /* callback */);
-    mSensors[accel->getSensorInfo().sensorHandle] = accel;
+    AddSensor<AccelSensor>();
+    AddSensor<GyroSensor>();
+    AddSensor<AmbientTempSensor>();
+    AddSensor<DeviceTempSensor>();
+    AddSensor<PressureSensor>();
+    AddSensor<MagnetometerSensor>();
+    AddSensor<LightSensor>();
+    AddSensor<ProximitySensor>();
+    AddSensor<RelativeHumiditySensor>();
 }
 
 Sensors::~Sensors() {
diff --git a/sensors/2.0/default/Sensors.h b/sensors/2.0/default/Sensors.h
index eba3f97..d06dd78 100644
--- a/sensors/2.0/default/Sensors.h
+++ b/sensors/2.0/default/Sensors.h
@@ -87,6 +87,16 @@
 
    private:
     /**
+     * Add a new sensor
+     */
+    template <class SensorType>
+    void AddSensor() {
+        std::shared_ptr<SensorType> sensor =
+                std::make_shared<SensorType>(mNextHandle++ /* sensorHandle */, this /* callback */);
+        mSensors[sensor->getSensorInfo().sensorHandle] = sensor;
+    }
+
+    /**
      * Utility function to delete the Event Flag
      */
     void deleteEventFlag();
@@ -132,6 +142,11 @@
     std::map<int32_t, std::shared_ptr<Sensor>> mSensors;
 
     /**
+     * The next available sensor handle
+     */
+    int32_t mNextHandle;
+
+    /**
      * Lock to protect writes to the FMQs
      */
     std::mutex mWriteLock;
diff --git a/sensors/2.0/vts/functional/VtsHalSensorsV2_0TargetTest.cpp b/sensors/2.0/vts/functional/VtsHalSensorsV2_0TargetTest.cpp
index 4a1f8f1..39053fe 100644
--- a/sensors/2.0/vts/functional/VtsHalSensorsV2_0TargetTest.cpp
+++ b/sensors/2.0/vts/functional/VtsHalSensorsV2_0TargetTest.cpp
@@ -51,7 +51,7 @@
     }
 
     void onEvent(const ::android::hardware::sensors::V1_0::Event& event) override {
-        if (event.sensorType == SensorType::ADDITIONAL_INFO &&
+        if (event.sensorType == SensorType::META_DATA &&
             event.u.meta.what == MetaDataEventType::META_DATA_FLUSH_COMPLETE) {
             std::unique_lock<std::recursive_mutex> lock(mFlushMutex);
             mFlushMap[event.sensorHandle]++;
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
index c0af30b..e5762f2 100644
--- a/wifi/1.0/vts/functional/wifi_ap_iface_hidl_test.cpp
+++ b/wifi/1.0/vts/functional/wifi_ap_iface_hidl_test.cpp
@@ -29,17 +29,23 @@
 using ::android::hardware::wifi::V1_0::WifiStatusCode;
 using ::android::sp;
 
+extern WifiHidlEnvironment* gEnv;
+
 /**
  * Fixture to use for all AP Iface HIDL interface tests.
  */
 class WifiApIfaceHidlTest : public ::testing::VtsHalHidlTargetTestBase {
    public:
     virtual void SetUp() override {
+        if (!gEnv->isSoftApOn) return;
         wifi_ap_iface_ = getWifiApIface();
         ASSERT_NE(nullptr, wifi_ap_iface_.get());
     }
 
-    virtual void TearDown() override { stopWifi(); }
+    virtual void TearDown() override {
+        if (!gEnv->isSoftApOn) return;
+        stopWifi();
+    }
 
    protected:
     sp<IWifiApIface> wifi_ap_iface_;
@@ -51,6 +57,7 @@
  * successfully created.
  */
 TEST(WifiApIfaceHidlTestNoFixture, Create) {
+    if (!gEnv->isSoftApOn) return;
     EXPECT_NE(nullptr, getWifiApIface().get());
     stopWifi();
 }
@@ -60,6 +67,7 @@
  * Ensures that the correct interface type is returned for AP interface.
  */
 TEST_F(WifiApIfaceHidlTest, GetType) {
+    if (!gEnv->isSoftApOn) return;
     const auto& status_and_type = HIDL_INVOKE(wifi_ap_iface_, getType);
     EXPECT_EQ(WifiStatusCode::SUCCESS, status_and_type.first.code);
     EXPECT_EQ(IfaceType::AP, status_and_type.second);
@@ -71,6 +79,7 @@
  * status code.
  */
 TEST_F(WifiApIfaceHidlTest, SetCountryCode) {
+    if (!gEnv->isSoftApOn) return;
     const android::hardware::hidl_array<int8_t, 2> kCountryCode{
         std::array<int8_t, 2>{{0x55, 0x53}}};
     EXPECT_EQ(WifiStatusCode::SUCCESS,
@@ -82,6 +91,7 @@
  * Ensures that we can retrieve valid frequencies for 2.4 GHz band.
  */
 TEST_F(WifiApIfaceHidlTest, GetValidFrequenciesForBand) {
+    if (!gEnv->isSoftApOn) return;
     const auto& status_and_freqs = HIDL_INVOKE(
         wifi_ap_iface_, getValidFrequenciesForBand, WifiBand::BAND_24GHZ);
     EXPECT_EQ(WifiStatusCode::SUCCESS, status_and_freqs.first.code);
diff --git a/wifi/1.0/vts/functional/wifi_chip_hidl_test.cpp b/wifi/1.0/vts/functional/wifi_chip_hidl_test.cpp
index 3555c2e..72cafd1 100644
--- a/wifi/1.0/vts/functional/wifi_chip_hidl_test.cpp
+++ b/wifi/1.0/vts/functional/wifi_chip_hidl_test.cpp
@@ -365,6 +365,7 @@
  * succeeds. The 2nd iface creation should be rejected.
  */
 TEST_F(WifiChipHidlTest, CreateApIface) {
+    if (!gEnv->isSoftApOn) return;
     configureChipForIfaceType(IfaceType::AP, true);
 
     sp<IWifiApIface> iface;
@@ -381,6 +382,7 @@
  * iface name is returned via the list.
  */
 TEST_F(WifiChipHidlTest, GetApIfaceNames) {
+    if (!gEnv->isSoftApOn) return;
     configureChipForIfaceType(IfaceType::AP, true);
 
     const auto& status_and_iface_names1 =
@@ -413,6 +415,7 @@
  * doesn't retrieve an iface object.
  */
 TEST_F(WifiChipHidlTest, GetApIface) {
+    if (!gEnv->isSoftApOn) return;
     configureChipForIfaceType(IfaceType::AP, true);
 
     sp<IWifiApIface> ap_iface;
@@ -439,6 +442,7 @@
  * doesn't remove the iface.
  */
 TEST_F(WifiChipHidlTest, RemoveApIface) {
+    if (!gEnv->isSoftApOn) return;
     configureChipForIfaceType(IfaceType::AP, true);
 
     sp<IWifiApIface> ap_iface;
diff --git a/wifi/1.0/vts/functional/wifi_hidl_test_utils.h b/wifi/1.0/vts/functional/wifi_hidl_test_utils.h
index 2b1c8ec..d430ce0 100644
--- a/wifi/1.0/vts/functional/wifi_hidl_test_utils.h
+++ b/wifi/1.0/vts/functional/wifi_hidl_test_utils.h
@@ -58,26 +58,33 @@
    public:
     // Whether NaN feature is supported on the device.
     bool isNanOn = false;
+    // Whether SoftAp feature is supported on the device.
+    bool isSoftApOn = false;
 
     void usage(char* me, char* arg) {
         fprintf(stderr,
                 "unrecognized option: %s\n\n"
                 "usage: %s <gtest options> <test options>\n\n"
                 "test options are:\n\n"
-                "-N, --nan_on: Whether NAN feature is supported\n",
+                "-N, --nan_on: Whether NAN feature is supported\n"
+                "-S, --softap_on: Whether SOFTAP feature is supported\n",
                 arg, me);
     }
 
     int initFromOptions(int argc, char** argv) {
         static struct option options[] = {{"nan_on", no_argument, 0, 'N'},
+                                          {"softap_on", no_argument, 0, 'S'},
                                           {0, 0, 0, 0}};
 
         int c;
-        while ((c = getopt_long(argc, argv, "N", options, NULL)) >= 0) {
+        while ((c = getopt_long(argc, argv, "NS", options, NULL)) >= 0) {
             switch (c) {
                 case 'N':
                     isNanOn = true;
                     break;
+                case 'S':
+                    isSoftApOn = true;
+                    break;
                 default:
                     usage(argv[0], argv[optind]);
                     return 2;
diff --git a/wifi/hostapd/1.1/vts/functional/hostapd_hidl_test.cpp b/wifi/hostapd/1.1/vts/functional/hostapd_hidl_test.cpp
index d1af655..439a624 100644
--- a/wifi/hostapd/1.1/vts/functional/hostapd_hidl_test.cpp
+++ b/wifi/hostapd/1.1/vts/functional/hostapd_hidl_test.cpp
@@ -34,6 +34,14 @@
 using ::android::hardware::wifi::hostapd::V1_1::IHostapd;
 using ::android::hardware::wifi::hostapd::V1_1::IHostapdCallback;
 
+namespace {
+constexpr unsigned char kNwSsid[] = {'t', 'e', 's', 't', '1',
+                                     '2', '3', '4', '5'};
+constexpr char kNwPassphrase[] = "test12345";
+constexpr int kIfaceChannel = 6;
+constexpr int kIfaceInvalidChannel = 567;
+}  // namespace
+
 class HostapdHidlTest : public ::testing::VtsHalHidlTargetTestBase {
    public:
     virtual void SetUp() override {
@@ -45,6 +53,99 @@
     virtual void TearDown() override { stopHostapd(); }
 
    protected:
+    std::string getPrimaryWlanIfaceName() {
+        std::array<char, PROPERTY_VALUE_MAX> buffer;
+        property_get("wifi.interface", buffer.data(), "wlan0");
+        return buffer.data();
+    }
+
+    IHostapd::IfaceParams getIfaceParamsWithAcs() {
+        ::android::hardware::wifi::hostapd::V1_0::IHostapd::IfaceParams
+            iface_params;
+        IHostapd::IfaceParams iface_params_1_1;
+
+        iface_params.ifaceName = getPrimaryWlanIfaceName();
+        iface_params.hwModeParams.enable80211N = true;
+        iface_params.hwModeParams.enable80211AC = false;
+        iface_params.channelParams.enableAcs = true;
+        iface_params.channelParams.acsShouldExcludeDfs = true;
+        iface_params.channelParams.channel = 0;
+        iface_params.channelParams.band = IHostapd::Band::BAND_ANY;
+        iface_params_1_1.V1_0 = iface_params;
+        return iface_params_1_1;
+    }
+
+    IHostapd::IfaceParams getIfaceParamsWithAcsAndChannelRange() {
+        IHostapd::IfaceParams iface_params_1_1 = getIfaceParamsWithAcs();
+        IHostapd::ChannelParams channelParams;
+        IHostapd::AcsChannelRange acsChannelRange;
+        acsChannelRange.start = 1;
+        acsChannelRange.end = 11;
+        std::vector<IHostapd::AcsChannelRange> vec_acsChannelRange;
+        vec_acsChannelRange.push_back(acsChannelRange);
+        channelParams.acsChannelRanges = vec_acsChannelRange;
+        iface_params_1_1.channelParams = channelParams;
+        return iface_params_1_1;
+    }
+
+    IHostapd::IfaceParams getIfaceParamsWithAcsAndInvalidChannelRange() {
+        IHostapd::IfaceParams iface_params_1_1 =
+            getIfaceParamsWithAcsAndChannelRange();
+        iface_params_1_1.channelParams.acsChannelRanges[0].start = 222;
+        iface_params_1_1.channelParams.acsChannelRanges[0].end = 999;
+        return iface_params_1_1;
+    }
+
+    IHostapd::IfaceParams getIfaceParamsWithoutAcs() {
+        ::android::hardware::wifi::hostapd::V1_0::IHostapd::IfaceParams
+            iface_params;
+        IHostapd::IfaceParams iface_params_1_1;
+
+        iface_params.ifaceName = getPrimaryWlanIfaceName();
+        iface_params.hwModeParams.enable80211N = true;
+        iface_params.hwModeParams.enable80211AC = false;
+        iface_params.channelParams.enableAcs = false;
+        iface_params.channelParams.acsShouldExcludeDfs = false;
+        iface_params.channelParams.channel = kIfaceChannel;
+        iface_params.channelParams.band = IHostapd::Band::BAND_2_4_GHZ;
+        iface_params_1_1.V1_0 = iface_params;
+        return iface_params_1_1;
+    }
+
+    IHostapd::IfaceParams getIfaceParamsWithInvalidChannel() {
+        IHostapd::IfaceParams iface_params_1_1 = getIfaceParamsWithoutAcs();
+        iface_params_1_1.V1_0.channelParams.channel = kIfaceInvalidChannel;
+        return iface_params_1_1;
+    }
+
+    IHostapd::NetworkParams getPskNwParams() {
+        IHostapd::NetworkParams nw_params;
+        nw_params.ssid =
+            std::vector<uint8_t>(kNwSsid, kNwSsid + sizeof(kNwSsid));
+        nw_params.isHidden = false;
+        nw_params.encryptionType = IHostapd::EncryptionType::WPA2;
+        nw_params.pskPassphrase = kNwPassphrase;
+        return nw_params;
+    }
+
+    IHostapd::NetworkParams getInvalidPskNwParams() {
+        IHostapd::NetworkParams nw_params;
+        nw_params.ssid =
+            std::vector<uint8_t>(kNwSsid, kNwSsid + sizeof(kNwSsid));
+        nw_params.isHidden = false;
+        nw_params.encryptionType = IHostapd::EncryptionType::WPA2;
+        return nw_params;
+    }
+
+    IHostapd::NetworkParams getOpenNwParams() {
+        IHostapd::NetworkParams nw_params;
+        nw_params.ssid =
+            std::vector<uint8_t>(kNwSsid, kNwSsid + sizeof(kNwSsid));
+        nw_params.isHidden = false;
+        nw_params.encryptionType = IHostapd::EncryptionType::NONE;
+        return nw_params;
+    }
+
     // IHostapd object used for all tests in this fixture.
     sp<IHostapd> hostapd_;
 };
@@ -65,3 +166,113 @@
             EXPECT_EQ(HostapdStatusCode::SUCCESS, status.code);
         });
 }
+
+/**
+ * Adds an access point with PSK network config & ACS enabled.
+ * Access point creation should pass.
+ */
+TEST_F(HostapdHidlTest, AddPskAccessPointWithAcs) {
+    auto status = HIDL_INVOKE(hostapd_, addAccessPoint_1_1,
+                              getIfaceParamsWithAcs(), getPskNwParams());
+    EXPECT_EQ(HostapdStatusCode::SUCCESS, status.code);
+}
+
+/**
+ * Adds an access point with PSK network config, ACS enabled & channel Range.
+ * Access point creation should pass.
+ */
+TEST_F(HostapdHidlTest, AddPskAccessPointWithAcsAndChannelRange) {
+    auto status =
+        HIDL_INVOKE(hostapd_, addAccessPoint_1_1,
+                    getIfaceParamsWithAcsAndChannelRange(), getPskNwParams());
+    EXPECT_EQ(HostapdStatusCode::SUCCESS, status.code);
+}
+
+/**
+ * Adds an access point with invalid channel range.
+ * Access point creation should fail.
+ */
+TEST_F(HostapdHidlTest, AddPskAccessPointWithAcsAndInvalidChannelRange) {
+    auto status = HIDL_INVOKE(hostapd_, addAccessPoint_1_1,
+                              getIfaceParamsWithAcsAndInvalidChannelRange(),
+                              getPskNwParams());
+    EXPECT_NE(HostapdStatusCode::SUCCESS, status.code);
+}
+
+/**
+ * Adds an access point with Open network config & ACS enabled.
+ * Access point creation should pass.
+ */
+TEST_F(HostapdHidlTest, AddOpenAccessPointWithAcs) {
+    auto status = HIDL_INVOKE(hostapd_, addAccessPoint_1_1,
+                              getIfaceParamsWithAcs(), getOpenNwParams());
+    EXPECT_EQ(HostapdStatusCode::SUCCESS, status.code);
+}
+
+/**
+ * Adds an access point with PSK network config & ACS disabled.
+ * Access point creation should pass.
+ */
+TEST_F(HostapdHidlTest, AddPskAccessPointWithoutAcs) {
+    auto status = HIDL_INVOKE(hostapd_, addAccessPoint_1_1,
+                              getIfaceParamsWithoutAcs(), getPskNwParams());
+    EXPECT_EQ(HostapdStatusCode::SUCCESS, status.code);
+}
+
+/**
+ * Adds an access point with Open network config & ACS disabled.
+ * Access point creation should pass.
+ */
+TEST_F(HostapdHidlTest, AddOpenAccessPointWithoutAcs) {
+    auto status = HIDL_INVOKE(hostapd_, addAccessPoint_1_1,
+                              getIfaceParamsWithoutAcs(), getOpenNwParams());
+    EXPECT_EQ(HostapdStatusCode::SUCCESS, status.code);
+}
+
+/**
+ * Adds & then removes an access point with PSK network config & ACS enabled.
+ * Access point creation & removal should pass.
+ */
+TEST_F(HostapdHidlTest, RemoveAccessPointWithAcs) {
+    auto status = HIDL_INVOKE(hostapd_, addAccessPoint_1_1,
+                              getIfaceParamsWithAcs(), getPskNwParams());
+    EXPECT_EQ(HostapdStatusCode::SUCCESS, status.code);
+    status =
+        HIDL_INVOKE(hostapd_, removeAccessPoint, getPrimaryWlanIfaceName());
+    EXPECT_EQ(HostapdStatusCode::SUCCESS, status.code);
+}
+
+/**
+ * Adds & then removes an access point with PSK network config & ACS disabled.
+ * Access point creation & removal should pass.
+ */
+TEST_F(HostapdHidlTest, RemoveAccessPointWithoutAcs) {
+    auto status = HIDL_INVOKE(hostapd_, addAccessPoint_1_1,
+                              getIfaceParamsWithoutAcs(), getPskNwParams());
+    EXPECT_EQ(HostapdStatusCode::SUCCESS, status.code);
+    status =
+        HIDL_INVOKE(hostapd_, removeAccessPoint, getPrimaryWlanIfaceName());
+    EXPECT_EQ(HostapdStatusCode::SUCCESS, status.code);
+}
+
+/**
+ * Adds an access point with invalid channel.
+ * Access point creation should fail.
+ */
+TEST_F(HostapdHidlTest, AddPskAccessPointWithInvalidChannel) {
+    auto status =
+        HIDL_INVOKE(hostapd_, addAccessPoint_1_1,
+                    getIfaceParamsWithInvalidChannel(), getPskNwParams());
+    EXPECT_NE(HostapdStatusCode::SUCCESS, status.code);
+}
+
+/**
+ * Adds an access point with invalid PSK network config.
+ * Access point creation should fail.
+ */
+TEST_F(HostapdHidlTest, AddInvalidPskAccessPointWithoutAcs) {
+    auto status =
+        HIDL_INVOKE(hostapd_, addAccessPoint_1_1, getIfaceParamsWithoutAcs(),
+                    getInvalidPskNwParams());
+    EXPECT_NE(HostapdStatusCode::SUCCESS, status.code);
+}