Merge "Properly append META_DATA event on flush"
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/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/biometrics/face/1.0/types.hal b/biometrics/face/1.0/types.hal
index 2bcd3d5..89e809b 100644
--- a/biometrics/face/1.0/types.hal
+++ b/biometrics/face/1.0/types.hal
@@ -324,9 +324,19 @@
     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 = 20
+    VENDOR = 21
 };
 
 /**
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/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/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/GeneratedTestHarness.cpp b/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.cpp
index b7a6f3f..2e13854 100644
--- a/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.cpp
+++ b/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.cpp
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+#include "GeneratedTestHarness.h"
 #include "Callbacks.h"
 #include "ExecutionBurstController.h"
 #include "TestHarness.h"
@@ -120,13 +121,14 @@
     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,
-                           Executor executor, MeasureTiming measure, bool testDynamicOutputShape) {
+                           Executor executor, MeasureTiming measure, OutputType outputType) {
     const uint32_t INPUT = 0;
     const uint32_t OUTPUT = 1;
 
@@ -174,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 = {},
@@ -183,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;
@@ -277,15 +294,15 @@
             }
         }
 
-        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);
@@ -295,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;
@@ -324,9 +360,54 @@
 void EvaluatePreparedModel(sp<T_IPreparedModel>& preparedModel, std::function<bool(int)> is_ignored,
                            const std::vector<MixedTypedExample>& examples,
                            bool hasRelaxedFloat32Model, Executor executor, MeasureTiming measure,
-                           bool testDynamicOutputShape) {
+                           OutputType outputType) {
     EvaluatePreparedModel(preparedModel, is_ignored, examples, hasRelaxedFloat32Model, kDefaultAtol,
-                          kDefaultRtol, executor, 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,
@@ -383,7 +464,7 @@
     float fpAtol = 1e-5f, fpRtol = 5.0f * 1.1920928955078125e-7f;
     EvaluatePreparedModel(preparedModel, is_ignored, examples,
                           /*hasRelaxedFloat32Model=*/false, fpAtol, fpRtol, Executor::ASYNC,
-                          MeasureTiming::NO, /*testDynamicOutputShape=*/false);
+                          MeasureTiming::NO, OutputType::FULLY_SPECIFIED);
 }
 
 void Execute(const sp<V1_1::IDevice>& device, std::function<V1_1::Model(void)> create_model,
@@ -430,15 +511,11 @@
 
     EvaluatePreparedModel(preparedModel, is_ignored, examples,
                           model.relaxComputationFloat32toFloat16, 1e-5f, 1e-5f, Executor::ASYNC,
-                          MeasureTiming::NO, /*testDynamicOutputShape=*/false);
+                          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(
@@ -461,12 +538,11 @@
     // 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 "
@@ -475,26 +551,18 @@
         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, Executor::ASYNC,
-                          MeasureTiming::NO, testDynamicOutputShape);
-    EvaluatePreparedModel(preparedModel, is_ignored, examples,
-                          model.relaxComputationFloat32toFloat16, Executor::SYNC, MeasureTiming::NO,
-                          testDynamicOutputShape);
-    EvaluatePreparedModel(preparedModel, is_ignored, examples,
-                          model.relaxComputationFloat32toFloat16, Executor::BURST,
-                          MeasureTiming::NO, testDynamicOutputShape);
-    EvaluatePreparedModel(preparedModel, is_ignored, examples,
-                          model.relaxComputationFloat32toFloat16, Executor::ASYNC,
-                          MeasureTiming::YES, testDynamicOutputShape);
-    EvaluatePreparedModel(preparedModel, is_ignored, examples,
-                          model.relaxComputationFloat32toFloat16, Executor::SYNC,
-                          MeasureTiming::YES, testDynamicOutputShape);
-    EvaluatePreparedModel(preparedModel, is_ignored, examples,
-                          model.relaxComputationFloat32toFloat16, Executor::BURST,
-                          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 de249b0..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
diff --git a/neuralnetworks/1.2/types.hal b/neuralnetworks/1.2/types.hal
index 4d5f0f4..2e48ba0 100644
--- a/neuralnetworks/1.2/types.hal
+++ b/neuralnetworks/1.2/types.hal
@@ -47,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. */
@@ -73,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, ...] =
@@ -96,6 +97,16 @@
      * 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::FUNDAMENTAL_MAX.
      */
@@ -108,10 +119,12 @@
  * The range of operand values in the OperandType enum.
  */
 enum OperandTypeRange : uint32_t {
+    BASE_MIN        = 0,
     FUNDAMENTAL_MIN = 0,
-    FUNDAMENTAL_MAX = 12,
-    OEM_MIN     = 10000,
-    OEM_MAX     = 10001,
+    FUNDAMENTAL_MAX = 13,
+    OEM_MIN         = 10000,
+    OEM_MAX         = 10001,
+    BASE_MAX        = 0xFFFF,
 };
 
 /**
@@ -189,10 +202,12 @@
  * The range of values in the OperationType enum.
  */
 enum OperationTypeRange : uint32_t {
+    BASE_MIN        = 0,
     FUNDAMENTAL_MIN = 0,
     FUNDAMENTAL_MAX = 93,
-    OEM_MIN = 10000,
-    OEM_MAX = 10000,
+    OEM_MIN         = 10000,
+    OEM_MAX         = 10000,
+    BASE_MAX        = 0xFFFF,
 };
 
 /**
@@ -221,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;
 
@@ -247,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;
 
@@ -351,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;
 };
 
@@ -432,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,
+    };
 };
 
 /**
@@ -685,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 1bbb203..a0f11eb 100644
--- a/neuralnetworks/1.2/vts/functional/ValidateModel.cpp
+++ b/neuralnetworks/1.2/vts/functional/ValidateModel.cpp
@@ -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 =
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.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 e8067d0..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),
@@ -202,7 +206,7 @@
     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 = "";
@@ -218,10 +222,10 @@
     mSensorInfo.type = SensorType::PRESSURE;
     mSensorInfo.typeAsString = "";
     mSensorInfo.maxRange = 1100.0f;   // hPa
-    mSensorInfo.resolution = 1.0f;    // hPa
+    mSensorInfo.resolution = 0.005f;  // hPa
     mSensorInfo.power = 0.001f;       // mA
-    mSensorInfo.minDelay = 28571.0f;  // microseconds
-    mSensorInfo.maxDelay = 0.0f;      // microseconds
+    mSensorInfo.minDelay = 100 * 1000;  // microseconds
+    mSensorInfo.maxDelay = kDefaultMaxDelayUs;
     mSensorInfo.fifoReservedEventCount = 0;
     mSensorInfo.fifoMaxEventCount = 0;
     mSensorInfo.requiredPermission = "";
@@ -236,11 +240,11 @@
     mSensorInfo.version = 1;
     mSensorInfo.type = SensorType::MAGNETIC_FIELD;
     mSensorInfo.typeAsString = "";
-    mSensorInfo.maxRange = 4911.0f;
-    mSensorInfo.resolution = 1.00f;
+    mSensorInfo.maxRange = 1300.0f;
+    mSensorInfo.resolution = 0.01f;
     mSensorInfo.power = 0.001f;       // mA
-    mSensorInfo.minDelay = 14284.0f;  // microseconds
-    mSensorInfo.maxDelay = 0.0f;      // microseconds
+    mSensorInfo.minDelay = 20 * 1000;  // microseconds
+    mSensorInfo.maxDelay = kDefaultMaxDelayUs;
     mSensorInfo.fifoReservedEventCount = 0;
     mSensorInfo.fifoMaxEventCount = 0;
     mSensorInfo.requiredPermission = "";
@@ -255,11 +259,11 @@
     mSensorInfo.version = 1;
     mSensorInfo.type = SensorType::LIGHT;
     mSensorInfo.typeAsString = "";
-    mSensorInfo.maxRange = 10000.0f;
+    mSensorInfo.maxRange = 43000.0f;
     mSensorInfo.resolution = 10.0f;
     mSensorInfo.power = 0.001f;           // mA
-    mSensorInfo.minDelay = 20.0f * 1000;  // microseconds
-    mSensorInfo.maxDelay = 0;             // microseconds
+    mSensorInfo.minDelay = 200 * 1000;    // microseconds
+    mSensorInfo.maxDelay = kDefaultMaxDelayUs;
     mSensorInfo.fifoReservedEventCount = 0;
     mSensorInfo.fifoMaxEventCount = 0;
     mSensorInfo.requiredPermission = "";
@@ -277,8 +281,8 @@
     mSensorInfo.maxRange = 5.0f;
     mSensorInfo.resolution = 1.0f;
     mSensorInfo.power = 0.012f;  // mA
-    mSensorInfo.minDelay = 500;  // microseconds
-    mSensorInfo.maxDelay = 2 * mSensorInfo.minDelay;
+    mSensorInfo.minDelay = 200 * 1000;  // microseconds
+    mSensorInfo.maxDelay = kDefaultMaxDelayUs;
     mSensorInfo.fifoReservedEventCount = 0;
     mSensorInfo.fifoMaxEventCount = 0;
     mSensorInfo.requiredPermission = "";
@@ -293,11 +297,11 @@
     mSensorInfo.version = 1;
     mSensorInfo.type = SensorType::GYROSCOPE;
     mSensorInfo.typeAsString = "";
-    mSensorInfo.maxRange = 8.726639f;
-    mSensorInfo.resolution = 1.0f;
+    mSensorInfo.maxRange = 1000.0f * M_PI / 180.0f;
+    mSensorInfo.resolution = 1000.0f * M_PI / (180.0f * 32768.0f);
     mSensorInfo.power = 0.001f;
-    mSensorInfo.minDelay = 4444;  // microseonds
-    mSensorInfo.maxDelay = 0;     // microseconds
+    mSensorInfo.minDelay = 2.5f * 1000;  // microseconds
+    mSensorInfo.maxDelay = kDefaultMaxDelayUs;
     mSensorInfo.fifoReservedEventCount = 0;
     mSensorInfo.fifoMaxEventCount = 0;
     mSensorInfo.requiredPermission = "";
@@ -313,10 +317,10 @@
     mSensorInfo.type = SensorType::AMBIENT_TEMPERATURE;
     mSensorInfo.typeAsString = "";
     mSensorInfo.maxRange = 80.0f;
-    mSensorInfo.resolution = 1.0f;
+    mSensorInfo.resolution = 0.01f;
     mSensorInfo.power = 0.001f;
-    mSensorInfo.minDelay = 4444;  // microseonds
-    mSensorInfo.maxDelay = 0;     // microseconds
+    mSensorInfo.minDelay = 40 * 1000;  // microseconds
+    mSensorInfo.maxDelay = kDefaultMaxDelayUs;
     mSensorInfo.fifoReservedEventCount = 0;
     mSensorInfo.fifoMaxEventCount = 0;
     mSensorInfo.requiredPermission = "";
@@ -332,10 +336,10 @@
     mSensorInfo.type = SensorType::TEMPERATURE;
     mSensorInfo.typeAsString = "";
     mSensorInfo.maxRange = 80.0f;
-    mSensorInfo.resolution = 1.0f;
+    mSensorInfo.resolution = 0.01f;
     mSensorInfo.power = 0.001f;
-    mSensorInfo.minDelay = 4444;  // microseonds
-    mSensorInfo.maxDelay = 0;     // microseconds
+    mSensorInfo.minDelay = 40 * 1000;  // microseconds
+    mSensorInfo.maxDelay = kDefaultMaxDelayUs;
     mSensorInfo.fifoReservedEventCount = 0;
     mSensorInfo.fifoMaxEventCount = 0;
     mSensorInfo.requiredPermission = "";
@@ -352,10 +356,10 @@
     mSensorInfo.type = SensorType::RELATIVE_HUMIDITY;
     mSensorInfo.typeAsString = "";
     mSensorInfo.maxRange = 100.0f;
-    mSensorInfo.resolution = 1.0f;
+    mSensorInfo.resolution = 0.1f;
     mSensorInfo.power = 0.001f;
-    mSensorInfo.minDelay = 4444;  // microseonds
-    mSensorInfo.maxDelay = 0;     // microseconds
+    mSensorInfo.minDelay = 40 * 1000;  // microseconds
+    mSensorInfo.maxDelay = kDefaultMaxDelayUs;
     mSensorInfo.fifoReservedEventCount = 0;
     mSensorInfo.fifoMaxEventCount = 0;
     mSensorInfo.requiredPermission = "";
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);
+}